'use client';

import { useState } from 'react';
import { CalendarClock, Send, Repeat, Wand2, Sparkles, Loader2, Info, AlertTriangle, CheckCircle2, CalendarDays, Clock, BarChart3, Link2, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import type { BriefingSchedule, ScheduleFrequency, Briefing } from '@/modules/briefing/ui/BriefingPanel';
import { OptionalSection } from '@/modules/briefing/ui/BriefingPanel';
import { prefillUtm, mergeUtmDefaults } from '@/modules/sending/lib/utm';
import { estimateDistribution, hasDistributionLimits } from '@/modules/scheduler/lib/distribute-jobs';

export interface SchedulerPanelProps {
  /** Controlled — Schedule-State liegt im Parent. */
  value: BriefingSchedule;
  onChange: (next: BriefingSchedule) => void;
  /** Briefing-Kontext für KI-Suggest (Workspace, Segment, Goal, Audience). */
  briefing: Briefing;
  /**
   * Partial-Update auf das Briefing (für UTM- und Champion-Test-Sections, die früher
   * im Briefing-Tab lebten und jetzt hier konfiguriert werden).
   */
  onBriefingPatch?: (patch: Partial<Briefing>) => void;
  /**
   * Anzahl der Subject-Varianten (1 = klassischer Send, ≥ 2 = A/B-Test).
   * Wird nur für den Hint in der Champion-Test-Section genutzt.
   */
  variantCount?: number;
  /** Audience-Source-Hint für KI (vom RecipientPicker). 'business' = B2B, 'orders' = B2C, etc. */
  audienceSource?: 'business' | 'orders' | 'evb' | 'csv';
  className?: string;
}

const FREQ_LABELS: Record<ScheduleFrequency, string> = {
  daily: 'Täglich',
  weekly: 'Wöchentlich',
  biweekly: 'Alle 2 Wochen',
  monthly: 'Monatlich',
};

const WEEKDAY_LABELS = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];

/** Reihenfolge der Pills im Wochentag-Toggle — Mo zuerst (deutsche Lese-Konvention). */
const WEEKDAY_PILLS: { value: number; short: string }[] = [
  { value: 1, short: 'Mo' },
  { value: 2, short: 'Di' },
  { value: 3, short: 'Mi' },
  { value: 4, short: 'Do' },
  { value: 5, short: 'Fr' },
  { value: 6, short: 'Sa' },
  { value: 0, short: 'So' },
];
const WORKDAYS_DEFAULT = [1, 2, 3, 4, 5];

export function SchedulerPanel({ value, onChange, briefing, onBriefingPatch, variantCount, audienceSource, className }: SchedulerPanelProps) {
  const [suggesting, setSuggesting] = useState(false);
  const [suggestError, setSuggestError] = useState<string | null>(null);

  const update = <K extends keyof BriefingSchedule>(k: K, v: BriefingSchedule[K]) => {
    onChange({ ...value, [k]: v });
  };

  const handleSuggest = async () => {
    setSuggesting(true);
    setSuggestError(null);
    try {
      const res = await fetch('/api/scheduler/suggest', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({
          workspaceSlug: briefing.workspaceSlug,
          recipientCount: briefing.recipients?.length ?? 0,
          audienceSource: audienceSource ?? 'business',
          offer: briefing.offer,
        }),
      });
      const data = await res.json();
      if (!res.ok) {
        setSuggestError(data.error ?? `HTTP ${res.status}`);
        return;
      }
      // Setze die Suggestion in den State, der User kann sie übernehmen
      onChange({
        ...value,
        suggestion: {
          bestDays: data.bestDays ?? [],
          bestTimeWindow: data.bestTimeWindow ?? '',
          timezone: data.timezone ?? 'Europe/Berlin',
          reasoning: data.reasoning ?? '',
          generatedAt: new Date().toISOString(),
        },
      });
    } catch (e) {
      setSuggestError(e instanceof Error ? e.message : 'Network error');
    } finally {
      setSuggesting(false);
    }
  };

  /** Übernimmt die KI-Empfehlung als nächste passende Datums-Konfiguration */
  const applySuggestion = () => {
    const sugg = value.suggestion;
    if (!sugg) return;
    // Parse "09:00-11:00" → start time
    const [startTime] = sugg.bestTimeWindow.split('-');
    const [hour, minute] = (startTime ?? '09:00').split(':').map(Number);
    // Find next matching weekday from suggested days (Monday-first index)
    const dayMap: Record<string, number> = {
      Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6, Sunday: 0,
      Montag: 1, Dienstag: 2, Mittwoch: 3, Donnerstag: 4, Freitag: 5, Samstag: 6, Sonntag: 0,
    };
    const targetDays = sugg.bestDays.map((d) => dayMap[d]).filter((d) => d !== undefined) as number[];
    if (targetDays.length === 0) return;
    const now = new Date();
    let candidate = new Date(now);
    candidate.setHours(hour ?? 9, minute ?? 0, 0, 0);
    // Wenn heute der Tag passt UND die Zeit noch in der Zukunft liegt → heute, sonst suche nächsten Match
    if (!targetDays.includes(candidate.getDay()) || candidate <= now) {
      for (let i = 1; i <= 7; i++) {
        const d = new Date(now);
        d.setDate(d.getDate() + i);
        d.setHours(hour ?? 9, minute ?? 0, 0, 0);
        if (targetDays.includes(d.getDay())) { candidate = d; break; }
      }
    }
    onChange({
      ...value,
      mode: value.mode === 'now' ? 'scheduled' : value.mode,
      scheduledAt: candidate.toISOString(),
    });
  };

  return (
    <div className={cn('flex flex-col gap-4', className)}>
      {/* ─── Header ──────────────────────────────────────────────────── */}
      <header>
        <div className="flex items-center gap-2">
          <h2 className="text-lg font-bold tracking-tight text-zinc-900 dark:text-zinc-100">Versand</h2>
          <span className="text-xs text-zinc-400">— wann und in welchem Rhythmus</span>
        </div>
      </header>

      {/* ─── KI-Suggest Banner ───────────────────────────────────────── */}
      <button
        type="button"
        onClick={handleSuggest}
        disabled={suggesting || !briefing.workspaceSlug}
        className={cn(
          'group flex w-full items-center justify-between gap-3 rounded-xl border-2 px-4 py-3 text-left transition',
          !suggesting && briefing.workspaceSlug
            ? 'border-pink-300 bg-gradient-to-r from-pink-50 to-rose-50 shadow-sm hover:border-pink-400 hover:shadow-md dark:border-pink-800 dark:from-pink-950/40 dark:to-rose-950/40'
            : 'cursor-not-allowed border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900/30',
        )}
      >
        <div className="flex items-center gap-3">
          <div
            className={cn(
              'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg shadow-sm transition',
              !suggesting && briefing.workspaceSlug
                ? 'bg-[#ff006a] text-white group-hover:bg-[#e60060]'
                : 'bg-zinc-200 text-zinc-400 dark:bg-zinc-800 dark:text-zinc-600',
            )}
          >
            {suggesting ? <Loader2 className="h-5 w-5 animate-spin" /> : <Wand2 className="h-5 w-5" />}
          </div>
          <div className="min-w-0">
            <div className={cn(
              'text-base font-bold',
              !suggesting && briefing.workspaceSlug ? 'text-pink-900 dark:text-pink-100' : 'text-zinc-500',
            )}>
              {suggesting ? 'Analysiere optimale Versandzeit …' : 'KI-Vorschlag für beste Versandzeit'}
            </div>
            <div className={cn(
              'mt-0.5 text-xs',
              !suggesting && briefing.workspaceSlug ? 'text-pink-700 dark:text-pink-300' : 'text-zinc-400',
            )}>
              {briefing.workspaceSlug
                ? `Basierend auf Workspace · Segment · Audience-Typ — empfiehlt beste Tage und Uhrzeit für hohe Open-Rate`
                : 'Erst eine Workspace auswählen (Tab "Briefing")'}
            </div>
          </div>
        </div>
        <Sparkles
          className={cn(
            'h-5 w-5 shrink-0 transition',
            !suggesting && briefing.workspaceSlug
              ? 'text-[#ff006a] group-hover:text-[#e60060] dark:text-pink-400'
              : 'text-zinc-300',
          )}
        />
      </button>

      {suggestError && (
        <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="mt-0.5 h-3.5 w-3.5 shrink-0" />
          <span className="flex-1">{suggestError}</span>
        </div>
      )}

      {value.suggestion && (
        <div className="flex items-start gap-3 rounded-lg border border-pink-200 bg-pink-50/60 p-4 dark:border-pink-900/50 dark:bg-pink-950/20">
          <Sparkles className="mt-0.5 h-4 w-4 shrink-0 text-[#ff006a]" />
          <div className="flex-1 min-w-0">
            <div className="text-sm font-semibold text-pink-900 dark:text-pink-100">
              Empfohlen: {value.suggestion.bestDays.join(', ')} · {value.suggestion.bestTimeWindow}
              <span className="ml-2 text-[10px] font-normal text-pink-700 dark:text-pink-300">({value.suggestion.timezone})</span>
            </div>
            <div className="mt-1 text-xs text-pink-800 dark:text-pink-200">{value.suggestion.reasoning}</div>
          </div>
          <button
            type="button"
            onClick={applySuggestion}
            className="inline-flex shrink-0 items-center gap-1.5 rounded-md bg-[#ff006a] px-3 py-1.5 text-xs font-semibold text-white shadow-sm hover:bg-[#e60060]"
          >
            <CheckCircle2 className="h-3.5 w-3.5" />
            Übernehmen
          </button>
        </div>
      )}

      {/* ─── Mode-Selector (Now / Scheduled / Recurring) ─────────────── */}
      <fieldset>
        <legend className="mb-2 text-sm font-semibold text-zinc-800 dark:text-zinc-200">Versand-Modus</legend>
        <div className="grid grid-cols-3 gap-2">
          <ModeCard
            active={value.mode === 'now'}
            onClick={() => update('mode', 'now')}
            icon={<Send className="h-4 w-4" />}
            label="Sofort"
            hint="Direkt nach Klick auf Versand starten"
          />
          <ModeCard
            active={value.mode === 'scheduled'}
            onClick={() => update('mode', 'scheduled')}
            icon={<CalendarClock className="h-4 w-4" />}
            label="Geplant"
            hint="Einmaliger Versand zu festem Termin"
          />
          <ModeCard
            active={value.mode === 'recurring'}
            onClick={() => update('mode', 'recurring')}
            icon={<Repeat className="h-4 w-4" />}
            label="Wiederkehrend"
            hint="Z.B. wöchentlicher Newsletter"
          />
        </div>
      </fieldset>

      {/* ─── Datum + Zeit (für scheduled & recurring) ─────────────────── */}
      {value.mode !== 'now' && (
        <div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
          <div className="flex flex-col gap-1.5">
            <label className="text-sm font-semibold text-zinc-800 dark:text-zinc-200">
              {value.mode === 'recurring' ? 'Erst-Versand am' : 'Versand-Zeitpunkt'}
            </label>
            <input
              type="datetime-local"
              value={value.scheduledAt ? toLocalDateTime(value.scheduledAt) : ''}
              onChange={(e) => update('scheduledAt', e.target.value ? new Date(e.target.value).toISOString() : undefined)}
              className="w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm transition focus:border-zinc-900 focus:outline-none focus:ring-2 focus:ring-zinc-900/10 dark:border-zinc-700 dark:bg-zinc-900"
            />
            <span className="text-[11px] text-zinc-500">Lokale Zeitzone — Worker konvertiert automatisch zu UTC</span>
          </div>

          {value.mode === 'recurring' && (
            <div className="flex flex-col gap-1.5">
              <label className="text-sm font-semibold text-zinc-800 dark:text-zinc-200">Frequenz</label>
              <select
                value={value.frequency ?? 'weekly'}
                onChange={(e) => update('frequency', e.target.value as ScheduleFrequency)}
                className="w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm transition focus:border-zinc-900 focus:outline-none focus:ring-2 focus:ring-zinc-900/10 dark:border-zinc-700 dark:bg-zinc-900"
              >
                {(Object.keys(FREQ_LABELS) as ScheduleFrequency[]).map((f) => (
                  <option key={f} value={f}>{FREQ_LABELS[f]}</option>
                ))}
              </select>
              {value.frequency && ['weekly', 'biweekly'].includes(value.frequency) && value.scheduledAt && (
                <span className="text-[11px] text-zinc-500">
                  → Jeden {WEEKDAY_LABELS[new Date(value.scheduledAt).getDay()]}
                </span>
              )}
            </div>
          )}
        </div>
      )}

      {/* ─── Throttle ──────────────────────────────────────────────────── */}
      <div className="flex flex-col gap-1.5 rounded-lg border border-zinc-200 bg-zinc-50/50 p-3 dark:border-zinc-800 dark:bg-zinc-900/30">
        <label className="flex items-center gap-1.5 text-sm font-semibold text-zinc-800 dark:text-zinc-200">
          Throttle
          <span title="M365-Limit: 30/min, 9.500/Tag pro Mailbox. Wir spielen anti-spam aus." className="cursor-help">
            <Info className="h-3.5 w-3.5 text-zinc-400" />
          </span>
        </label>
        <div className="flex items-center gap-2">
          <input
            type="number"
            min={10}
            max={1500}
            value={value.throttlePerHour ?? 100}
            onChange={(e) => update('throttlePerHour', Math.max(10, Math.min(1500, parseInt(e.target.value, 10) || 100)))}
            className="w-24 rounded-md border border-zinc-200 bg-white px-3 py-1.5 text-sm dark:border-zinc-700 dark:bg-zinc-900"
          />
          <span className="text-sm text-zinc-600 dark:text-zinc-400">Mails / Stunde</span>
          {(briefing.recipients?.length ?? 0) > 0 && (
            <span className="ml-auto text-xs text-zinc-500">
              ≈ {Math.ceil((briefing.recipients?.length ?? 0) / (value.throttlePerHour ?? 100))} Stunden Versand-Dauer
            </span>
          )}
        </div>
      </div>

      {/* ─── Versand-Limits (nur scheduled/recurring) ──────────────────── */}
      {value.mode !== 'now' && (
        <DistributionLimits value={value} onChange={onChange} briefing={briefing} />
      )}

      {/* ─── Tracking & A/B-Strategie ──────────────────────────────────── */}
      {/*
        UTM-Tracking und Champion-Test lebten früher im Briefing-Tab — sie betreffen aber
        ausschliesslich das Send-Verhalten (Worker hängt UTM zur Send-Zeit an, Champion
        promotet Varianten nach abWinnerHours). Daher gehören sie thematisch in den Versand-Tab.
        Beide schreiben weiterhin in dasselbe Briefing-Objekt via `onBriefingPatch`.
      */}
      {onBriefingPatch && (
        <div className="flex flex-col gap-2">
          <UtmSection briefing={briefing} onBriefingPatch={onBriefingPatch} />
          <ChampionTestSection briefing={briefing} onBriefingPatch={onBriefingPatch} variantCount={variantCount} />
        </div>
      )}

      {/* ─── Status-Summary ────────────────────────────────────────────── */}
      <div className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-xs text-zinc-600 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400">
        <strong className="text-zinc-900 dark:text-zinc-100">Zusammenfassung: </strong>
        {value.mode === 'now' && 'Sofortiger Versand nach Klick auf den „Versand starten"-Button.'}
        {value.mode === 'scheduled' && value.scheduledAt && (
          <>Einmaliger Versand am <strong>{formatDateTime(value.scheduledAt)}</strong> · {value.throttlePerHour ?? 100} Mails/h.</>
        )}
        {value.mode === 'scheduled' && !value.scheduledAt && (
          <span className="text-amber-700 dark:text-amber-400">⚠ Bitte Versand-Zeitpunkt setzen.</span>
        )}
        {value.mode === 'recurring' && value.scheduledAt && value.frequency && (
          <>{FREQ_LABELS[value.frequency]} ab <strong>{formatDateTime(value.scheduledAt)}</strong> · {value.throttlePerHour ?? 100} Mails/h.</>
        )}
        {value.mode === 'recurring' && (!value.scheduledAt || !value.frequency) && (
          <span className="text-amber-700 dark:text-amber-400">⚠ Bitte Erst-Termin und Frequenz setzen.</span>
        )}
        {value.mode !== 'now' && describeLimits(value)}
      </div>
    </div>
  );
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

/** ISO-Date → lokales 'YYYY-MM-DDTHH:MM'-Format für `<input type="datetime-local">` */
function toLocalDateTime(iso: string): string {
  const d = new Date(iso);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

function formatDateTime(iso: string): string {
  return new Date(iso).toLocaleString('de-DE', {
    weekday: 'short',
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

// ─── Sub-Components ───────────────────────────────────────────────────────────

/** Zusätzliche Summary-Zeile, wenn mindestens ein Distribution-Limit gesetzt ist. */
function describeLimits(s: BriefingSchedule): React.ReactNode {
  const parts: string[] = [];
  if (s.sendWindowStart && s.sendWindowEnd) parts.push(`Fenster ${s.sendWindowStart}–${s.sendWindowEnd}`);
  if (s.maxPerDay !== undefined) parts.push(`max ${s.maxPerDay}/Tag`);
  if (s.allowedWeekdays && s.allowedWeekdays.length > 0 && s.allowedWeekdays.length < 7) {
    const labels = WEEKDAY_PILLS.filter((p) => s.allowedWeekdays!.includes(p.value)).map((p) => p.short).join(', ');
    parts.push(labels);
  }
  if (parts.length === 0) return null;
  return <span className="ml-1 text-zinc-500">· {parts.join(' · ')}</span>;
}

/** Versand-Limits-Section: Tages-Cap, Zeitfenster, Wochentag-Filter + Live-Estimate. */
function DistributionLimits({
  value,
  onChange,
  briefing,
}: {
  value: BriefingSchedule;
  onChange: (next: BriefingSchedule) => void;
  briefing: Briefing;
}) {
  const update = <K extends keyof BriefingSchedule>(k: K, v: BriefingSchedule[K]) => {
    onChange({ ...value, [k]: v });
  };

  const recipientCount = briefing.recipients?.length ?? 0;
  const capActive = value.maxPerDay !== undefined;
  const windowActive = value.sendWindowStart !== undefined && value.sendWindowEnd !== undefined;
  const weekdaysActive = value.allowedWeekdays !== undefined;

  // Live-Estimate. startAt fallback = jetzt (für anzeige solange scheduledAt fehlt).
  const startAt = value.scheduledAt ? new Date(value.scheduledAt) : new Date();
  const estimate = recipientCount > 0 && hasDistributionLimits({
    count: recipientCount,
    startAt,
    throttlePerHour: value.throttlePerHour,
    maxPerDay: value.maxPerDay,
    windowStart: value.sendWindowStart,
    windowEnd: value.sendWindowEnd,
    allowedWeekdays: value.allowedWeekdays,
  })
    ? estimateDistribution({
        count: recipientCount,
        startAt,
        throttlePerHour: value.throttlePerHour,
        maxPerDay: value.maxPerDay,
        windowStart: value.sendWindowStart,
        windowEnd: value.sendWindowEnd,
        allowedWeekdays: value.allowedWeekdays,
      })
    : null;

  return (
    <fieldset className="flex flex-col gap-3 rounded-lg border border-zinc-200 bg-zinc-50/30 p-3 dark:border-zinc-800 dark:bg-zinc-900/20">
      <legend className="px-1 text-sm font-semibold text-zinc-800 dark:text-zinc-200">Versand-Limits</legend>

      {/* Tages-Cap */}
      <LimitToggle
        active={capActive}
        onToggle={(on) => update('maxPerDay', on ? 200 : undefined)}
        icon={<BarChart3 className="h-4 w-4" />}
        label="Max Mails pro Tag"
        hint="Verteilt grosse Empfänger-Listen auf mehrere Tage."
      >
        <div className="flex items-center gap-2">
          <input
            type="number"
            min={1}
            max={9500}
            value={value.maxPerDay ?? 200}
            onChange={(e) => update('maxPerDay', Math.max(1, Math.min(9500, parseInt(e.target.value, 10) || 200)))}
            className="w-24 rounded-md border border-zinc-200 bg-white px-3 py-1.5 text-sm dark:border-zinc-700 dark:bg-zinc-900"
          />
          <span className="text-sm text-zinc-600 dark:text-zinc-400">Empfänger / Tag</span>
        </div>
      </LimitToggle>

      {/* Zeitfenster */}
      <LimitToggle
        active={windowActive}
        onToggle={(on) =>
          onChange({
            ...value,
            sendWindowStart: on ? '07:00' : undefined,
            sendWindowEnd: on ? '09:00' : undefined,
          })
        }
        icon={<Clock className="h-4 w-4" />}
        label="Nur in Zeitfenster versenden"
        hint="Z.B. nur morgens zwischen 7 und 9 Uhr."
      >
        <div className="flex items-center gap-2 text-sm text-zinc-600 dark:text-zinc-400">
          <span>Von</span>
          <input
            type="time"
            value={value.sendWindowStart ?? '07:00'}
            onChange={(e) => update('sendWindowStart', e.target.value)}
            className="rounded-md border border-zinc-200 bg-white px-2 py-1 text-sm dark:border-zinc-700 dark:bg-zinc-900"
          />
          <span>bis</span>
          <input
            type="time"
            value={value.sendWindowEnd ?? '09:00'}
            onChange={(e) => update('sendWindowEnd', e.target.value)}
            className="rounded-md border border-zinc-200 bg-white px-2 py-1 text-sm dark:border-zinc-700 dark:bg-zinc-900"
          />
          {windowActive && value.sendWindowStart && value.sendWindowEnd && value.sendWindowEnd <= value.sendWindowStart && (
            <span className="text-amber-700 dark:text-amber-400">⚠ Ende muss nach Start liegen</span>
          )}
        </div>
      </LimitToggle>

      {/* Wochentage */}
      <LimitToggle
        active={weekdaysActive}
        onToggle={(on) => update('allowedWeekdays', on ? WORKDAYS_DEFAULT : undefined)}
        icon={<CalendarDays className="h-4 w-4" />}
        label="Nur an bestimmten Wochentagen"
        hint="Z.B. Wochenenden ausschliessen."
      >
        <div className="flex flex-wrap gap-1.5">
          {WEEKDAY_PILLS.map((d) => {
            const enabled = value.allowedWeekdays?.includes(d.value) ?? false;
            return (
              <button
                key={d.value}
                type="button"
                onClick={() => {
                  const current = value.allowedWeekdays ?? [];
                  const next = enabled
                    ? current.filter((v) => v !== d.value)
                    : [...current, d.value].sort((a, b) => a - b);
                  update('allowedWeekdays', next.length === 0 ? undefined : next);
                }}
                className={cn(
                  'rounded-md border-2 px-2.5 py-1 text-xs font-semibold transition',
                  enabled
                    ? 'border-[#ff006a] bg-[#ff006a] text-white shadow-sm'
                    : 'border-zinc-200 bg-white text-zinc-600 hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-400',
                )}
              >
                {d.short}
              </button>
            );
          })}
          {weekdaysActive && (value.allowedWeekdays?.length ?? 0) === 0 && (
            <span className="self-center text-xs text-amber-700 dark:text-amber-400">⚠ Mindestens einen Tag wählen</span>
          )}
        </div>
      </LimitToggle>

      {/* Estimate-Box */}
      {estimate && estimate.finishAt && (
        <div className="flex items-start gap-2 rounded-md border border-emerald-200 bg-emerald-50/60 px-3 py-2 text-xs text-emerald-900 dark:border-emerald-900/50 dark:bg-emerald-950/20 dark:text-emerald-200">
          <BarChart3 className="mt-0.5 h-3.5 w-3.5 shrink-0" />
          <div className="flex-1">
            <strong>{recipientCount.toLocaleString('de-DE')} Empfänger</strong> · ~{estimate.perDay}/Tag · {estimate.totalDays} {estimate.totalDays === 1 ? 'Versand-Tag' : 'Versand-Tage'}
            <div className="text-emerald-700 dark:text-emerald-300">
              Versand fertig am <strong>{formatDateTime(estimate.finishAt.toISOString())}</strong>
            </div>
          </div>
        </div>
      )}
    </fieldset>
  );
}

function LimitToggle({
  active,
  onToggle,
  icon,
  label,
  hint,
  children,
}: {
  active: boolean;
  onToggle: (on: boolean) => void;
  icon: React.ReactNode;
  label: string;
  hint: string;
  children: React.ReactNode;
}) {
  return (
    <div className={cn('rounded-md border bg-white p-2.5 dark:bg-zinc-950', active ? 'border-zinc-300 dark:border-zinc-700' : 'border-zinc-200 dark:border-zinc-800')}>
      <label className="flex cursor-pointer items-start gap-2.5">
        <input
          type="checkbox"
          checked={active}
          onChange={(e) => onToggle(e.target.checked)}
          className="mt-0.5 h-4 w-4 cursor-pointer accent-[#ff006a]"
        />
        <div className="flex-1 min-w-0">
          <div className={cn('flex items-center gap-1.5 text-sm font-semibold', active ? 'text-zinc-900 dark:text-zinc-100' : 'text-zinc-600 dark:text-zinc-400')}>
            {icon}
            {label}
          </div>
          <div className="mt-0.5 text-[11px] text-zinc-500">{hint}</div>
        </div>
      </label>
      {active && <div className="mt-2 pl-[26px]">{children}</div>}
    </div>
  );
}

function ModeCard({ active, onClick, icon, label, hint }: {
  active: boolean; onClick: () => void; icon: React.ReactNode; label: string; hint: string;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        'flex flex-col items-start gap-1 rounded-lg border-2 p-3 text-left transition',
        active
          ? 'border-[#ff006a] bg-pink-50/60 dark:border-[#ff006a] dark:bg-pink-950/30'
          : 'border-zinc-200 bg-white hover:border-zinc-300 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:hover:border-zinc-600',
      )}
    >
      <div className={cn('flex items-center gap-1.5 text-sm font-semibold', active ? 'text-[#ff006a]' : 'text-zinc-700 dark:text-zinc-300')}>
        {icon}
        {label}
      </div>
      <span className="text-[11px] leading-tight text-zinc-500 dark:text-zinc-400">{hint}</span>
    </button>
  );
}

// ─── UTM-Tracking-Section ─────────────────────────────────────────────────────
//
// UTM-Defaults der Campaign — bei aktivem Toggle werden alle Links im HTML zur Send-Zeit
// mit diesen Parametern angereichert (Auto-Append). `utm_content` wird beim A/B-Send
// automatisch pro Variante überschrieben (A/B/C). KI-Verfeinerung schlägt saubere
// Slugs nach Workspace-Konvention vor.

function UtmSection({
  briefing,
  onBriefingPatch,
}: {
  briefing: Briefing;
  onBriefingPatch: (patch: Partial<Briefing>) => void;
}) {
  const [isSuggestingUtm, setIsSuggestingUtm] = useState(false);
  const [utmSuggestError, setUtmSuggestError] = useState<string | null>(null);

  const enabled = briefing.optional?.utmTracking ?? false;

  const handleSuggestUtm = async () => {
    setIsSuggestingUtm(true);
    setUtmSuggestError(null);
    try {
      const res = await fetch('/api/suggest-utm', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({
          briefText: '',
          workspaceSlug: briefing.workspaceSlug,
          campaignName: briefing.campaignName,
          existing: briefing.utm ?? {},
        }),
      });
      const data = await res.json();
      if (!res.ok) {
        setUtmSuggestError(typeof data?.error === 'string' ? data.error : 'KI-Vorschlag fehlgeschlagen');
        return;
      }
      const s = data.suggestions ?? {};
      const nextUtm = mergeUtmDefaults(briefing.utm, {
        source: s.source,
        medium: s.medium,
        campaign: s.campaign,
        term: s.term,
      });
      onBriefingPatch({ utm: nextUtm });
    } catch (err) {
      setUtmSuggestError(err instanceof Error ? err.message : 'Netzwerk-Fehler');
    } finally {
      setIsSuggestingUtm(false);
    }
  };

  return (
    <OptionalSection
      icon={<Link2 className="h-4 w-4" />}
      title="Tracking / UTM-Parameter"
      subtitle="Hängt utm_source / utm_medium / utm_campaign automatisch an alle Links im Email-Body — für Google Analytics & Co."
      enabled={enabled}
      onToggle={(v) => {
        // Beim Aktivieren: deterministische Defaults aus Workspace/Campaign-Name
        // non-destruktiv mergen. Bereits getippte UTM-Werte bleiben unverändert.
        // Beim Deaktivieren: Werte stehen lassen, falls der User später wieder anschaltet.
        const nextUtm = v
          ? mergeUtmDefaults(
              briefing.utm,
              prefillUtm({
                workspaceSlug: briefing.workspaceSlug,
                campaignName: briefing.campaignName,
              }),
            )
          : briefing.utm;
        onBriefingPatch({
          optional: { ...briefing.optional, utmTracking: v },
          utm: nextUtm,
        });
      }}
    >
      <div className="mb-2 flex items-center justify-between gap-2">
        <span className="text-[10px] text-zinc-500 dark:text-zinc-400">
          Vorbelegt aus Briefing — KI verfeinert auf saubere Slugs.
        </span>
        <button
          type="button"
          onClick={handleSuggestUtm}
          disabled={isSuggestingUtm}
          className="inline-flex items-center gap-1 rounded-md border border-pink-200 bg-pink-50 px-2 py-1 text-[11px] font-medium text-[#ff006a] transition hover:bg-pink-100 disabled:cursor-not-allowed disabled:opacity-60 dark:border-pink-900/50 dark:bg-pink-950/30 dark:hover:bg-pink-900/40"
        >
          {isSuggestingUtm ? (
            <>
              <Loader2 className="h-3 w-3 animate-spin" />
              KI denkt nach…
            </>
          ) : (
            <>
              <Sparkles className="h-3 w-3" />
              KI verfeinern
            </>
          )}
        </button>
      </div>
      {utmSuggestError && (
        <div className="mb-2 flex items-start gap-1.5 rounded-md border border-red-200 bg-red-50 px-2 py-1.5 text-[11px] text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300">
          <span className="font-medium">Fehler:</span>
          <span className="flex-1">{utmSuggestError}</span>
          <button onClick={() => setUtmSuggestError(null)} className="opacity-60 hover:opacity-100" aria-label="schließen">
            <X className="h-3 w-3" />
          </button>
        </div>
      )}
      <div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
        <UtmField
          label="utm_source"
          value={briefing.utm?.source ?? ''}
          onChange={(v) => onBriefingPatch({ utm: { ...briefing.utm, source: v || undefined } })}
          placeholder="z.B. newsletter"
        />
        <UtmField
          label="utm_medium"
          value={briefing.utm?.medium ?? ''}
          onChange={(v) => onBriefingPatch({ utm: { ...briefing.utm, medium: v || undefined } })}
          placeholder="email"
        />
        <UtmField
          label="utm_campaign"
          value={briefing.utm?.campaign ?? ''}
          onChange={(v) => onBriefingPatch({ utm: { ...briefing.utm, campaign: v || undefined } })}
          placeholder={briefing.campaignName || 'frühling-2026'}
        />
        <UtmField
          label="utm_term"
          value={briefing.utm?.term ?? ''}
          onChange={(v) => onBriefingPatch({ utm: { ...briefing.utm, term: v || undefined } })}
          placeholder="optional"
        />
      </div>
      <p className="mt-2 rounded-md border border-zinc-200 bg-zinc-50 px-2 py-1.5 text-[10px] leading-relaxed text-zinc-600 dark:border-zinc-800 dark:bg-zinc-900/50 dark:text-zinc-400">
        <strong>utm_content</strong> wird beim A/B-Versand automatisch pro Variante gesetzt
        (<code>A</code>, <code>B</code>, <code>C</code> …). So siehst du in Google Analytics direkt
        welche Variante besser performt hat.
      </p>
    </OptionalSection>
  );
}

function UtmField({
  label,
  value,
  onChange,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  return (
    <label className="flex flex-col gap-1">
      <span className="font-mono text-[10px] uppercase tracking-wider text-zinc-500">{label}</span>
      <input
        type="text"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        className="w-full rounded-md border border-zinc-200 bg-white px-2 py-1.5 text-xs focus:border-zinc-900 focus:outline-none dark:border-zinc-700 dark:bg-zinc-900"
      />
    </label>
  );
}

// ─── Champion-Test-Section ────────────────────────────────────────────────────
//
// A/B-Strategie: nur effektiv wenn ≥ 2 Subject-Varianten existieren. testPercent
// (5-50%) gehen sofort raus, der Rest wartet `winnerHours` (1-24h) auf den Winner
// (höchste Click-Rate; Tie-Break über Open-Rate). Bei nur 1 Variante: klassischer
// Even-Split-Send, der Toggle ist No-Op.

function ChampionTestSection({
  briefing,
  onBriefingPatch,
  variantCount,
}: {
  briefing: Briefing;
  onBriefingPatch: (patch: Partial<Briefing>) => void;
  variantCount?: number;
}) {
  const enabled = briefing.optional?.championTest ?? false;
  const champion = briefing.championTest;
  const onlyOneVariant = (variantCount ?? 1) < 2;

  return (
    <OptionalSection
      icon={<Sparkles className="h-4 w-4" />}
      title="Champion-Test (statt Even-Split)"
      subtitle="Bei A/B-Test mit ≥ 2 Varianten: zuerst kleiner Test-Send → Winner-Variante geht an die Mehrheit"
      enabled={enabled}
      onToggle={(v) => onBriefingPatch({ optional: { ...briefing.optional, championTest: v } })}
    >
      {onlyOneVariant && (
        <div className="mb-3 flex items-start gap-1.5 rounded-md border border-amber-200 bg-amber-50 px-2 py-1.5 text-[11px] text-amber-800 dark:border-amber-900/50 dark:bg-amber-950/30 dark:text-amber-200">
          <Info className="mt-0.5 h-3 w-3 shrink-0" />
          <span>Aktuell ist nur 1 Subject-Variante konfiguriert — der Champion-Test greift erst ab 2 Varianten. Du kannst die Einstellung trotzdem schon vornehmen.</span>
        </div>
      )}
      <div className="grid grid-cols-2 gap-3">
        <label className="flex flex-col gap-1">
          <span className="text-[11px] font-medium text-zinc-700 dark:text-zinc-300">
            Test-Anteil <span className="text-zinc-400">({champion?.testPercent ?? 20}%)</span>
          </span>
          <input
            type="range"
            min={5}
            max={50}
            step={5}
            value={champion?.testPercent ?? 20}
            onChange={(e) =>
              onBriefingPatch({
                championTest: {
                  testPercent: Number(e.target.value),
                  winnerHours: champion?.winnerHours ?? 4,
                },
              })
            }
            className="accent-[#ff006a]"
          />
          <span className="text-[10px] text-zinc-400">5–50% gehen sofort raus, der Rest wartet auf den Winner</span>
        </label>
        <label className="flex flex-col gap-1">
          <span className="text-[11px] font-medium text-zinc-700 dark:text-zinc-300">
            Winner nach <span className="text-zinc-400">({champion?.winnerHours ?? 4} h)</span>
          </span>
          <input
            type="range"
            min={1}
            max={24}
            step={1}
            value={champion?.winnerHours ?? 4}
            onChange={(e) =>
              onBriefingPatch({
                championTest: {
                  testPercent: champion?.testPercent ?? 20,
                  winnerHours: Number(e.target.value),
                },
              })
            }
            className="accent-[#ff006a]"
          />
          <span className="text-[10px] text-zinc-400">Wartezeit bevor die Winner-Variante an die restlichen 80% geht</span>
        </label>
      </div>
      <p className="mt-2 rounded-md border border-zinc-200 bg-zinc-50 px-2 py-1.5 text-[10px] leading-relaxed text-zinc-600 dark:border-zinc-800 dark:bg-zinc-900/50 dark:text-zinc-400">
        <strong>Auswahl-Metrik</strong>: Variante mit höchster Click-Rate gewinnt; Tie-Break über Open-Rate. Bei
        Gleichstand → Variante A.
      </p>
    </OptionalSection>
  );
}
