"use client";

import Link from "next/link";
import { useParams } from "next/navigation";
import { useRef, useState } from "react";

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 Report = { counts: Record<string, number>; unmapped_tags: string[] };
type Preview = components["schemas"]["ImportPreview"];
type Dup = components["schemas"]["DuplicateMatch"];
type Action = "new" | "skip" | "merge" | "overwrite";

const ACTIONS: { value: Action; label: string }[] = [
  { value: "new", label: "Import as new" },
  { value: "merge", label: "Merge into existing" },
  { value: "skip", label: "Skip (use existing)" },
  { value: "overwrite", label: "Overwrite existing" },
];

const fieldCls = "h-9 rounded-md border border-[var(--border)] bg-[var(--surface)] px-2 text-sm";

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

  const [target, setTarget] = useState<"new" | "this">("new");
  const [newName, setNewName] = useState("");
  const [busy, setBusy] = useState(false);
  const [report, setReport] = useState<Report | null>(null);
  const [importedTreeId, setImportedTreeId] = useState<string | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  // Two-step dedupe flow (only when importing into an existing tree).
  const [file, setFile] = useState<File | null>(null);
  const [preview, setPreview] = useState<Preview | null>(null);
  const [resolutions, setResolutions] = useState<Record<string, Action>>({});

  function resetAll() {
    setReport(null);
    setImportedTreeId(null);
    setPreview(null);
    setFile(null);
    setResolutions({});
  }

  async function postImport(
    tid: string,
    f: File,
    opts?: { resolutions?: string; defaultAction?: Action },
  ) {
    const fd = new FormData();
    fd.append("file", f);
    if (opts?.defaultAction) fd.append("default_action", opts.defaultAction);
    if (opts?.resolutions) fd.append("resolutions", opts.resolutions);
    const resp = await fetch(`/api/v1/trees/${tid}/gedcom/import`, {
      method: "POST",
      body: fd,
      credentials: "include",
    });
    if (resp.ok) {
      setReport(await resp.json());
      setImportedTreeId(tid);
    }
  }

  async function onFile(e: React.ChangeEvent<HTMLInputElement>) {
    const f = e.target.files?.[0];
    if (fileRef.current) fileRef.current.value = "";
    if (!f) return;
    setBusy(true);
    resetAll();

    if (target === "new") {
      // Fresh tree — nothing to dedupe against, import directly.
      const { data } = await api.POST("/api/v1/trees", {
        body: { name: newName.trim() || "Imported tree" },
      });
      if (data) await postImport(data.id, f);
      setBusy(false);
      return;
    }

    // Existing tree — preview for duplicates first.
    setFile(f);
    const fd = new FormData();
    fd.append("file", f);
    const resp = await fetch(`/api/v1/trees/${treeId}/gedcom/preview`, {
      method: "POST",
      body: fd,
      credentials: "include",
    });
    if (resp.ok) {
      const pv: Preview = await resp.json();
      setPreview(pv);
      // Default: high-confidence matches merge, lower ones come in as new.
      const init: Record<string, Action> = {};
      for (const d of pv.potential_duplicates) init[d.xref] = d.score === "high" ? "merge" : "new";
      setResolutions(init);
    }
    setBusy(false);
  }

  async function runImport() {
    if (!file) return;
    setBusy(true);
    const map: Record<string, { action: Action; target_id: string }> = {};
    for (const d of preview?.potential_duplicates ?? []) {
      const action = resolutions[d.xref] ?? "new";
      if (action !== "new") map[d.xref] = { action, target_id: d.existing_person_id };
    }
    await postImport(treeId, file, { resolutions: JSON.stringify(map) });
    setPreview(null);
    setFile(null);
    setBusy(false);
  }

  async function exportGed() {
    const resp = await fetch(`/api/v1/trees/${treeId}/gedcom/export`, { credentials: "include" });
    if (!resp.ok) return;
    const blob = await resp.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "tree.ged";
    a.click();
    URL.revokeObjectURL(url);
  }

  const dups = preview?.potential_duplicates ?? [];

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-semibold">Import &amp; export GEDCOM</h1>

      <Card>
        <CardHeader>
          <CardTitle className="text-base">Import a GEDCOM file</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <label className="flex items-center gap-2 text-sm">
            <input
              type="radio"
              name="target"
              checked={target === "new"}
              onChange={() => {
                setTarget("new");
                resetAll();
              }}
            />
            Import into a <strong>new tree</strong> (recommended)
          </label>
          {target === "new" && (
            <Input
              className="max-w-xs"
              placeholder="New tree name"
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
            />
          )}
          <label className="flex items-center gap-2 text-sm">
            <input
              type="radio"
              name="target"
              checked={target === "this"}
              onChange={() => {
                setTarget("this");
                resetAll();
              }}
            />
            Import into <strong>this tree</strong> (checks for duplicates)
          </label>
          {target === "this" && !preview && (
            <p className="rounded-md bg-bronze/[0.08] px-3 py-2 text-sm text-[var(--muted)]">
              We&apos;ll scan the file and flag anyone who looks like a person already in this
              tree, so you can merge, skip, or overwrite before anything is saved.
            </p>
          )}

          <input
            ref={fileRef}
            type="file"
            accept=".ged,.gedcom,text/plain"
            onChange={onFile}
            className="hidden"
          />
          {!preview && (
            <Button onClick={() => fileRef.current?.click()} disabled={busy}>
              {busy ? "Working…" : "Choose GEDCOM file"}
            </Button>
          )}

          {/* Duplicate-resolution step */}
          {preview && (
            <div className="space-y-4">
              <div className="flex flex-wrap gap-x-6 gap-y-1 text-sm text-[var(--muted)]">
                {Object.entries(preview.counts).map(([k, v]) => (
                  <span key={k}>
                    <span className="font-medium text-[var(--foreground)]">{v}</span> {k}
                  </span>
                ))}
              </div>

              {dups.length === 0 ? (
                <p className="rounded-md bg-bronze/[0.08] px-3 py-2 text-sm">
                  No likely duplicates found — everyone will be imported as new.
                </p>
              ) : (
                <div className="space-y-2">
                  <div className="flex items-center justify-between">
                    <h3 className="text-sm font-semibold">
                      {dups.length} possible duplicate{dups.length === 1 ? "" : "s"}
                    </h3>
                    <label className="flex items-center gap-2 text-xs text-[var(--muted)]">
                      Set all to
                      <select
                        className={fieldCls}
                        onChange={(e) => {
                          const a = e.target.value as Action;
                          const all: Record<string, Action> = {};
                          for (const d of dups) all[d.xref] = a;
                          setResolutions(all);
                        }}
                        defaultValue=""
                      >
                        <option value="" disabled>
                          choose…
                        </option>
                        {ACTIONS.map((a) => (
                          <option key={a.value} value={a.value}>
                            {a.label}
                          </option>
                        ))}
                      </select>
                    </label>
                  </div>
                  <ul className="divide-y divide-[var(--border)] rounded-lg border border-[var(--border)]">
                    {dups.map((d: Dup) => (
                      <li
                        key={d.xref}
                        className="flex flex-wrap items-center justify-between gap-3 px-3 py-2 text-sm"
                      >
                        <div className="min-w-0">
                          <span className="font-medium">{d.incoming_name}</span>
                          {d.incoming_birth_year && (
                            <span className="text-[var(--muted)]"> b. {d.incoming_birth_year}</span>
                          )}
                          <span className="text-[var(--muted)]"> ↔ </span>
                          <span>{d.existing_name}</span>
                          {d.existing_birth_year && (
                            <span className="text-[var(--muted)]"> b. {d.existing_birth_year}</span>
                          )}
                          <span
                            className={`ml-2 rounded px-1.5 py-0.5 text-xs ${
                              d.score === "high"
                                ? "bg-bronze/15 text-bronze"
                                : "bg-[var(--border)]/50 text-[var(--muted)]"
                            }`}
                          >
                            {d.score}
                          </span>
                        </div>
                        <select
                          className={fieldCls}
                          value={resolutions[d.xref] ?? "new"}
                          onChange={(e) =>
                            setResolutions((r) => ({ ...r, [d.xref]: e.target.value as Action }))
                          }
                        >
                          {ACTIONS.map((a) => (
                            <option key={a.value} value={a.value}>
                              {a.label}
                            </option>
                          ))}
                        </select>
                      </li>
                    ))}
                  </ul>
                </div>
              )}

              <div className="flex gap-2">
                <Button onClick={runImport} disabled={busy}>
                  {busy ? "Importing…" : "Run import"}
                </Button>
                <Button variant="ghost" onClick={resetAll} disabled={busy}>
                  Cancel
                </Button>
              </div>
            </div>
          )}

          {report && (
            <div className="space-y-3 rounded-lg border border-[var(--border)] p-4">
              <div className="font-medium">Import complete</div>
              <div className="flex flex-wrap gap-x-6 gap-y-1 text-sm text-[var(--muted)]">
                {Object.entries(report.counts).map(([k, v]) => (
                  <span key={k}>
                    <span className="font-medium text-[var(--foreground)]">{v}</span> {k}
                  </span>
                ))}
              </div>
              {report.unmapped_tags.length > 0 && (
                <div className="text-xs text-[var(--muted)]">
                  Unmapped tags (skipped): {report.unmapped_tags.join(", ")}
                </div>
              )}
              {importedTreeId && (
                <Link
                  href={`/trees/${importedTreeId}`}
                  className="inline-block text-sm text-bronze hover:underline"
                >
                  Open the imported tree →
                </Link>
              )}
            </div>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle className="text-base">Export this tree</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3">
          <p className="text-sm text-[var(--muted)]">
            Download this tree as a GEDCOM file — people, relationships, events, and sources.
          </p>
          <Button variant="outline" onClick={exportGed}>
            Download .ged
          </Button>
        </CardContent>
      </Card>
    </div>
  );
}
