"use client";

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { api } from "@/lib/api";
import type {
  ProceedingType,
  RuleTreeNode,
  CalculateResponse,
  Case,
} from "@/lib/types";
import { format, parseISO } from "date-fns";
import { de } from "date-fns/locale";
import {
  Scale,
  Users,
  Gavel,
  FileText,
  Clock,
  CalendarDays,
  AlertTriangle,
  ChevronRight,
  RotateCcw,
  Loader2,
  Check,
  FolderOpen,
} from "lucide-react";
import { useState, 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 "";
  }
}

interface FlatRule {
  id: string;
  name: string;
  duration_value: number;
  duration_unit: string;
  rule_code?: string;
  primary_party?: string;
  event_type?: string;
  is_mandatory: boolean;
  deadline_notes?: string;
  description?: string;
  depth: number;
}

function flattenRuleTree(nodes: RuleTreeNode[], depth = 0): FlatRule[] {
  const result: FlatRule[] = [];
  for (const node of nodes) {
    result.push({
      id: node.id,
      name: node.name,
      duration_value: node.duration_value,
      duration_unit: node.duration_unit,
      rule_code: node.rule_code,
      primary_party: node.primary_party,
      event_type: node.event_type,
      is_mandatory: node.is_mandatory,
      deadline_notes: node.deadline_notes,
      description: node.description,
      depth,
    });
    if (node.children && node.children.length > 0) {
      result.push(...flattenRuleTree(node.children, depth + 1));
    }
  }
  return result;
}

// --- Group labels ---

const categoryLabels: Record<string, string> = {
  hauptverfahren: "Hauptverfahren",
  im_verfahren: "Verfahren im Verfahren",
  rechtsbehelf: "Rechtsbehelfe",
};

const jurisdictionLabels: Record<string, string> = {
  UPC: "UPC",
  DE: "Deutsche Patentverfahren",
};

interface TypeGroup {
  key: string;
  label: string;
  items: ProceedingType[];
}

function groupProceedingTypes(types: ProceedingType[]): TypeGroup[] {
  const groups: TypeGroup[] = [];
  const seen = new Set<string>();
  for (const pt of types) {
    const j = pt.jurisdiction ?? "Sonstige";
    const c = pt.category ?? "hauptverfahren";
    const key = `${j}::${c}`;
    if (!seen.has(key)) {
      seen.add(key);
      const jLabel = jurisdictionLabels[j] ?? j;
      const cLabel = categoryLabels[c] ?? c;
      const label = j === "DE" ? jLabel : `${jLabel} — ${cLabel}`;
      groups.push({ key, label, items: [] });
    }
    groups.find((g) => g.key === key)!.items.push(pt);
  }
  return groups;
}

// --- Main Component ---

export function FristenRechner() {
  const [selectedType, setSelectedType] = useState<string | null>(null);
  const [expandedRuleId, setExpandedRuleId] = useState<string | null>(null);
  const [triggerDate, setTriggerDate] = useState(
    new Date().toISOString().split("T")[0],
  );
  const [calcResults, setCalcResults] = useState<
    Record<string, { due_date: string; original_due_date: string; was_adjusted: boolean }>
  >({});
  const [savingRuleId, setSavingRuleId] = useState<string | null>(null);
  const [selectedCaseId, setSelectedCaseId] = useState<string>("");
  const queryClient = useQueryClient();

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

  // Fetch rule tree when type is selected
  const { data: ruleTree, isLoading: rulesLoading } = useQuery({
    queryKey: ["deadline-rules", selectedType],
    queryFn: () => api.get<RuleTreeNode[]>(`/deadline-rules/${selectedType}`),
    enabled: !!selectedType,
  });

  // Fetch cases for "save to case"
  const { data: cases } = useQuery({
    queryKey: ["cases"],
    queryFn: () => api.get<Case[]>("/cases"),
    enabled: savingRuleId !== null,
  });

  // Calculate single deadline
  const calcMutation = useMutation({
    mutationFn: (params: {
      proceeding_type: string;
      trigger_event_date: string;
      selected_rule_ids: string[];
    }) => api.post<CalculateResponse>("/deadlines/calculate", params),
    onSuccess: (data, variables) => {
      if (data.deadlines && data.deadlines.length > 0) {
        const d = data.deadlines[0];
        setCalcResults((prev) => ({
          ...prev,
          [variables.selected_rule_ids[0]]: {
            due_date: d.due_date,
            original_due_date: d.original_due_date,
            was_adjusted: d.was_adjusted,
          },
        }));
      }
    },
  });

  // Save deadline to case
  const saveMutation = useMutation({
    mutationFn: (params: {
      caseId: string;
      deadline: { title: string; due_date: string; original_due_date?: string; rule_code?: string };
    }) =>
      api.post(`/cases/${params.caseId}/deadlines`, {
        title: params.deadline.title,
        due_date: params.deadline.due_date,
        original_due_date: params.deadline.original_due_date,
        rule_code: params.deadline.rule_code,
        source: "calculator",
      }),
    onSuccess: () => {
      toast.success("Frist auf Akte gespeichert");
      queryClient.invalidateQueries({ queryKey: ["deadlines"] });
      setSavingRuleId(null);
      setSelectedCaseId("");
    },
    onError: () => {
      toast.error("Fehler beim Speichern");
    },
  });

  // Flat list of rules
  const flatRules = useMemo(() => {
    if (!ruleTree) return [];
    return flattenRuleTree(ruleTree);
  }, [ruleTree]);

  // Groups
  const groups = useMemo(() => {
    if (!proceedingTypes) return [];
    return groupProceedingTypes(proceedingTypes);
  }, [proceedingTypes]);

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

  function handleTypeSelect(code: string) {
    setSelectedType(code);
    setExpandedRuleId(null);
    setCalcResults({});
    setSavingRuleId(null);
  }

  function handleReset() {
    setSelectedType(null);
    setExpandedRuleId(null);
    setCalcResults({});
    setSavingRuleId(null);
    setSelectedCaseId("");
  }

  function handleRuleClick(ruleId: string) {
    if (expandedRuleId === ruleId) {
      setExpandedRuleId(null);
      return;
    }
    setExpandedRuleId(ruleId);
    setSavingRuleId(null);
    // Auto-calculate with current date
    if (selectedType && triggerDate) {
      calcMutation.mutate({
        proceeding_type: selectedType,
        trigger_event_date: triggerDate,
        selected_rule_ids: [ruleId],
      });
    }
  }

  function handleDateChange(ruleId: string, date: string) {
    setTriggerDate(date);
    if (selectedType && date) {
      calcMutation.mutate({
        proceeding_type: selectedType,
        trigger_event_date: date,
        selected_rule_ids: [ruleId],
      });
    }
  }

  return (
    <div className="space-y-6">
      {/* Step 1: Proceeding Type Cards */}
      <div>
        <div className="mb-4 flex items-center justify-between">
          <h2 className="text-sm font-medium text-neutral-900">
            Verfahrensart waehlen
          </h2>
          {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>

        {typesLoading ? (
          <div className="flex justify-center py-8">
            <Loader2 className="h-5 w-5 animate-spin text-neutral-400" />
          </div>
        ) : (
          <div className="space-y-5">
            {groups.map((group) => (
              <div key={group.key}>
                <div className="mb-2 text-xs font-medium uppercase tracking-wide text-neutral-400">
                  {group.label}
                </div>
                <div className="flex flex-wrap gap-2">
                  {group.items.map((pt) => {
                    const isSelected = selectedType === pt.code;
                    return (
                      <button
                        key={pt.id}
                        onClick={() => handleTypeSelect(pt.code)}
                        className={`rounded-lg border px-3 py-2 text-sm transition-all ${
                          isSelected
                            ? "border-neutral-900 bg-neutral-900 text-white shadow-sm"
                            : "border-neutral-200 bg-white text-neutral-700 hover:border-neutral-300 hover:shadow-sm"
                        }`}
                      >
                        {pt.name}
                      </button>
                    );
                  })}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Step 2: Deadline Rules for Selected Type */}
      {selectedType && (
        <div className="animate-fade-in">
          <div className="mb-3 flex items-center justify-between">
            <div>
              <h2 className="text-sm font-medium text-neutral-900">
                Fristen: {selectedPT?.name}
              </h2>
              {flatRules.length > 0 && (
                <p className="mt-0.5 text-xs text-neutral-500">
                  {flatRules.length} Fristen &mdash; Frist anklicken zum Berechnen
                </p>
              )}
            </div>
          </div>

          {rulesLoading ? (
            <div className="flex justify-center py-8">
              <Loader2 className="h-5 w-5 animate-spin text-neutral-400" />
            </div>
          ) : flatRules.length === 0 ? (
            <div className="rounded-lg border border-dashed border-neutral-300 bg-white px-6 py-8 text-center text-sm text-neutral-500">
              Keine Fristenregeln fuer diesen Verfahrenstyp hinterlegt.
            </div>
          ) : (
            <div className="rounded-lg border border-neutral-200 bg-white divide-y divide-neutral-100">
              {flatRules.map((rule, i) => {
                const isExpanded = expandedRuleId === rule.id;
                const result = calcResults[rule.id];
                const duration = formatDuration(rule.duration_value, rule.duration_unit);

                return (
                  <div key={rule.id}>
                    {/* Rule Row */}
                    <button
                      onClick={() => handleRuleClick(rule.id)}
                      className={`flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-neutral-50 ${
                        isExpanded ? "bg-neutral-50" : ""
                      }`}
                      style={{ paddingLeft: `${16 + rule.depth * 20}px` }}
                    >
                      {/* Timeline dot + connector */}
                      <div className="flex flex-col items-center">
                        <div
                          className={`h-2.5 w-2.5 shrink-0 rounded-full border-2 ${
                            isExpanded
                              ? "border-neutral-900 bg-neutral-900"
                              : "border-neutral-300 bg-white"
                          }`}
                        />
                        {i < flatRules.length - 1 && (
                          <div className="mt-0.5 h-3 w-px bg-neutral-200" />
                        )}
                      </div>

                      {/* Content */}
                      <div className="min-w-0 flex-1">
                        <div className="flex items-center gap-2">
                          <span className="text-sm font-medium text-neutral-900">
                            {rule.name}
                          </span>
                          {!rule.is_mandatory && (
                            <span className="rounded bg-neutral-100 px-1 py-0.5 text-[10px] text-neutral-400">
                              optional
                            </span>
                          )}
                        </div>
                        <div className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-neutral-500">
                          {duration && (
                            <span className="flex items-center gap-0.5">
                              <Clock className="h-3 w-3" />
                              {duration}
                            </span>
                          )}
                          {rule.rule_code && (
                            <>
                              <span className="text-neutral-300">&middot;</span>
                              <span className="rounded bg-neutral-100 px-1 py-0.5 font-mono text-[10px]">
                                {rule.rule_code}
                              </span>
                            </>
                          )}
                          {rule.primary_party && (
                            <>
                              <span className="text-neutral-300">&middot;</span>
                              <span className="flex items-center gap-0.5">
                                {getPartyIcon(rule.primary_party)}
                                {getPartyLabel(rule.primary_party)}
                              </span>
                            </>
                          )}
                        </div>
                      </div>

                      {/* Chevron */}
                      <ChevronRight
                        className={`h-4 w-4 shrink-0 text-neutral-400 transition-transform ${
                          isExpanded ? "rotate-90" : ""
                        }`}
                      />
                    </button>

                    {/* Step 3: Expanded Calculation Panel */}
                    {isExpanded && (
                      <div className="border-t border-neutral-100 bg-neutral-50 px-4 py-4 animate-fade-in"
                        style={{ paddingLeft: `${36 + rule.depth * 20}px` }}
                      >
                        <div className="flex flex-col gap-4 sm:flex-row sm:items-end">
                          {/* Date picker */}
                          <div>
                            <label className="mb-1 block text-xs font-medium text-neutral-500">
                              Ausloesedatum
                            </label>
                            <input
                              type="date"
                              value={triggerDate}
                              onChange={(e) =>
                                handleDateChange(rule.id, e.target.value)
                              }
                              className="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>

                          {/* Result */}
                          {calcMutation.isPending &&
                            calcMutation.variables?.selected_rule_ids[0] === rule.id ? (
                            <div className="flex items-center gap-2 text-sm text-neutral-500">
                              <Loader2 className="h-4 w-4 animate-spin" />
                              Berechne...
                            </div>
                          ) : result ? (
                            <div className="flex items-center gap-4">
                              <div>
                                <div className="text-xs font-medium text-neutral-500">
                                  Fristende
                                </div>
                                <div className="flex items-center gap-2">
                                  <CalendarDays className="h-4 w-4 text-neutral-700" />
                                  <span className="text-lg font-semibold tabular-nums text-neutral-900">
                                    {format(
                                      parseISO(result.due_date),
                                      "dd. MMMM yyyy",
                                      { locale: de },
                                    )}
                                  </span>
                                </div>
                                {result.was_adjusted && (
                                  <div className="mt-0.5 flex items-center gap-1 text-xs text-amber-600">
                                    <AlertTriangle className="h-3 w-3" />
                                    Angepasst (Original:{" "}
                                    {format(
                                      parseISO(result.original_due_date),
                                      "dd.MM.yyyy",
                                    )}
                                    )
                                  </div>
                                )}
                              </div>

                              {/* Save to case button */}
                              <button
                                onClick={(e) => {
                                  e.stopPropagation();
                                  setSavingRuleId(
                                    savingRuleId === rule.id ? null : rule.id,
                                  );
                                }}
                                className="flex items-center gap-1 rounded-md border border-neutral-200 bg-white px-2.5 py-1.5 text-xs font-medium text-neutral-700 transition-colors hover:bg-neutral-50"
                              >
                                <FolderOpen className="h-3.5 w-3.5" />
                                Auf Akte
                              </button>
                            </div>
                          ) : null}
                        </div>

                        {/* Save to case panel */}
                        {savingRuleId === rule.id && result && (
                          <div className="mt-3 flex items-center gap-2 animate-fade-in">
                            <select
                              value={selectedCaseId}
                              onChange={(e) =>
                                setSelectedCaseId(e.target.value)
                              }
                              className="flex-1 rounded-md border border-neutral-200 bg-white px-3 py-1.5 text-xs 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 || saveMutation.isPending
                              }
                              onClick={() => {
                                saveMutation.mutate({
                                  caseId: selectedCaseId,
                                  deadline: {
                                    title: rule.name,
                                    due_date: result.due_date,
                                    original_due_date: result.was_adjusted
                                      ? result.original_due_date
                                      : undefined,
                                    rule_code: rule.rule_code,
                                  },
                                });
                              }}
                              className="flex items-center gap-1 rounded-md bg-neutral-900 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-neutral-800 disabled:opacity-50"
                            >
                              {saveMutation.isPending ? (
                                <Loader2 className="h-3 w-3 animate-spin" />
                              ) : (
                                <Check className="h-3 w-3" />
                              )}
                              Speichern
                            </button>
                          </div>
                        )}

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

      {/* Empty state */}
      {!selectedType && !typesLoading && (
        <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">
            Fristenrechner
          </p>
          <p className="mt-1 max-w-sm text-xs text-neutral-500">
            Waehlen Sie oben eine Verfahrensart, um alle zugehoerigen Fristen
            anzuzeigen und einzelne Termine zu berechnen.
          </p>
        </div>
      )}

      {/* Calculation error */}
      {calcMutation.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>
      )}
    </div>
  );
}
