"use client";

import { RotateCcw, X } from "lucide-react";
import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import { applyReorg, undoReorg, type ReorgMovePayload } from "@/actions/reorg";
import { Button } from "@/components/ui/Button";
import { Field, SelectField, TextField } from "@/components/ui/Field";
import { Lookup } from "@/components/ui/Lookup";
import { useToast } from "@/components/ui/Toast";
import { fmtDate } from "@/lib/format";
import type { OrgDepartment, OrgDivision, OrgEmployee, OrgTeam, ReorgScenarioSummary } from "./types";

type ChangeKind = "emp" | "team" | "abt" | "dept";

type PendingMove = {
  id: string;
  kind: ChangeKind;
  label: string;
  employeeIds: string[];
  targetTeamId: string;
  targetTeamLabel: string;
};

const KIND_LABELS: Record<ChangeKind, string> = {
  emp: "Mitarbeiter:in(nen)",
  team: "Ganzes Team",
  abt: "Ganze Abteilung",
  dept: "Ganzer Bereich",
};

type ReorgWorkbenchProps = {
  employees: OrgEmployee[];
  divisions: OrgDivision[];
  departments: OrgDepartment[];
  teams: OrgTeam[];
  reorgScenarios: ReorgScenarioSummary[];
};

export function ReorgWorkbench({ employees, divisions, departments, teams, reorgScenarios }: ReorgWorkbenchProps) {
  const { showToast } = useToast();
  const router = useRouter();

  const [name, setName] = useState("");
  const [effectiveDate, setEffectiveDate] = useState("");
  const [changeType, setChangeType] = useState<ChangeKind>("emp");
  const [selectedEmployees, setSelectedEmployees] = useState<OrgEmployee[]>([]);
  const [sourceTeamId, setSourceTeamId] = useState("");
  const [sourceDeptId, setSourceDeptId] = useState("");
  const [sourceDivisionId, setSourceDivisionId] = useState("");
  const [targetDivisionId, setTargetDivisionId] = useState("");
  const [targetTeamId, setTargetTeamId] = useState("");
  const [pendingMoves, setPendingMoves] = useState<PendingMove[]>([]);
  const [applying, setApplying] = useState(false);
  const [undoingId, setUndoingId] = useState<string | null>(null);

  const divisionById = useMemo(() => new Map(divisions.map((d) => [d.id, d])), [divisions]);
  const departmentById = useMemo(() => new Map(departments.map((d) => [d.id, d])), [departments]);
  const teamById = useMemo(() => new Map(teams.map((t) => [t.id, t])), [teams]);
  const teamDivisionId = useMemo(() => {
    const deptDivision = new Map(departments.map((d) => [d.id, d.division_id]));
    const m = new Map<string, string>();
    for (const t of teams) m.set(t.id, deptDivision.get(t.department_id) ?? "");
    return m;
  }, [teams, departments]);
  const teamsInTargetDivision = useMemo(
    () => teams.filter((t) => teamDivisionId.get(t.id) === targetDivisionId),
    [teams, teamDivisionId, targetDivisionId]
  );

  async function searchLocalEmployees(query: string): Promise<OrgEmployee[]> {
    const q = query.trim().toLowerCase();
    if (q.length < 2) return [];
    return employees
      .filter(
        (e) =>
          !selectedEmployees.some((s) => s.id === e.id) &&
          (`${e.first_name} ${e.last_name}`.toLowerCase().includes(q) || e.job_title.toLowerCase().includes(q))
      )
      .slice(0, 20);
  }

  function resolveEmployeeIds(): string[] {
    if (changeType === "emp") return selectedEmployees.map((e) => e.id);
    if (changeType === "team") return employees.filter((e) => e.team_id === sourceTeamId).map((e) => e.id);
    if (changeType === "abt") {
      const teamIds = new Set(teams.filter((t) => t.department_id === sourceDeptId).map((t) => t.id));
      return employees.filter((e) => e.team_id && teamIds.has(e.team_id)).map((e) => e.id);
    }
    return employees.filter((e) => e.division_id === sourceDivisionId).map((e) => e.id);
  }

  function sourceLabel(): string {
    if (changeType === "emp") return `${selectedEmployees.length} Mitarbeiter:in(nen)`;
    if (changeType === "team") return `Team ${teamById.get(sourceTeamId)?.name ?? ""}`;
    if (changeType === "abt") return `Abteilung ${departmentById.get(sourceDeptId)?.name ?? ""}`;
    return `Bereich ${divisionById.get(sourceDivisionId)?.name ?? ""}`;
  }

  function handleAddMove() {
    const employeeIds = resolveEmployeeIds();
    if (employeeIds.length === 0) {
      showToast("Keine Mitarbeiter:innen in der Auswahl gefunden.", "error");
      return;
    }
    if (!targetTeamId) {
      showToast("Bitte ein Ziel-Team wählen.", "error");
      return;
    }
    const targetTeam = teamById.get(targetTeamId);
    setPendingMoves((prev) => [
      ...prev,
      {
        id: crypto.randomUUID(),
        kind: changeType,
        label: sourceLabel(),
        employeeIds,
        targetTeamId,
        targetTeamLabel: targetTeam?.name ?? "",
      },
    ]);
    setSelectedEmployees([]);
    setSourceTeamId("");
    setSourceDeptId("");
    setSourceDivisionId("");
  }

  function removeMove(id: string) {
    setPendingMoves((prev) => prev.filter((m) => m.id !== id));
  }

  const divisionBefore = useMemo(() => {
    const m = new Map<string, number>();
    for (const e of employees) m.set(e.division_id, (m.get(e.division_id) ?? 0) + 1);
    return m;
  }, [employees]);

  const divisionDelta = useMemo(() => {
    const m = new Map<string, number>();
    const employeeById = new Map(employees.map((e) => [e.id, e]));
    for (const move of pendingMoves) {
      const targetDivId = teamDivisionId.get(move.targetTeamId);
      for (const empId of move.employeeIds) {
        const emp = employeeById.get(empId);
        if (!emp || !targetDivId || emp.division_id === targetDivId) continue;
        m.set(emp.division_id, (m.get(emp.division_id) ?? 0) - 1);
        m.set(targetDivId, (m.get(targetDivId) ?? 0) + 1);
      }
    }
    return m;
  }, [pendingMoves, employees, teamDivisionId]);

  async function handleApply() {
    if (!name || !effectiveDate || pendingMoves.length === 0) {
      showToast("Bitte Name, Datum und mindestens eine Änderung angeben.", "error");
      return;
    }
    setApplying(true);
    const moves: ReorgMovePayload[] = pendingMoves.map((m) => ({
      kind: m.kind,
      label: m.label,
      employee_ids: m.employeeIds,
      target_team_id: m.targetTeamId,
    }));
    const result = await applyReorg({ name, effective_date: effectiveDate, moves });
    setApplying(false);
    if (result.success) {
      showToast("Reorganisation durchgeführt.");
      setPendingMoves([]);
      setName("");
      setEffectiveDate("");
      router.refresh();
    } else {
      showToast(result.error ?? "Fehler bei der Reorganisation.", "error");
    }
  }

  async function handleUndo(scenarioId: string) {
    setUndoingId(scenarioId);
    const result = await undoReorg({ scenario_id: scenarioId });
    setUndoingId(null);
    if (result.success) {
      showToast("Reorganisation rückgängig gemacht.");
      router.refresh();
    } else {
      showToast(result.error ?? "Fehler beim Rückgängigmachen.", "error");
    }
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="rounded border border-border bg-white p-4">
        <h2 className="mb-3 text-sm font-bold text-ink">Neue Reorganisation</h2>
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
          <TextField label="Name der Reorganisation" required value={name} onChange={setName} />
          <TextField label="Wirksam ab" required type="date" value={effectiveDate} onChange={setEffectiveDate} />
        </div>

        <fieldset className="mt-4">
          <legend className="sr-only">Art der Änderung</legend>
          <div className="flex flex-wrap gap-2">
            {(Object.keys(KIND_LABELS) as ChangeKind[]).map((kind) => (
              <button
                key={kind}
                type="button"
                aria-pressed={changeType === kind}
                onClick={() => setChangeType(kind)}
                className={`rounded px-3 py-1.5 text-sm font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-500 ${
                  changeType === kind ? "bg-brand-500 text-white" : "border border-border text-ink-body hover:bg-surface"
                }`}
              >
                {KIND_LABELS[kind]}
              </button>
            ))}
          </div>
        </fieldset>

        <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2">
          <div>
            {changeType === "emp" && (
              <div className="flex flex-col gap-2">
                <Field label="Quelle: Mitarbeiter:innen">
                  {(p) => (
                    <Lookup<OrgEmployee>
                      {...p}
                      placeholder="Mitarbeiter:in suchen…"
                      onSearch={searchLocalEmployees}
                      onSelect={(e) => setSelectedEmployees((prev) => [...prev, e])}
                      renderResult={(e) => (
                        <div>
                          <div className="font-semibold text-ink">
                            {e.first_name} {e.last_name}
                          </div>
                          <div className="text-xs text-ink-muted">{e.job_title}</div>
                        </div>
                      )}
                    />
                  )}
                </Field>
                {selectedEmployees.length > 0 && (
                  <div className="flex flex-wrap gap-1.5">
                    {selectedEmployees.map((e) => (
                      <span key={e.id} className="flex items-center gap-1 rounded-full bg-brand-100 px-2.5 py-1 text-xs font-semibold text-brand-700">
                        {e.first_name} {e.last_name}
                        <button
                          type="button"
                          aria-label={`${e.first_name} ${e.last_name} aus der Auswahl entfernen`}
                          onClick={() => setSelectedEmployees((prev) => prev.filter((s) => s.id !== e.id))}
                          className="rounded focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-brand-500"
                        >
                          <X className="h-3 w-3" />
                        </button>
                      </span>
                    ))}
                  </div>
                )}
              </div>
            )}
            {changeType === "team" && (
              <SelectField
                label="Quelle: Team"
                value={sourceTeamId}
                onChange={setSourceTeamId}
                placeholder="Team wählen…"
                options={teams.map((t) => ({ value: t.id, label: t.name }))}
              />
            )}
            {changeType === "abt" && (
              <SelectField
                label="Quelle: Abteilung"
                value={sourceDeptId}
                onChange={setSourceDeptId}
                placeholder="Abteilung wählen…"
                options={departments.map((d) => ({ value: d.id, label: d.name }))}
              />
            )}
            {changeType === "dept" && (
              <SelectField
                label="Quelle: Bereich"
                value={sourceDivisionId}
                onChange={setSourceDivisionId}
                placeholder="Bereich wählen…"
                options={divisions.map((d) => ({ value: d.id, label: d.name }))}
              />
            )}
          </div>

          <div className="flex flex-col gap-2">
            <SelectField
              label="Ziel-Bereich"
              required
              value={targetDivisionId}
              onChange={(v) => {
                setTargetDivisionId(v);
                setTargetTeamId("");
              }}
              placeholder="Ziel-Bereich wählen…"
              options={divisions.map((d) => ({ value: d.id, label: d.name }))}
            />
            <SelectField
              label="Ziel-Team"
              required
              value={targetTeamId}
              onChange={setTargetTeamId}
              placeholder="Ziel-Team wählen…"
              options={teamsInTargetDivision.map((t) => ({ value: t.id, label: t.name }))}
            />
          </div>
        </div>

        <Button variant="secondary" onClick={handleAddMove} className="mt-4">
          + Zur Reorganisation hinzufügen
        </Button>
      </div>

      {pendingMoves.length > 0 && (
        <div className="rounded border border-border bg-white p-4">
          <h2 className="mb-3 text-sm font-bold text-ink">Geplante Änderungen ({pendingMoves.length})</h2>
          <ul className="mb-4 flex flex-col divide-y divide-border">
            {pendingMoves.map((m) => (
              <li key={m.id} className="flex items-center justify-between py-2 text-sm">
                <div>
                  <span className="mr-2 rounded-full bg-purple-bg px-2 py-0.5 text-xs font-semibold text-purple-text">{KIND_LABELS[m.kind]}</span>
                  <span className="text-ink">
                    {m.label} → {m.targetTeamLabel}
                  </span>
                  <span className="ml-2 text-xs text-ink-muted">({m.employeeIds.length} Mitarbeiter:innen)</span>
                </div>
                <Button
                  variant="icon"
                  onClick={() => removeMove(m.id)}
                  aria-label={`${m.label} aus der Reorganisation entfernen`}
                  className="hover:!text-danger-solid"
                >
                  <X className="h-4 w-4" />
                </Button>
              </li>
            ))}
          </ul>

          <h3 className="mb-2 text-xs font-semibold uppercase tracking-wide text-ink-muted">Auswirkung auf Headcount</h3>
          <table className="w-full text-sm">
            <thead>
              <tr className="text-left text-xs text-ink-muted">
                <th className="py-1 pr-3">Bereich</th>
                <th className="py-1 pr-3">Vorher</th>
                <th className="py-1 pr-3">Nachher</th>
                <th className="py-1 pr-3">Δ</th>
              </tr>
            </thead>
            <tbody>
              {Array.from(divisionDelta.entries())
                .filter(([, delta]) => delta !== 0)
                .map(([divId, delta]) => {
                  const before = divisionBefore.get(divId) ?? 0;
                  return (
                    <tr key={divId} className="border-t border-border">
                      <td className="py-1.5 pr-3 text-ink">{divisionById.get(divId)?.name}</td>
                      <td className="py-1.5 pr-3 text-ink-body">{before}</td>
                      <td className="py-1.5 pr-3 text-ink-body">{before + delta}</td>
                      <td className={`py-1.5 pr-3 font-semibold ${delta > 0 ? "text-success-text" : "text-danger-text"}`}>
                        {delta > 0 ? `+${delta}` : delta}
                      </td>
                    </tr>
                  );
                })}
            </tbody>
          </table>

          <div className="mt-4 flex flex-wrap gap-2">
            <Button variant="secondary" onClick={() => setPendingMoves([])}>
              Verwerfen
            </Button>
            <Button onClick={handleApply} pending={applying}>
              Reorganisation durchführen
            </Button>
          </div>
        </div>
      )}

      {reorgScenarios.length > 0 && (
        <div className="rounded border border-border bg-white p-4">
          <h2 className="mb-3 text-sm font-bold text-ink">↩ Durchgeführte Reorganisationen – rückgängig machbar</h2>
          <ul className="flex flex-col divide-y divide-border">
            {reorgScenarios.map((s) => (
              <li key={s.id} className="flex items-center justify-between py-2 text-sm">
                <div>
                  <span className="font-semibold text-ink">{s.name}</span>
                  <span className="ml-2 text-xs text-ink-muted">
                    wirksam ab {fmtDate(s.effective_date)} · durchgeführt am {fmtDate(s.applied_at)}
                  </span>
                </div>
                <Button variant="secondary" size="sm" onClick={() => handleUndo(s.id)} pending={undoingId === s.id}>
                  <RotateCcw className="h-3.5 w-3.5" />
                  Rückgängig machen
                </Button>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}
