"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { useParams } from "next/navigation";

import { api } from "@/lib/api/client";
import type { components } from "@/lib/api/schema";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

type Deceased = components["schemas"]["DeceasedCandidate"];
type GenderProp = components["schemas"]["GenderProposal"];
type NameIssue = components["schemas"]["NameIssue"];

const ISSUE_LABEL: Record<string, string> = {
  date_in_surname: "date in surname",
  date_in_given: "date in given name",
  no_surname: "no surname",
  packed_given: "long given name",
};

export default function CleanupPage() {
  const params = useParams<{ id: string }>();
  const treeId = params.id;

  // 1) Deceased by birth year
  const [year, setYear] = useState(1930);
  const [deceased, setDeceased] = useState<Deceased[] | null>(null);
  const [decSel, setDecSel] = useState<Set<string>>(new Set());
  const [decMsg, setDecMsg] = useState<string | null>(null);

  // 2) Gender from source GEDCOM
  const [gender, setGender] = useState<GenderProp[] | null>(null);
  const [genSel, setGenSel] = useState<Set<string>>(new Set());
  const [genMsg, setGenMsg] = useState<string | null>(null);
  const genFile = useRef<HTMLInputElement>(null);

  // 3) Name issues
  const [issues, setIssues] = useState<NameIssue[] | null>(null);
  const [edits, setEdits] = useState<Record<string, { given: string; surname: string; on: boolean }>>({});
  const [nameMsg, setNameMsg] = useState<string | null>(null);

  async function previewDeceased() {
    setDecMsg(null);
    const { data } = await api.GET("/api/v1/trees/{tree_id}/cleanup/deceased", {
      params: { path: { tree_id: treeId }, query: { born_on_or_before: year } },
    });
    setDeceased(data ?? []);
    setDecSel(new Set((data ?? []).map((d) => d.person_id)));
  }
  async function applyDeceased() {
    const ids = [...decSel];
    const { data } = await api.POST("/api/v1/trees/{tree_id}/cleanup/deceased", {
      params: { path: { tree_id: treeId } },
      body: { person_ids: ids },
    });
    setDecMsg(`Marked ${data?.updated ?? 0} people deceased.`);
    setDeceased(null);
  }

  async function previewGender(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (genFile.current) genFile.current.value = "";
    if (!file) return;
    setGenMsg(null);
    const fd = new FormData();
    fd.append("file", file);
    const resp = await fetch(`/api/v1/trees/${treeId}/cleanup/gender/preview`, {
      method: "POST",
      body: fd,
      credentials: "include",
    });
    if (resp.ok) {
      const data: GenderProp[] = await resp.json();
      setGender(data);
      setGenSel(new Set(data.map((g) => g.person_id)));
    }
  }
  async function applyGender() {
    const updates = (gender ?? [])
      .filter((g) => genSel.has(g.person_id))
      .map((g) => ({ person_id: g.person_id, gender: g.proposed_gender }));
    const { data } = await api.POST("/api/v1/trees/{tree_id}/cleanup/gender", {
      params: { path: { tree_id: treeId } },
      body: { updates },
    });
    setGenMsg(`Set gender on ${data?.updated ?? 0} people.`);
    setGender(null);
  }

  const loadNames = useCallback(async () => {
    setNameMsg(null);
    const { data } = await api.GET("/api/v1/trees/{tree_id}/cleanup/names", {
      params: { path: { tree_id: treeId } },
    });
    setIssues(data ?? []);
    const init: Record<string, { given: string; surname: string; on: boolean }> = {};
    for (const i of data ?? []) {
      init[i.name_id] = { given: i.given ?? "", surname: i.surname ?? "", on: false };
    }
    setEdits(init);
  }, [treeId]);

  useEffect(() => {
    loadNames();
  }, [loadNames]);

  async function applyNames() {
    const chosen = (issues ?? []).filter((i) => edits[i.name_id]?.on);
    const body = {
      edits: chosen.map((i) => ({
        name_id: i.name_id,
        given: edits[i.name_id].given,
        surname: edits[i.name_id].surname,
      })),
    };
    if (!body.edits.length) return;
    const { data } = await api.POST("/api/v1/trees/{tree_id}/cleanup/names", {
      params: { path: { tree_id: treeId } },
      body,
    });
    setNameMsg(`Fixed ${data?.updated ?? 0} names.`);
    loadNames();
  }

  const toggle = (set: Set<string>, id: string, setter: (s: Set<string>) => void) => {
    const n = new Set(set);
    if (n.has(id)) n.delete(id);
    else n.add(id);
    setter(n);
  };

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-semibold">Cleanup</h1>
        <p className="mt-1 text-sm text-[var(--muted)]">
          Fix common import messes in bulk. Each tool previews its changes — nothing is saved
          until you apply.
        </p>
      </div>

      {/* 1) Deceased by year */}
      <Card>
        <CardHeader>
          <CardTitle className="text-base">Mark deceased by birth year</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3">
          <div className="flex flex-wrap items-end gap-2">
            <label className="flex flex-col gap-1 text-sm">
              <span className="text-xs text-[var(--muted)]">Born on or before</span>
              <Input
                type="number"
                className="w-28"
                value={year}
                onChange={(e) => setYear(Number(e.target.value))}
              />
            </label>
            <Button variant="outline" onClick={previewDeceased}>
              Preview
            </Button>
          </div>
          {decMsg && <p className="text-sm text-bronze">{decMsg}</p>}
          {deceased && (
            <div className="space-y-2">
              <p className="text-sm text-[var(--muted)]">
                {deceased.length} people born ≤ {year} (not already marked deceased).
              </p>
              <ul className="max-h-64 divide-y divide-[var(--border)] overflow-auto rounded-lg border border-[var(--border)]">
                {deceased.map((d) => (
                  <li key={d.person_id} className="flex items-center gap-3 px-3 py-1.5 text-sm">
                    <input
                      type="checkbox"
                      checked={decSel.has(d.person_id)}
                      onChange={() => toggle(decSel, d.person_id, setDecSel)}
                    />
                    <span className="flex-1">{d.name}</span>
                    <span className="text-xs text-[var(--muted)]">b. {d.birth_year}</span>
                  </li>
                ))}
              </ul>
              {deceased.length > 0 && (
                <Button onClick={applyDeceased}>Mark {decSel.size} deceased</Button>
              )}
            </div>
          )}
        </CardContent>
      </Card>

      {/* 2) Gender from source */}
      <Card>
        <CardHeader>
          <CardTitle className="text-base">Set sex from a source GEDCOM</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3">
          <p className="text-sm text-[var(--muted)]">
            Upload your source <code>.ged</code> (it carries each person’s sex). We match by
            name and propose sex only for people who don’t have it set.
          </p>
          <input
            ref={genFile}
            type="file"
            accept=".ged,.gedcom,text/plain"
            onChange={previewGender}
            className="hidden"
          />
          <Button variant="outline" onClick={() => genFile.current?.click()}>
            Choose source GEDCOM
          </Button>
          {genMsg && <p className="text-sm text-bronze">{genMsg}</p>}
          {gender && (
            <div className="space-y-2">
              <p className="text-sm text-[var(--muted)]">{gender.length} matches with a sex to set.</p>
              <ul className="max-h-64 divide-y divide-[var(--border)] overflow-auto rounded-lg border border-[var(--border)]">
                {gender.map((g) => (
                  <li key={g.person_id} className="flex items-center gap-3 px-3 py-1.5 text-sm">
                    <input
                      type="checkbox"
                      checked={genSel.has(g.person_id)}
                      onChange={() => toggle(genSel, g.person_id, setGenSel)}
                    />
                    <span className="flex-1">{g.name}</span>
                    <span
                      className="text-xs"
                      style={{
                        color:
                          g.proposed_gender === "male"
                            ? "rgb(120,159,172)"
                            : "rgb(196,138,146)",
                      }}
                    >
                      {g.proposed_gender}
                    </span>
                  </li>
                ))}
              </ul>
              {gender.length > 0 && (
                <Button onClick={applyGender}>Set sex on {genSel.size} people</Button>
              )}
            </div>
          )}
        </CardContent>
      </Card>

      {/* 3) Name issues */}
      <Card>
        <CardHeader>
          <CardTitle className="text-base">Names that look broken</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3">
          {nameMsg && <p className="text-sm text-bronze">{nameMsg}</p>}
          {issues === null ? (
            <p className="text-sm text-[var(--muted)]">Scanning…</p>
          ) : issues.length === 0 ? (
            <p className="text-sm text-[var(--muted)]">No obvious name problems found.</p>
          ) : (
            <div className="space-y-2">
              <p className="text-sm text-[var(--muted)]">
                {issues.length} flagged. Edit given/surname, tick the ones to fix, then apply.
              </p>
              <ul className="space-y-2">
                {issues.map((i) => {
                  const e = edits[i.name_id] ?? { given: "", surname: "", on: false };
                  return (
                    <li key={i.name_id} className="flex flex-wrap items-center gap-2 text-sm">
                      <input
                        type="checkbox"
                        checked={e.on}
                        onChange={() =>
                          setEdits((p) => ({ ...p, [i.name_id]: { ...e, on: !e.on } }))
                        }
                      />
                      <Input
                        className="h-9 w-40"
                        placeholder="Given"
                        value={e.given}
                        onChange={(ev) =>
                          setEdits((p) => ({ ...p, [i.name_id]: { ...e, given: ev.target.value } }))
                        }
                      />
                      <Input
                        className="h-9 w-40"
                        placeholder="Surname"
                        value={e.surname}
                        onChange={(ev) =>
                          setEdits((p) => ({
                            ...p,
                            [i.name_id]: { ...e, surname: ev.target.value },
                          }))
                        }
                      />
                      <span className="rounded bg-[var(--border)]/50 px-1.5 py-0.5 text-xs text-[var(--muted)]">
                        {ISSUE_LABEL[i.issue] ?? i.issue}
                      </span>
                    </li>
                  );
                })}
              </ul>
              <Button onClick={applyNames}>Fix selected</Button>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
