"use client";

import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, 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 } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

type Person = components["schemas"]["PersonRead"];
type Relationship = components["schemas"]["RelationshipRead"];
type Event = components["schemas"]["EventRead"];

function splitName(full: string): { given: string | null; surname: string | null } {
  const t = full.trim().split(/\s+/).filter(Boolean);
  if (t.length === 0) return { given: null, surname: null };
  if (t.length === 1) return { given: t[0], surname: null };
  return { given: t.slice(0, -1).join(" "), surname: t[t.length - 1] };
}

type AddKind = "parent" | "child" | "partner";

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

  const [people, setPeople] = useState<Person[]>([]);
  const [rels, setRels] = useState<Relationship[]>([]);
  const [events, setEvents] = useState<Event[]>([]);
  const [ready, setReady] = useState(false);
  const [focusId, setFocusId] = useState<string | null>(null);
  const [search, setSearch] = useState("");
  const [firstName, setFirstName] = useState("");
  // Inline add-relative form: which anchor + kind is open, and the typed name.
  const [adding, setAdding] = useState<{ kind: AddKind; anchor: string } | null>(null);
  const [addName, setAddName] = useState("");

  const load = useCallback(async () => {
    const p = await api.GET("/api/v1/trees/{tree_id}/persons", {
      params: { path: { tree_id: treeId } },
    });
    if (p.response.status === 401) {
      router.push("/login");
      return;
    }
    const [r, e] = await Promise.all([
      api.GET("/api/v1/trees/{tree_id}/relationships", { params: { path: { tree_id: treeId } } }),
      api.GET("/api/v1/trees/{tree_id}/events", { params: { path: { tree_id: treeId } } }),
    ]);
    const ppl = p.data ?? [];
    setPeople(ppl);
    setRels(r.data ?? []);
    setEvents(e.data ?? []);
    setFocusId((cur) => cur ?? ppl[0]?.id ?? null);
    setReady(true);
  }, [router, treeId]);

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

  const byId = useMemo(() => new Map(people.map((p) => [p.id, p])), [people]);
  const parentsOf = (id: string) =>
    rels.filter((r) => r.type === "parent_child" && r.person_to_id === id).map((r) => r.person_from_id);
  const childrenOf = (id: string) =>
    rels.filter((r) => r.type === "parent_child" && r.person_from_id === id).map((r) => r.person_to_id);
  const partnersOf = (id: string) =>
    rels
      .filter((r) => r.type === "partnership" && (r.person_from_id === id || r.person_to_id === id))
      .map((r) => (r.person_from_id === id ? r.person_to_id : r.person_from_id));

  const years = useMemo(() => {
    const m = new Map<string, string>();
    const yr = (e: Event) => (e.date_start ? e.date_start.slice(0, 4) : e.date_value ?? "");
    for (const p of people) {
      const b = events.find((e) => e.person_id === p.id && e.event_type === "birth");
      const d = events.find((e) => e.person_id === p.id && e.event_type === "death");
      const parts = [b ? yr(b) : "", d ? yr(d) : ""];
      if (parts[0] || parts[1]) m.set(p.id, `${parts[0]}–${parts[1]}`.replace(/^–$/, ""));
    }
    return m;
  }, [people, events]);

  async function addPerson(name: string): Promise<string | null> {
    const { given, surname } = splitName(name);
    const { data } = await api.POST("/api/v1/trees/{tree_id}/persons", {
      params: { path: { tree_id: treeId } },
      body: { given, surname },
    });
    return data?.id ?? null;
  }

  async function createFirst(e: React.FormEvent) {
    e.preventDefault();
    if (!firstName.trim()) return;
    const id = await addPerson(firstName);
    setFirstName("");
    if (id) setFocusId(id);
    load();
  }

  async function submitAdd(e: React.FormEvent) {
    e.preventDefault();
    if (!adding || !addName.trim()) return;
    const newId = await addPerson(addName);
    if (newId) {
      const { kind, anchor } = adding;
      const body =
        kind === "parent"
          ? { type: "parent_child" as const, person_from_id: newId, person_to_id: anchor, qualifier: "biological" as const }
          : kind === "child"
            ? { type: "parent_child" as const, person_from_id: anchor, person_to_id: newId, qualifier: "biological" as const }
            : { type: "partnership" as const, person_from_id: anchor, person_to_id: newId };
      await api.POST("/api/v1/trees/{tree_id}/relationships", {
        params: { path: { tree_id: treeId } },
        body,
      });
    }
    setAdding(null);
    setAddName("");
    load();
  }

  if (!ready) return <p className="text-[var(--muted)]">Loading…</p>;

  if (people.length === 0) {
    return (
      <div className="space-y-6">
        <h1 className="text-2xl font-semibold">Start your tree</h1>
        <Card>
          <CardContent className="p-6">
            <form onSubmit={createFirst} className="flex flex-wrap gap-2">
              <Input
                className="w-64"
                placeholder="First person's full name"
                value={firstName}
                onChange={(e) => setFirstName(e.target.value)}
              />
              <Button type="submit">Add person</Button>
            </form>
          </CardContent>
        </Card>
      </div>
    );
  }

  const focus = focusId ? byId.get(focusId) : undefined;
  if (!focus) {
    setFocusId(people[0].id);
    return null;
  }

  const PersonBox = ({
    id,
    muted,
  }: {
    id: string;
    muted?: boolean;
  }) => {
    const p = byId.get(id);
    if (!p) return null;
    const isFocus = id === focusId;
    return (
      <button
        onClick={() => setFocusId(id)}
        className={`w-44 rounded-lg border px-3 py-2 text-left transition-colors ${
          isFocus
            ? "border-bronze bg-bronze/[0.08]"
            : "border-[var(--border)] bg-[var(--surface)] hover:border-bronze/60"
        } ${muted ? "opacity-90" : ""}`}
      >
        <div className="truncate text-sm font-medium">{p.primary_name ?? "Unnamed"}</div>
        <div className="text-xs text-[var(--muted)]">{years.get(id) ?? "—"}</div>
      </button>
    );
  };

  const AddSlot = ({ kind, anchor, label }: { kind: AddKind; anchor: string; label: string }) =>
    adding && adding.kind === kind && adding.anchor === anchor ? (
      <form onSubmit={submitAdd} className="flex w-44 flex-col gap-1">
        <Input
          autoFocus
          className="h-9"
          placeholder="Full name"
          value={addName}
          onChange={(e) => setAddName(e.target.value)}
        />
        <div className="flex gap-1">
          <Button type="submit" size="sm">
            Add
          </Button>
          <button
            type="button"
            onClick={() => setAdding(null)}
            className="text-xs text-[var(--muted)]"
          >
            cancel
          </button>
        </div>
      </form>
    ) : (
      <button
        onClick={() => {
          setAdding({ kind, anchor });
          setAddName("");
        }}
        className="w-44 rounded-lg border border-dashed border-[var(--border)] px-3 py-2 text-left text-sm text-[var(--muted)] hover:border-bronze hover:text-bronze"
      >
        + {label}
      </button>
    );

  const parents = parentsOf(focus.id);
  const partners = partnersOf(focus.id);
  const children = childrenOf(focus.id);

  const sorted = [...people].sort((a, b) =>
    (a.primary_name ?? "").localeCompare(b.primary_name ?? ""),
  );
  const matches = search
    ? sorted.filter((p) => (p.primary_name ?? "").toLowerCase().includes(search.toLowerCase()))
    : sorted;

  return (
    <div className="space-y-8">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <h1 className="text-2xl font-semibold">Family view</h1>
        <Link
          href={`/trees/${treeId}/persons/${focus.id}`}
          className="text-sm text-bronze hover:underline"
        >
          Open {focus.primary_name ?? "person"} →
        </Link>
      </div>

      {/* Pedigree: focus → parents → grandparents */}
      <Card>
        <CardContent className="overflow-x-auto p-6">
          <div className="flex min-w-[40rem] items-stretch gap-8">
            <div className="flex flex-1 flex-col justify-center gap-3">
              <div className="mb-1 text-xs font-semibold uppercase tracking-wider text-[var(--muted)]">
                Focus
              </div>
              <PersonBox id={focus.id} />
            </div>

            <div className="flex flex-1 flex-col justify-center gap-4">
              <div className="mb-1 text-xs font-semibold uppercase tracking-wider text-[var(--muted)]">
                Parents
              </div>
              {parents.map((pid) => (
                <PersonBox key={pid} id={pid} muted />
              ))}
              {parents.length < 2 && <AddSlot kind="parent" anchor={focus.id} label="add parent" />}
            </div>

            <div className="flex flex-1 flex-col justify-center gap-4">
              <div className="mb-1 text-xs font-semibold uppercase tracking-wider text-[var(--muted)]">
                Grandparents
              </div>
              {parents.length === 0 && (
                <div className="text-sm text-[var(--muted)]">Add parents first.</div>
              )}
              {parents.map((pid) => (
                <div key={pid} className="flex flex-col gap-2">
                  {parentsOf(pid).map((gp) => (
                    <PersonBox key={gp} id={gp} muted />
                  ))}
                  {parentsOf(pid).length < 2 && (
                    <AddSlot kind="parent" anchor={pid} label="add parent" />
                  )}
                </div>
              ))}
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Family group: partners + children of the focus */}
      <div className="grid gap-5 sm:grid-cols-2">
        <Card>
          <CardContent className="space-y-3 p-6">
            <h2 className="font-serif text-base font-semibold">Spouses &amp; partners</h2>
            <div className="flex flex-wrap gap-3">
              {partners.map((id) => (
                <PersonBox key={id} id={id} muted />
              ))}
              <AddSlot kind="partner" anchor={focus.id} label="add spouse" />
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardContent className="space-y-3 p-6">
            <h2 className="font-serif text-base font-semibold">Children</h2>
            <div className="flex flex-wrap gap-3">
              {children.map((id) => (
                <PersonBox key={id} id={id} muted />
              ))}
              <AddSlot kind="child" anchor={focus.id} label="add child" />
            </div>
          </CardContent>
        </Card>
      </div>

      {/* Searchable index of everyone in the tree */}
      <div className="space-y-3">
        <div className="flex items-center justify-between gap-3">
          <h2 className="font-serif text-base font-semibold">All people ({people.length})</h2>
          <Input
            className="w-56"
            placeholder="Search…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <div className="flex flex-wrap gap-2">
          {matches.map((p) => (
            <button
              key={p.id}
              onClick={() => setFocusId(p.id)}
              className={`rounded-full border px-3 py-1 text-sm transition-colors ${
                p.id === focusId
                  ? "border-bronze bg-bronze/[0.08] text-bronze"
                  : "border-[var(--border)] hover:border-bronze/60"
              }`}
            >
              {p.primary_name ?? "Unnamed"}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}
