"use client";

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { api } from "@/lib/api";
import type {
  ProceedingType,
  TimelineResponse,
  DetermineResponse,
  TimelineEvent,
  Case,
} from "@/lib/types";
import { format, parseISO, isPast, isThisWeek, isBefore, addDays } from "date-fns";
import { de } from "date-fns/locale";
import {
  Scale,
  Calendar,
  ChevronRight,
  ChevronDown,
  GitBranch,
  Check,
  Clock,
  AlertTriangle,
  FileText,
  Users,
  Gavel,
  ArrowRight,
  RotateCcw,
  Loader2,
  CheckCircle2,
  FolderOpen,
} from "lucide-react";
import { useState, useCallback, useMemo } from "react";
import { toast } from "sonner";

// --- Helpers ---

function formatDuration(value: number, unit: string): string {
  if (value === 0) return "";
  const labels: Record<string, string> = {
    days: value === 1 ? "Tag" : "Tage",
    weeks: value === 1 ? "Woche" : "Wochen",
    months: value === 1 ? "Monat" : "Monate",
  };
  return `${value} ${labels[unit] || unit}`;
}

function getPartyIcon(party?: string) {
  switch (party) {
    case "claimant":
      return <Scale className="h-3.5 w-3.5" />;
    case "defendant":
      return <Users className="h-3.5 w-3.5" />;
    case "court":
      return <Gavel className="h-3.5 w-3.5" />;
    default:
      return <FileText className="h-3.5 w-3.5" />;
  }
}

function getPartyLabel(party?: string): string {
  switch (party) {
    case "claimant":
      return "Klaeger";
    case "defendant":
      return "Beklagter";
    case "court":
      return "Gericht";
    case "both":
      return "Beide Parteien";
    default:
      return "";
  }
}

function getEventTypeLabel(type?: string): string {
  switch (type) {
    case "filing":
      return "Einreichung";
    case "hearing":
      return "Verhandlung";
    case "decision":
      return "Entscheidung";
    default:
      return "";
  }
}

type Urgency = "past" | "overdue" | "this_week" | "upcoming" | "future" | "none";

function getUrgency(dateStr?: string): Urgency {
  if (!dateStr) return "none";
  const date = parseISO(dateStr);
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  if (isPast(date) && isBefore(date, today)) return "overdue";
  if (isThisWeek(date, { weekStartsOn: 1 })) return "this_week";
  if (isBefore(date, addDays(today, 30))) return "upcoming";
  return "future";
}

const urgencyStyles: Record<Urgency, { dot: string; text: string; bg: string }> = {
  past: { dot: "bg-neutral-400", text: "text-neutral-500", bg: "bg-neutral-50" },
  overdue: { dot: "bg-red-500", text: "text-red-700", bg: "bg-red-50" },
  this_week: { dot: "bg-amber-500", text: "text-amber-700", bg: "bg-amber-50" },
  upcoming: { dot: "bg-blue-500", text: "text-blue-700", bg: "bg-blue-50" },
  future: { dot: "bg-green-500", text: "text-green-700", bg: "bg-green-50" },
  none: { dot: "bg-neutral-300", text: "text-neutral-500", bg: "bg-neutral-50" },
};

// --- Spawn Extraction ---

function extractSpawns(events: TimelineEvent[]): TimelineEvent[] {
  const spawns: TimelineEvent[] = [];
  function walk(evts: TimelineEvent[]) {
    for (const ev of evts) {
      if (ev.is_spawn) spawns.push(ev);
      if (ev.children) walk(ev.children);
    }
  }
  walk(events);
  return spawns;
}

// --- Flat timeline extraction ---

function flattenTimeline(events: TimelineEvent[], depth = 0): (TimelineEvent & { depth: number })[] {
  const result: (TimelineEvent & { depth: number })[] = [];
  for (const ev of events) {
    result.push({ ...ev, depth });
    if (ev.children && ev.children.length > 0) {
      result.push(...flattenTimeline(ev.children, depth + 1));
    }
  }
  return result;
}

// --- Main Component ---

export function DeadlineWizard() {
  const [selectedType, setSelectedType] = useState<string>("");
  const [triggerDate, setTriggerDate] = useState("");
  const [conditions, setConditions] = useState<Record<string, boolean>>({});
  const [selectedCaseId, setSelectedCaseId] = useState<string>("");
  const [showBatchPanel, setShowBatchPanel] = useState(false);
  const queryClient = useQueryClient();

  // Fetch proceeding types
  const { data: proceedingTypes, isLoading: typesLoading } = useQuery({
    queryKey: ["proceeding-types"],
    queryFn: () => api.get<ProceedingType[]>("/proceeding-types"),
  });

  // Fetch timeline structure when type is selected
  const { data: timelineData } = useQuery({
    queryKey: ["timeline", selectedType],
    queryFn: () => api.get<TimelineResponse>(`/proceeding-types/${selectedType}/timeline`),
    enabled: !!selectedType,
  });

  // Determine mutation
  const determineMutation = useMutation({
    mutationFn: (params: { proceeding_type: string; trigger_event_date: string; conditions: Record<string, boolean> }) =>
      api.post<DetermineResponse>("/deadlines/determine", params),
  });

  // Cases for batch create
  const { data: cases } = useQuery({
    queryKey: ["cases"],
    queryFn: () => api.get<Case[]>("/cases"),
    enabled: showBatchPanel,
  });

  // Batch create mutation
  const batchMutation = useMutation({
    mutationFn: (params: { caseId: string; deadlines: { title: string; due_date: string; rule_code?: string }[] }) =>
      api.post(`/cases/${params.caseId}/deadlines/batch`, { deadlines: params.deadlines }),
    onSuccess: () => {
      toast.success("Alle Fristen wurden auf die Akte uebernommen");
      queryClient.invalidateQueries({ queryKey: ["deadlines"] });
      setShowBatchPanel(false);
    },
    onError: () => {
      toast.error("Fehler beim Erstellen der Fristen");
    },
  });

  // Spawns from timeline structure (for condition toggles)
  const spawns = useMemo(() => {
    if (!timelineData?.timeline) return [];
    return extractSpawns(timelineData.timeline);
  }, [timelineData]);

  // Calculate on type/date/condition change
  const calculate = useCallback(() => {
    if (!selectedType || !triggerDate) return;
    determineMutation.mutate({
      proceeding_type: selectedType,
      trigger_event_date: triggerDate,
      conditions,
    });
  }, [selectedType, triggerDate, conditions, determineMutation]);

  // Auto-calculate when date or conditions change
  const handleDateChange = (date: string) => {
    setTriggerDate(date);
    if (selectedType && date) {
      determineMutation.mutate({
        proceeding_type: selectedType,
        trigger_event_date: date,
        conditions,
      });
    }
  };

  const handleConditionToggle = (spawnId: string) => {
    const next = { ...conditions, [spawnId]: !conditions[spawnId] };
    setConditions(next);
    if (selectedType && triggerDate) {
      determineMutation.mutate({
        proceeding_type: selectedType,
        trigger_event_date: triggerDate,
        conditions: next,
      });
    }
  };

  const handleTypeSelect = (code: string) => {
    setSelectedType(code);
    setConditions({});
    if (triggerDate) {
      // Will recalculate once timeline loads
      determineMutation.reset();
    }
  };

  const handleReset = () => {
    setSelectedType("");
    setTriggerDate("");
    setConditions({});
    setShowBatchPanel(false);
    determineMutation.reset();
  };

  // Collect calculated deadlines for batch create
  const collectDeadlines = (events: TimelineEvent[]): { title: string; due_date: string; rule_code?: string }[] => {
    const result: { title: string; due_date: string; rule_code?: string }[] = [];
    for (const ev of events) {
      if (ev.date && ev.duration_value > 0) {
        result.push({ title: ev.name, due_date: ev.date, rule_code: ev.rule_code || undefined });
      }
      if (ev.children) result.push(...collectDeadlines(ev.children));
    }
    return result;
  };

  const results = determineMutation.data;
  const selectedPT = proceedingTypes?.find((pt) => pt.code === selectedType);

  return (
    <div className="space-y-5">
      {/* Step 1: Proceeding Type Selection */}
      <div className="rounded-lg border border-neutral-200 bg-white p-5">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2 text-sm font-medium text-neutral-900">
            <Scale className="h-4 w-4" />
            Verfahrensart waehlen
          </div>
          {selectedType && (
            <button
              onClick={handleReset}
              className="flex items-center gap-1 text-xs text-neutral-500 hover:text-neutral-700"
            >
              <RotateCcw className="h-3 w-3" />
              Zuruecksetzen
            </button>
          )}
        </div>

        <div className="mt-4 space-y-4">
          {typesLoading ? (
            <div className="flex justify-center py-4">
              <Loader2 className="h-5 w-5 animate-spin text-neutral-400" />
            </div>
          ) : (
            (() => {
              const grouped = new Map<string, ProceedingType[]>();
              for (const pt of proceedingTypes ?? []) {
                const key = pt.jurisdiction ?? "Sonstige";
                if (!grouped.has(key)) grouped.set(key, []);
                grouped.get(key)!.push(pt);
              }
              const labels: Record<string, string> = {
                UPC: "UPC-Verfahren",
                DE: "Deutsche Patentverfahren",
              };
              return Array.from(grouped.entries()).map(([jurisdiction, types]) => (
                <div key={jurisdiction}>
                  <div className="mb-2 text-xs font-medium text-neutral-500">
                    {labels[jurisdiction] ?? jurisdiction}
                  </div>
                  <div className="grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-6">
                    {types.map((pt) => (
                      <button
                        key={pt.id}
                        onClick={() => handleTypeSelect(pt.code)}
                        className={`rounded-lg border px-3 py-2.5 text-left transition-all ${
                          selectedType === pt.code
                            ? "border-neutral-900 bg-neutral-900 text-white shadow-sm"
                            : "border-neutral-200 bg-white text-neutral-700 hover:border-neutral-400 hover:bg-neutral-50"
                        }`}
                      >
                        <div className="flex items-center gap-1.5">
                          <div
                            className="h-2 w-2 rounded-full"
                            style={{ backgroundColor: pt.default_color }}
                          />
                          <span className="text-xs font-semibold">{pt.code}</span>
                        </div>
                        <div className="mt-1 text-xs leading-tight opacity-80">{pt.name}</div>
                      </button>
                    ))}
                  </div>
                </div>
              ));
            })()
          )}
        </div>
      </div>

      {/* Step 2: Date + Conditions */}
      {selectedType && (
        <div className="animate-fade-in rounded-lg border border-neutral-200 bg-white p-5">
          <div className="flex items-center gap-2 text-sm font-medium text-neutral-900">
            <Calendar className="h-4 w-4" />
            Ausloesendes Ereignis
          </div>

          <div className="mt-4 flex flex-col gap-4 sm:flex-row sm:items-end">
            <div className="flex-1">
              <label className="mb-1 block text-xs font-medium text-neutral-500">
                Datum des {selectedPT?.name || selectedType} (z.B. Klagezustellung)
              </label>
              <input
                type="date"
                value={triggerDate}
                onChange={(e) => handleDateChange(e.target.value)}
                className="w-full rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-900 outline-none transition-colors focus:border-neutral-400 focus:ring-1 focus:ring-neutral-400"
              />
            </div>

            {/* Condition toggles */}
            {spawns.length > 0 && (
              <div className="flex flex-wrap gap-2">
                {spawns.map((spawn) => (
                  <button
                    key={spawn.id}
                    onClick={() => handleConditionToggle(spawn.id)}
                    className={`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium transition-all ${
                      conditions[spawn.id]
                        ? "bg-neutral-900 text-white"
                        : "border border-neutral-300 bg-white text-neutral-600 hover:bg-neutral-50"
                    }`}
                  >
                    <GitBranch className="h-3 w-3" />
                    {spawn.spawn_label || spawn.name}
                    {conditions[spawn.id] && <Check className="h-3 w-3" />}
                  </button>
                ))}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Error */}
      {determineMutation.isError && (
        <div className="flex items-center gap-2 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
          <AlertTriangle className="h-4 w-4 shrink-0" />
          Fehler bei der Berechnung. Bitte Eingaben pruefen.
        </div>
      )}

      {/* Step 3: Calculated Timeline */}
      {results && results.timeline && (
        <div className="animate-fade-in space-y-3">
          {/* Header */}
          <div className="flex items-center justify-between">
            <div>
              <h3 className="text-sm font-medium text-neutral-900">
                Verfahrens-Timeline: {results.proceeding_name}
              </h3>
              <p className="mt-0.5 text-xs text-neutral-500">
                {results.total_deadlines} Ereignisse ab{" "}
                {format(parseISO(results.trigger_event_date), "dd. MMMM yyyy", { locale: de })}
              </p>
            </div>
            <button
              onClick={() => setShowBatchPanel(!showBatchPanel)}
              className="flex items-center gap-1.5 rounded-md bg-neutral-900 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-neutral-800"
            >
              <CheckCircle2 className="h-3.5 w-3.5" />
              Alle uebernehmen
            </button>
          </div>

          {/* Timeline visualization */}
          <div className="rounded-lg border border-neutral-200 bg-white">
            <TimelineTree events={results.timeline} conditions={conditions} depth={0} />
          </div>

          {/* Batch create panel */}
          {showBatchPanel && (
            <div className="animate-fade-in rounded-lg border border-neutral-200 bg-neutral-50 p-4">
              <div className="flex items-center gap-2 text-sm font-medium text-neutral-900">
                <FolderOpen className="h-4 w-4" />
                Fristen auf Akte uebernehmen
              </div>
              <div className="mt-3 flex gap-3">
                <select
                  value={selectedCaseId}
                  onChange={(e) => setSelectedCaseId(e.target.value)}
                  className="flex-1 rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-900 outline-none focus:border-neutral-400"
                >
                  <option value="">Akte waehlen...</option>
                  {cases
                    ?.filter((c) => c.status !== "closed")
                    .map((c) => (
                      <option key={c.id} value={c.id}>
                        {c.case_number} — {c.title}
                      </option>
                    ))}
                </select>
                <button
                  disabled={!selectedCaseId || batchMutation.isPending}
                  onClick={() => {
                    const deadlines = collectDeadlines(results.timeline);
                    if (deadlines.length === 0) return;
                    batchMutation.mutate({ caseId: selectedCaseId, deadlines });
                  }}
                  className="flex items-center gap-1.5 rounded-md bg-neutral-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-neutral-800 disabled:cursor-not-allowed disabled:opacity-50"
                >
                  {batchMutation.isPending ? (
                    <Loader2 className="h-3.5 w-3.5 animate-spin" />
                  ) : (
                    <ArrowRight className="h-3.5 w-3.5" />
                  )}
                  {batchMutation.isPending ? "Erstelle..." : `${collectDeadlines(results.timeline).length} Fristen erstellen`}
                </button>
              </div>
            </div>
          )}
        </div>
      )}

      {/* Empty state */}
      {!results && !determineMutation.isPending && selectedType && triggerDate && (
        <div className="flex items-center justify-center py-8">
          <Loader2 className="h-5 w-5 animate-spin text-neutral-400" />
        </div>
      )}

      {!selectedType && (
        <div className="flex flex-col items-center rounded-lg border border-dashed border-neutral-300 bg-white px-6 py-12 text-center">
          <div className="rounded-xl bg-neutral-100 p-3">
            <Scale className="h-6 w-6 text-neutral-400" />
          </div>
          <p className="mt-3 text-sm font-medium text-neutral-700">
            Fristenbestimmung
          </p>
          <p className="mt-1 max-w-sm text-xs text-neutral-500">
            Waehlen Sie die Verfahrensart und geben Sie das Datum des ausloesenden Ereignisses ein.
            Alle Fristen des Verfahrens werden automatisch berechnet.
          </p>
        </div>
      )}
    </div>
  );
}

// --- Timeline Tree Component ---

function TimelineTree({
  events,
  conditions,
  depth,
}: {
  events: TimelineEvent[];
  conditions: Record<string, boolean>;
  depth: number;
}) {
  return (
    <>
      {events.map((ev, i) => (
        <TimelineNode
          key={ev.id}
          event={ev}
          conditions={conditions}
          depth={depth}
          isLast={i === events.length - 1}
        />
      ))}
    </>
  );
}

function TimelineNode({
  event: ev,
  conditions,
  depth,
  isLast,
}: {
  event: TimelineEvent;
  conditions: Record<string, boolean>;
  depth: number;
  isLast: boolean;
}) {
  const [expanded, setExpanded] = useState(true);

  // Skip inactive spawns
  if (ev.is_spawn && !conditions[ev.id]) return null;

  const hasChildren = ev.children && ev.children.length > 0;
  const visibleChildren = ev.children?.filter(
    (c) => !c.is_spawn || conditions[c.id]
  );
  const hasVisibleChildren = visibleChildren && visibleChildren.length > 0;

  const urgency = getUrgency(ev.date);
  const styles = urgencyStyles[urgency];
  const duration = formatDuration(ev.duration_value, ev.duration_unit);
  const isConditional = ev.has_condition && ev.condition_rule_id;

  return (
    <>
      <div
        className={`group relative flex gap-3 px-4 py-3 transition-colors hover:bg-neutral-50 ${
          !isLast && depth === 0 ? "border-b border-neutral-100" : ""
        }`}
        style={{ paddingLeft: `${16 + depth * 24}px` }}
      >
        {/* Timeline connector */}
        <div className="flex flex-col items-center pt-1">
          <div className={`h-3 w-3 shrink-0 rounded-full border-2 border-white shadow-sm ${styles.dot}`} />
          {!isLast && <div className="mt-1 w-px flex-1 bg-neutral-200" />}
        </div>

        {/* Content */}
        <div className="min-w-0 flex-1">
          <div className="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between sm:gap-2">
            <div className="flex items-center gap-1.5">
              {hasVisibleChildren && (
                <button
                  onClick={() => setExpanded(!expanded)}
                  className="text-neutral-400 hover:text-neutral-600"
                >
                  {expanded ? (
                    <ChevronDown className="h-3.5 w-3.5" />
                  ) : (
                    <ChevronRight className="h-3.5 w-3.5" />
                  )}
                </button>
              )}
              {ev.is_spawn && (
                <GitBranch className="h-3.5 w-3.5 text-violet-500" />
              )}
              <span className="text-sm font-medium text-neutral-900">{ev.name}</span>
              {!ev.is_mandatory && (
                <span className="rounded bg-neutral-100 px-1 py-0.5 text-[10px] text-neutral-500">
                  optional
                </span>
              )}
            </div>

            {/* Date */}
            {ev.date && (
              <div className="flex items-center gap-1.5 shrink-0">
                {ev.was_adjusted && (
                  <span className="text-[10px] text-amber-600" title={`Original: ${ev.original_date}`}>
                    angepasst
                  </span>
                )}
                <span className={`text-sm font-medium tabular-nums ${styles.text}`}>
                  {format(parseISO(ev.date), "dd.MM.yyyy")}
                </span>
              </div>
            )}
          </div>

          {/* Meta row */}
          <div className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-neutral-500">
            {ev.primary_party && (
              <span className="flex items-center gap-0.5">
                {getPartyIcon(ev.primary_party)}
                {getPartyLabel(ev.primary_party)}
              </span>
            )}
            {ev.event_type && (
              <>
                <span className="text-neutral-300">·</span>
                <span>{getEventTypeLabel(ev.event_type)}</span>
              </>
            )}
            {duration && (
              <>
                <span className="text-neutral-300">·</span>
                <span className="flex items-center gap-0.5">
                  <Clock className="h-3 w-3" />
                  {duration}
                </span>
              </>
            )}
            {ev.rule_code && (
              <>
                <span className="text-neutral-300">·</span>
                <span className="rounded bg-neutral-100 px-1 py-0.5 font-mono text-[10px]">
                  {ev.rule_code}
                </span>
              </>
            )}
            {isConditional && (
              <>
                <span className="text-neutral-300">·</span>
                <span className="text-violet-600">
                  bedingt{ev.alt_rule_code ? ` (${ev.alt_rule_code})` : ""}
                </span>
              </>
            )}
          </div>

          {/* Notes */}
          {ev.deadline_notes && (
            <p className="mt-1 text-xs text-neutral-400 italic">{ev.deadline_notes}</p>
          )}
        </div>
      </div>

      {/* Children */}
      {expanded && hasVisibleChildren && (
        <TimelineTree events={visibleChildren!} conditions={conditions} depth={depth + 1} />
      )}
    </>
  );
}
