'use client';

/**
 * Drawer mit Recipient-Detail + chronologischer Event-Timeline (Phase 2).
 *
 * Mount-Pattern: Fixed-Position right-side, Backdrop schließt bei Klick außerhalb.
 * Render erst wenn `recipientId` gesetzt — vorher Null-Return (kein DOM).
 *
 * Datenquelle: GET /api/recipients/[id]/timeline
 *
 * Lifeline-Layout: vertikale Liste, Email-Events visuell von Onsite-Events
 * unterscheidbar (Icon + Farbe). Bei MPP-Open ein dezenter Hinweis.
 */

import { useCallback, useEffect, useState, type ReactNode } from 'react';
import {
  AlertOctagon,
  AlertTriangle,
  BadgeEuro,
  Eye,
  EyeOff,
  Loader2,
  MailCheck,
  MailX,
  MousePointerClick,
  ShoppingCart,
  FileText,
  ScrollText,
  Clock,
  Globe,
  Sparkles,
  X,
  ChevronDown,
  ChevronUp,
  UserCircle2,
  ExternalLink,
  Database,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { Ga4SessionPanel } from './Ga4SessionPanel';

interface TimelineEvent {
  id: string;
  source: 'email' | 'onsite' | 'crm';
  type: string;
  ts: string;
  meta: {
    linkUrl?: string;
    isMpp?: boolean;
    productId?: string;
    value?: number;
    scrollPct?: number;
    durationMs?: number;
    url?: string;
    source?: string;
  };
}

interface RecipientDetail {
  id: string;
  email: string;
  firstName: string | null;
  lastName: string | null;
  variantId: string | null;
  variantLabel: string | null;
  deliveredAt: string | null;
  firstOpenAt: string | null;
  firstClickAt: string | null;
  bounceAt: string | null;
  unsubscribedAt: string | null;
  conversionCount: number;
  conversionValueTotal: number;
  openCount: number;
  clickCount: number;
  behaviorCount: number;
  isMppOnly: boolean;
  lastEventAt: string | null;
  status: string;
  campaignId: string;
  campaignName: string;
  workspaceSlug: string;
  brandName: string;
  customDataJson: Record<string, unknown> | null;
  crmId: string | null;
}

interface TimelineResponse {
  ok: boolean;
  detail: RecipientDetail;
  events: TimelineEvent[];
}

export interface RecipientTimelineDrawerProps {
  recipientId: string | null;
  onClose: () => void;
}

function fmtName(d: RecipientDetail): string {
  const fn = [d.firstName, d.lastName].filter(Boolean).join(' ').trim();
  return fn || d.email;
}

function fmtTimeShort(iso: string): string {
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return iso;
  return d.toLocaleString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
  });
}

function fmtEuro(value: number): string {
  return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }).format(value);
}

function fmtDuration(ms?: number): string {
  if (!ms) return '';
  if (ms < 1000) return `${ms}ms`;
  if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
  return `${Math.round(ms / 60_000)}min`;
}

interface EventIconInfo {
  icon: ReactNode;
  label: string;
  description: (e: TimelineEvent) => string;
  /** Tailwind-Farbe für Icon-Kreis */
  color: string;
}

const EVENT_LOOKUP: Record<string, EventIconInfo> = {
  delivered: {
    icon: <MailCheck className="h-3.5 w-3.5" />,
    label: 'Zugestellt',
    description: () => 'Microsoft hat die Mail angenommen',
    color: 'bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300',
  },
  open: {
    icon: <Eye className="h-3.5 w-3.5" />,
    label: 'Geöffnet',
    description: (e) => (e.meta.isMpp ? 'Apple-MPP-Proxy-Ping (kein verifizierter Open)' : 'Verifizierter Open'),
    color: 'bg-indigo-100 text-indigo-700 dark:bg-indigo-950/40 dark:text-indigo-300',
  },
  click: {
    icon: <MousePointerClick className="h-3.5 w-3.5" />,
    label: 'Geklickt',
    description: (e) => e.meta.linkUrl ?? 'CTA geklickt',
    color: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-300',
  },
  bounce: {
    icon: <MailX className="h-3.5 w-3.5" />,
    label: 'Bounce',
    description: () => 'Unzustellbar — Empfänger wird übersprungen',
    color: 'bg-red-100 text-red-700 dark:bg-red-950/40 dark:text-red-300',
  },
  unsubscribe: {
    icon: <UserCircle2 className="h-3.5 w-3.5" />,
    label: 'Abgemeldet',
    description: () => 'Newsletter-Opt-Out',
    color: 'bg-zinc-200 text-zinc-700 dark:bg-zinc-700 dark:text-zinc-300',
  },
  complaint: {
    icon: <AlertOctagon className="h-3.5 w-3.5" />,
    label: 'Beschwerde',
    description: () => 'Spam-Beschwerde des Empfängers',
    color: 'bg-rose-200 text-rose-800 dark:bg-rose-950/50 dark:text-rose-300',
  },
  conversion: {
    icon: <BadgeEuro className="h-3.5 w-3.5" />,
    label: 'Conversion',
    description: (e) => {
      const src = e.meta.source ?? 'unbekannt';
      const value = e.meta.value ? ` · ${fmtEuro(e.meta.value)}` : '';
      return `Quelle: ${src}${value}`;
    },
    color: 'bg-amber-100 text-amber-700 dark:bg-amber-950/40 dark:text-amber-300',
  },
  pageview: {
    icon: <Globe className="h-3.5 w-3.5" />,
    label: 'Pageview',
    description: (e) => e.meta.url ?? 'Seitenaufruf',
    color: 'bg-sky-100 text-sky-700 dark:bg-sky-950/40 dark:text-sky-300',
  },
  product_view: {
    icon: <Sparkles className="h-3.5 w-3.5" />,
    label: 'Produkt angesehen',
    description: (e) => e.meta.productId ?? e.meta.url ?? 'Produktseite',
    color: 'bg-violet-100 text-violet-700 dark:bg-violet-950/40 dark:text-violet-300',
  },
  add_to_cart: {
    icon: <ShoppingCart className="h-3.5 w-3.5" />,
    label: 'In den Warenkorb',
    description: (e) => `${e.meta.productId ?? 'Produkt'}${e.meta.value ? ' · ' + fmtEuro(e.meta.value) : ''}`,
    color: 'bg-orange-100 text-orange-700 dark:bg-orange-950/40 dark:text-orange-300',
  },
  quote_form: {
    icon: <FileText className="h-3.5 w-3.5" />,
    label: 'Quote-Formular',
    description: (e) => e.meta.url ?? 'Angebotsanfrage abgesendet',
    color: 'bg-teal-100 text-teal-700 dark:bg-teal-950/40 dark:text-teal-300',
  },
  scroll_depth: {
    icon: <ScrollText className="h-3.5 w-3.5" />,
    label: 'Scroll-Tiefe',
    description: (e) => `${e.meta.scrollPct ?? 0}% gescrollt`,
    color: 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300',
  },
  time_on_page: {
    icon: <Clock className="h-3.5 w-3.5" />,
    label: 'Verweildauer',
    description: (e) => fmtDuration(e.meta.durationMs),
    color: 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300',
  },
  custom: {
    icon: <Sparkles className="h-3.5 w-3.5" />,
    label: 'Custom-Event',
    description: (e) => e.meta.url ?? e.type,
    color: 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300',
  },
};

function getEventInfo(type: string): EventIconInfo {
  return EVENT_LOOKUP[type] ?? EVENT_LOOKUP.custom;
}

export function RecipientTimelineDrawer({ recipientId, onClose }: RecipientTimelineDrawerProps) {
  const [data, setData] = useState<TimelineResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [crmExpanded, setCrmExpanded] = useState(false);

  const fetchTimeline = useCallback(async () => {
    if (!recipientId) return;
    setLoading(true);
    setError(null);
    try {
      const res = await fetch(`/api/recipients/${recipientId}/timeline`);
      if (!res.ok) {
        if (res.status === 404) throw new Error('Empfänger nicht gefunden');
        throw new Error(`Timeline-Lookup fehlgeschlagen (${res.status})`);
      }
      const json: TimelineResponse = await res.json();
      setData(json);
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Timeline-Lookup fehlgeschlagen');
    } finally {
      setLoading(false);
    }
  }, [recipientId]);

  // Fetch wenn ID sich ändert
  useEffect(() => {
    if (recipientId) {
      setData(null);
      void fetchTimeline();
    }
  }, [recipientId, fetchTimeline]);

  // ESC zum Schließen
  useEffect(() => {
    if (!recipientId) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [recipientId, onClose]);

  if (!recipientId) return null;

  return (
    <div className="fixed inset-0 z-50 flex">
      {/* Backdrop */}
      <div
        onClick={onClose}
        className="flex-1 bg-zinc-900/40 backdrop-blur-sm transition"
        aria-hidden="true"
      />
      {/* Drawer-Panel */}
      <div className="flex h-full w-full max-w-[600px] flex-col overflow-hidden bg-white shadow-2xl dark:bg-zinc-950">
        {/* ─── Header ─────────────────────────────────────────────── */}
        <div className="flex items-start justify-between gap-3 border-b border-zinc-200 px-5 py-4 dark:border-zinc-800">
          {data ? (
            <div className="min-w-0 flex-1">
              <div className="flex items-center gap-2">
                <h2 className="truncate text-lg font-semibold text-zinc-900 dark:text-zinc-100">
                  {fmtName(data.detail)}
                </h2>
                {data.detail.variantLabel && (
                  <span className="rounded bg-zinc-900 px-1.5 py-0.5 text-[10px] font-bold text-white dark:bg-zinc-200 dark:text-zinc-900">
                    {data.detail.variantLabel}
                  </span>
                )}
              </div>
              <div className="mt-0.5 truncate text-xs text-zinc-500">{data.detail.email}</div>
              <div className="mt-1 text-[11px] text-zinc-400">
                {data.detail.brandName} · {data.detail.campaignName}
              </div>
            </div>
          ) : (
            <div className="flex-1">
              <div className="h-5 w-40 animate-pulse rounded bg-zinc-100 dark:bg-zinc-800" />
              <div className="mt-2 h-3 w-32 animate-pulse rounded bg-zinc-100 dark:bg-zinc-800" />
            </div>
          )}
          <button
            type="button"
            onClick={onClose}
            className="rounded-md p-1 text-zinc-500 transition hover:bg-zinc-100 dark:hover:bg-zinc-800"
            aria-label="Drawer schließen"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        {/* ─── Quick-Stats ──────────────────────────────────────────── */}
        {data && (
          <div className="grid grid-cols-4 gap-2 border-b border-zinc-200 bg-zinc-50/50 px-5 py-3 dark:border-zinc-800 dark:bg-zinc-900/50">
            <QuickStat
              icon={data.detail.isMppOnly ? <EyeOff className="h-3 w-3" /> : <Eye className="h-3 w-3" />}
              label={data.detail.isMppOnly ? 'Opens (MPP)' : 'Opens'}
              value={String(data.detail.openCount)}
            />
            <QuickStat
              icon={<MousePointerClick className="h-3 w-3" />}
              label="Klicks"
              value={String(data.detail.clickCount)}
            />
            <QuickStat
              icon={<Globe className="h-3 w-3" />}
              label="Onsite"
              value={String(data.detail.behaviorCount)}
            />
            <QuickStat
              icon={<BadgeEuro className="h-3 w-3" />}
              label="Conversion"
              value={
                data.detail.conversionValueTotal > 0
                  ? fmtEuro(data.detail.conversionValueTotal)
                  : String(data.detail.conversionCount)
              }
            />
          </div>
        )}

        {/* ─── Content ──────────────────────────────────────────── */}
        <div className="flex-1 overflow-y-auto px-5 py-4">
          {error && (
            <div className="flex items-start gap-2 rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-800 dark:border-red-900/50 dark:bg-red-950/30">
              <AlertTriangle className="h-4 w-4 mt-0.5" />
              <span>{error}</span>
            </div>
          )}

          {loading && !data && (
            <div className="flex items-center justify-center py-12 text-sm text-zinc-500">
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              Lade Timeline…
            </div>
          )}

          {data && data.events.length === 0 && (
            <div className="rounded-md border border-dashed border-zinc-300 px-4 py-8 text-center text-xs text-zinc-500 dark:border-zinc-700">
              Noch keine Events für diesen Empfänger.
              <br />
              Erste Daten kommen mit der nächsten Öffnung / Klick.
            </div>
          )}

          {data && data.events.length > 0 && (
            <ol className="relative space-y-3 border-l border-zinc-200 pl-5 dark:border-zinc-800">
              {data.events.map((e) => (
                <TimelineEntry key={e.id} event={e} />
              ))}
            </ol>
          )}

          {/* CRM-Daten-Sektion */}
          {data?.detail.customDataJson && Object.keys(data.detail.customDataJson).length > 0 && (
            <div className="mt-6 rounded-md border border-zinc-200 dark:border-zinc-800">
              <button
                type="button"
                onClick={() => setCrmExpanded((v) => !v)}
                className="flex w-full items-center justify-between px-3 py-2 text-xs font-semibold text-zinc-700 dark:text-zinc-300"
              >
                <span className="flex items-center gap-1.5">
                  <Database className="h-3.5 w-3.5" />
                  CRM-Daten
                  {data.detail.crmId && (
                    <span className="ml-1 rounded bg-zinc-100 px-1.5 py-0.5 font-mono text-[10px] text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400">
                      ID {data.detail.crmId}
                    </span>
                  )}
                </span>
                {crmExpanded ? <ChevronUp className="h-3.5 w-3.5" /> : <ChevronDown className="h-3.5 w-3.5" />}
              </button>
              {crmExpanded && (
                <dl className="grid grid-cols-1 gap-1 border-t border-zinc-200 px-3 py-2 text-xs dark:border-zinc-800">
                  {Object.entries(data.detail.customDataJson)
                    .filter(([, v]) => v != null && v !== '')
                    .map(([k, v]) => (
                      <div key={k} className="flex justify-between gap-2 border-b border-zinc-100 py-1 last:border-b-0 dark:border-zinc-900">
                        <dt className="text-zinc-500">{k}</dt>
                        <dd className="truncate text-right text-zinc-700 dark:text-zinc-300">
                          {typeof v === 'object' ? JSON.stringify(v) : String(v)}
                        </dd>
                      </div>
                    ))}
                </dl>
              )}
            </div>
          )}

          {/* GA4-Session-Panel (Phase 4) */}
          <Ga4SessionPanel recipientId={data!.detail.id} />
        </div>
      </div>
    </div>
  );
}

function QuickStat({ icon, label, value }: { icon: ReactNode; label: string; value: string }) {
  return (
    <div className="flex flex-col gap-0.5">
      <div className="flex items-center gap-1 text-[10px] uppercase tracking-wider text-zinc-500">
        {icon}
        {label}
      </div>
      <div className="text-sm font-semibold text-zinc-900 dark:text-zinc-100">{value}</div>
    </div>
  );
}

function TimelineEntry({ event }: { event: TimelineEvent }) {
  const info = getEventInfo(event.type);
  const isOnsite = event.source === 'onsite';
  return (
    <li className="relative">
      {/* Marker auf der Linie */}
      <span
        className={cn(
          'absolute -left-[26px] flex h-5 w-5 items-center justify-center rounded-full border-2 border-white dark:border-zinc-950',
          info.color,
        )}
      >
        {info.icon}
      </span>
      <div className="flex items-start justify-between gap-2">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-1.5 text-xs font-semibold text-zinc-900 dark:text-zinc-100">
            {info.label}
            {isOnsite && (
              <span className="rounded bg-sky-50 px-1 py-0.5 text-[9px] font-medium uppercase text-sky-700 dark:bg-sky-950/40 dark:text-sky-300">
                onsite
              </span>
            )}
            {event.type === 'open' && event.meta.isMpp && (
              <span className="rounded bg-zinc-100 px-1 py-0.5 text-[9px] font-medium uppercase text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400">
                MPP
              </span>
            )}
          </div>
          <div className="mt-0.5 truncate text-[11px] text-zinc-500">{info.description(event)}</div>
          {event.meta.linkUrl && (
            <a
              href={event.meta.linkUrl}
              target="_blank"
              rel="noopener noreferrer"
              className="mt-0.5 inline-flex items-center gap-0.5 text-[11px] text-blue-600 hover:underline dark:text-blue-400"
              onClick={(e) => e.stopPropagation()}
            >
              <ExternalLink className="h-3 w-3" /> Link öffnen
            </a>
          )}
        </div>
        <div className="shrink-0 text-[10px] tabular-nums text-zinc-400">
          {fmtTimeShort(event.ts)}
        </div>
      </div>
    </li>
  );
}
