import { useState } from 'react';
import { Link } from 'react-router-dom';
import {
  useIntegrations,
  useOffice365TasksFlat,
  useCrmOpenTasks,
  usePushTaskToO365,
  useCompleteO365Task,
  useCompleteCrmTask,
} from '../crm/hooks';
import type { M365TaskFlat, CrmOpenTask } from '../crm/types';
import styles from './DashboardTasksTab.module.css';

// ── CRM-Sync-Marker Regex ────────────────────────────────────────────────────

const CRM_MARKER_RE = /\[INSIGHT_CRM:([^\]]+)\]/;

function extractCrmId(body: string | null | undefined): string | null {
  if (!body) return null;
  const m = CRM_MARKER_RE.exec(body);
  return m ? m[1] : null;
}

// ── Typen für die vereinheitlichte Liste ─────────────────────────────────────

type TaskSource = 'o365' | 'crm' | 'synced';

interface UnifiedTask {
  key: string;
  source: TaskSource;
  title: string;
  dueDate: string | null;
  contactLabel: string | null;
  contactId: string | null;
  companyLabel: string | null;
  companyId: string | null;
  importance?: 'low' | 'normal' | 'high';
  // O365-spezifisch
  o365ListId?: string;
  o365TaskId?: string;
  // CRM-spezifisch
  crmActivityId?: string;
  crmType?: 'TASK' | 'FOLLOWUP';
}

// ── Datum formatieren ────────────────────────────────────────────────────────

function formatDue(isoOrDateTime: string | null): string | null {
  if (!isoOrDateTime) return null;
  try {
    const d = new Date(isoOrDateTime);
    const today = new Date();
    const todayStr = today.toISOString().slice(0, 10);
    const dStr = d.toISOString().slice(0, 10);
    const tomorrow = new Date(today.getTime() + 86_400_000).toISOString().slice(0, 10);

    if (dStr === todayStr) return 'Heute';
    if (dStr === tomorrow) return 'Morgen';
    if (dStr < todayStr) {
      const days = Math.round((today.getTime() - d.getTime()) / 86_400_000);
      return `Überfällig (${days}d)`;
    }
    return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
  } catch {
    return null;
  }
}

function isDue(isoOrDateTime: string | null): boolean {
  if (!isoOrDateTime) return false;
  try {
    const d = new Date(isoOrDateTime);
    return d < new Date();
  } catch {
    return false;
  }
}

// ── Source-Badge ─────────────────────────────────────────────────────────────

function SourceBadge({ source }: { source: TaskSource }) {
  return (
    <span className={styles.badgeGroup}>
      {(source === 'o365' || source === 'synced') && (
        <span className={`${styles.badge} ${styles.badgeO365}`}>O365</span>
      )}
      {(source === 'crm' || source === 'synced') && (
        <span className={`${styles.badge} ${styles.badgeCrm}`}>CRM</span>
      )}
    </span>
  );
}

// ── Einzelne Aufgaben-Zeile ───────────────────────────────────────────────────

function TaskRow({
  task,
  onComplete,
  onPushToO365,
  isPushPending,
  isCompletePending,
  isO365Connected,
}: {
  task: UnifiedTask;
  onComplete: (t: UnifiedTask) => void;
  onPushToO365: (t: UnifiedTask) => void;
  isPushPending: boolean;
  isCompletePending: boolean;
  isO365Connected: boolean;
}) {
  const overdue = isDue(task.dueDate);
  const dueFmt = formatDue(task.dueDate);

  return (
    <div
      className={`${styles.taskRow} ${styles[`taskRow_${task.source}`]}`}
    >
      <SourceBadge source={task.source} />

      <div className={styles.taskMain}>
        <span className={styles.taskTitle}>{task.title}</span>

        <div className={styles.taskMeta}>
          {task.contactLabel && task.contactId && (
            <Link
              to={`/crm/contacts/${task.contactId}`}
              className={styles.taskMetaLink}
            >
              {task.contactLabel}
            </Link>
          )}
          {task.companyLabel && task.companyId && (
            <Link
              to={`/crm/companies/${task.companyId}`}
              className={styles.taskMetaLink}
            >
              {task.companyLabel}
            </Link>
          )}
          {dueFmt && (
            <span className={`${styles.taskDue} ${overdue ? styles.taskDueOverdue : ''}`}>
              {dueFmt}
            </span>
          )}
          {task.importance === 'high' && (
            <span className={styles.taskImportance}>!</span>
          )}
        </div>
      </div>

      <div className={styles.taskActions}>
        {/* CRM-Aufgabe in O365 übernehmen */}
        {task.source === 'crm' && isO365Connected && (
          <button
            type="button"
            className={styles.actionPush}
            onClick={() => onPushToO365(task)}
            disabled={isPushPending}
            title="In Microsoft 365 übernehmen"
          >
            {isPushPending ? '…' : '→ O365'}
          </button>
        )}

        {/* Erledigen */}
        <button
          type="button"
          className={styles.actionComplete}
          onClick={() => onComplete(task)}
          disabled={isCompletePending}
          title="Als erledigt markieren"
        >
          {isCompletePending ? '…' : '✓'}
        </button>
      </div>
    </div>
  );
}

// ── Hauptkomponente ───────────────────────────────────────────────────────────

export function DashboardTasksTab() {
  const { data: integrationsData } = useIntegrations();
  const isO365Connected =
    integrationsData?.data?.some(
      (i) => i.provider === 'MICROSOFT_365' && i.connected,
    ) ?? false;

  const { data: o365Data, isLoading: o365Loading } = useOffice365TasksFlat();
  const { data: crmData, isLoading: crmLoading } = useCrmOpenTasks();

  const pushMutation = usePushTaskToO365();
  const completeO365 = useCompleteO365Task();
  const completeCrm = useCompleteCrmTask();

  // IDs, auf denen gerade eine Aktion läuft
  const [pendingComplete, setPendingComplete] = useState<string | null>(null);
  const [pendingPush, setPendingPush] = useState<string | null>(null);

  // ── Unified list aufbauen ────────────────────────────────────────────────

  const o365Tasks: M365TaskFlat[] = o365Data?.data ?? [];
  const crmTasks: CrmOpenTask[] = crmData?.data ?? [];

  // CRM-IDs, die bereits in einer O365-Aufgabe verknüpft sind
  const syncedCrmIds = new Set<string>();
  for (const t of o365Tasks) {
    const crmId = extractCrmId(t.bodyContent);
    if (crmId) syncedCrmIds.add(crmId);
  }

  const unified: UnifiedTask[] = [];

  // O365-Aufgaben (inkl. synced)
  for (const t of o365Tasks) {
    const crmId = extractCrmId(t.bodyContent);
    const crmActivity = crmId
      ? crmTasks.find((c) => c.id === crmId) ?? null
      : null;

    const source: TaskSource = crmId ? 'synced' : 'o365';

    unified.push({
      key: `o365-${t.id}`,
      source,
      title: t.title,
      dueDate: t.dueDateTime?.dateTime ?? null,
      importance: t.importance as 'low' | 'normal' | 'high',
      contactLabel: crmActivity?.contact
        ? (`${crmActivity.contact.firstName ?? ''} ${crmActivity.contact.lastName ?? ''}`.trim() ||
            crmActivity.contact.companyName) ?? null
        : null,
      contactId: crmActivity?.contactId ?? null,
      companyLabel: crmActivity?.company?.name ?? null,
      companyId: crmActivity?.companyId ?? null,
      o365ListId: t.listId,
      o365TaskId: t.id,
      crmActivityId: crmId ?? undefined,
    });
  }

  // CRM-Aufgaben, die NICHT in O365 synchronisiert sind
  for (const c of crmTasks) {
    if (syncedCrmIds.has(c.id)) continue;

    const contactLabel = c.contact
      ? (`${c.contact.firstName ?? ''} ${c.contact.lastName ?? ''}`.trim() ||
          c.contact.companyName) ?? null
      : null;

    unified.push({
      key: `crm-${c.id}`,
      source: 'crm',
      title: c.subject,
      dueDate: c.scheduledAt,
      contactLabel,
      contactId: c.contactId,
      companyLabel: c.company?.name ?? null,
      companyId: c.companyId,
      crmActivityId: c.id,
      crmType: c.type,
    });
  }

  // Sortierung: Überfällige zuerst, dann nach Datum, dann Rest
  unified.sort((a, b) => {
    const aOver = a.dueDate && isDue(a.dueDate);
    const bOver = b.dueDate && isDue(b.dueDate);
    if (aOver && !bOver) return -1;
    if (!aOver && bOver) return 1;
    if (a.dueDate && b.dueDate) return a.dueDate.localeCompare(b.dueDate);
    if (a.dueDate) return -1;
    if (b.dueDate) return 1;
    return 0;
  });

  // ── Event-Handler ────────────────────────────────────────────────────────

  function handleComplete(task: UnifiedTask) {
    setPendingComplete(task.key);

    const promises: Promise<unknown>[] = [];

    if (task.o365TaskId && task.o365ListId) {
      promises.push(
        completeO365.mutateAsync({ listId: task.o365ListId, taskId: task.o365TaskId }),
      );
    }
    if (task.crmActivityId) {
      promises.push(completeCrm.mutateAsync(task.crmActivityId));
    }

    Promise.allSettled(promises).finally(() => setPendingComplete(null));
  }

  function handlePushToO365(task: UnifiedTask) {
    if (!task.crmActivityId) return;
    setPendingPush(task.key);

    const crmActivity = crmTasks.find((c) => c.id === task.crmActivityId);
    const dueDateISO = crmActivity?.scheduledAt ?? undefined;

    pushMutation
      .mutateAsync({
        title: task.title,
        bodyContent: `[INSIGHT_CRM:${task.crmActivityId}] ${crmActivity?.description ?? ''}`.trim(),
        dueDateISO: dueDateISO ?? undefined,
      })
      .finally(() => setPendingPush(null));
  }

  // ── Render ───────────────────────────────────────────────────────────────

  const isLoading = (isO365Connected && o365Loading) || crmLoading;

  return (
    <div className={styles.root}>
      {/* Header */}
      <div className={styles.header}>
        <h2 className={styles.title}>Aufgaben</h2>
        <div className={styles.legend}>
          <span className={`${styles.badge} ${styles.badgeO365}`}>O365</span>
          <span className={styles.legendLabel}>Microsoft 365</span>
          <span className={`${styles.badge} ${styles.badgeCrm}`}>CRM</span>
          <span className={styles.legendLabel}>CRM-Aktivität</span>
        </div>
      </div>

      {isLoading && (
        <p className={styles.status}>Aufgaben werden geladen…</p>
      )}

      {!isLoading && unified.length === 0 && (
        <div className={styles.empty}>
          <span className={styles.emptyIcon}>✅</span>
          <p className={styles.emptyTitle}>Keine offenen Aufgaben</p>
          <p className={styles.emptySub}>
            {isO365Connected
              ? 'Alle Aufgaben aus CRM und Microsoft 365 sind erledigt.'
              : 'Alle CRM-Aufgaben sind erledigt. Microsoft 365 nicht verbunden.'}
          </p>
        </div>
      )}

      {!isLoading && unified.length > 0 && (
        <div className={styles.list}>
          {unified.map((task) => (
            <TaskRow
              key={task.key}
              task={task}
              onComplete={handleComplete}
              onPushToO365={handlePushToO365}
              isPushPending={pendingPush === task.key}
              isCompletePending={pendingComplete === task.key}
              isO365Connected={isO365Connected}
            />
          ))}
        </div>
      )}

      {!isO365Connected && (
        <p className={styles.hint}>
          💡 Verbinden Sie{' '}
          <a href="/settings" className={styles.hintLink}>
            Microsoft 365
          </a>{' '}
          um auch To-Do-Aufgaben anzuzeigen.
        </p>
      )}
    </div>
  );
}
