import { createFileRoute, Link, useRouter } from "@tanstack/react-router";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { AppShell, PageHeader } from "@/components/app-shell";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Input, NativeSelect, Textarea } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  AGREEMENT_KIND_LABEL,
  AGREEMENT_STATUS_LABEL,
  GRANTS_MAILBOX,
  RESEARCH_TERMS,
  SPONSORSHIP_TERMS,
  type AgreementKind,
  type AgreementStatus,
} from "@/lib/constants";
import { grokStatus } from "@/lib/server/api-ai";
import { generateAgreement, listAgreements } from "@/lib/server/api-agreements";
import { getShellMeta } from "@/lib/server/api-core";
import { listDonations } from "@/lib/server/api-donations";
import { listRelationships } from "@/lib/server/api-pipeline";
import { formatDate, moneyCents } from "@/lib/utils";

export const Route = createFileRoute("/agreements/")({
  loader: async () => {
    const [meta, agreements, relationships, donations, grok] = await Promise.all([
      getShellMeta(),
      listAgreements(),
      listRelationships(),
      listDonations(),
      grokStatus(),
    ]);
    return { meta, agreements, relationships, donations, grok };
  },
  component: AgreementsPage,
});

function statusVariant(status: string) {
  if (status === "executed" || status === "sent") return "success" as const;
  if (status === "review") return "warning" as const;
  return "muted" as const;
}

function AgreementsPage() {
  const { meta, agreements, relationships, donations, grok } = Route.useLoaderData();
  const router = useRouter();
  const [filter, setFilter] = useState<"all" | AgreementKind>("all");
  const [open, setOpen] = useState(false);
  const [kind, setKind] = useState<AgreementKind>("sponsorship");
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [amount, setAmount] = useState("1000");
  const [term, setTerm] = useState("12");
  const [purpose, setPurpose] = useState(
    "Open-enrollment financial literacy and entrepreneurship education for military veterans and college student-athletes.",
  );
  const [relId, setRelId] = useState("");
  const [donId, setDonId] = useState("");
  const [terms, setTerms] = useState<Record<string, boolean>>({});
  const [busy, setBusy] = useState(false);

  const required = kind === "sponsored_research" ? RESEARCH_TERMS : SPONSORSHIP_TERMS;
  const rows = agreements.filter((a) => (filter === "all" ? true : a.kind === filter));

  const counts = useMemo(() => {
    return {
      all: agreements.length,
      sponsorship: agreements.filter((a) => a.kind === "sponsorship").length,
      sponsored_research: agreements.filter((a) => a.kind === "sponsored_research").length,
    };
  }, [agreements]);

  function resetTerms(next: AgreementKind) {
    setKind(next);
    setTerms({});
  }

  async function generate(e: React.FormEvent) {
    e.preventDefault();
    setBusy(true);
    try {
      const res = await generateAgreement({
        data: {
          kind,
          counterparty_name: name,
          counterparty_email: email || undefined,
          amount: amount ? Number(amount) : undefined,
          term_months: term ? Number(term) : undefined,
          purpose,
          relationshipId: relId || undefined,
          donationId: donId || undefined,
          terms,
        },
      });
      toast.success(res.usedGrok ? "Grok drafted the agreement" : "Template drafted — Grok unavailable, edit before send");
      setOpen(false);
      setName("");
      setEmail("");
      setTerms({});
      await router.invalidate();
      await router.navigate({ to: "/agreements/$id", params: { id: res.id } });
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Could not generate");
    } finally {
      setBusy(false);
    }
  }

  return (
    <AppShell hold={meta.hold} unread={meta.unread} noticeCount={meta.noticeCount} inboxUnread={meta.inboxUnread}>
      <PageHeader
        kicker="Layer 4 · stewardship"
        title="Agreements"
        description="Sponsorship and sponsored-research documents. Terms must be accepted before Grok (or the template) drafts. Staff review, then send from grants@."
        actions={
          <Dialog
            open={open}
            onOpenChange={(v) => {
              setOpen(v);
              if (!v) setTerms({});
            }}
          >
            <DialogTrigger asChild>
              <Button>New agreement</Button>
            </DialogTrigger>
            <DialogContent
              className="max-h-[90vh] max-w-2xl overflow-y-auto"
              title="Generate agreement"
              description={
                grok.available
                  ? "Grok drafts from CFL terms. You review and send — nothing goes out on generate."
                  : "Grok is unavailable. A CFL template will draft; you edit before sending."
              }
            >
              <form className="flex flex-col gap-3" onSubmit={generate}>
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="kind">Kind</Label>
                    <NativeSelect
                      id="kind"
                      value={kind}
                      onChange={(e) => resetTerms(e.target.value as AgreementKind)}
                    >
                      <option value="sponsorship">Sponsorship</option>
                      <option value="sponsored_research">Sponsored research</option>
                    </NativeSelect>
                  </div>
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="term">Term (months)</Label>
                    <Input id="term" type="number" min="1" value={term} onChange={(e) => setTerm(e.target.value)} />
                  </div>
                </div>
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="cp">Counterparty</Label>
                    <Input id="cp" required value={name} onChange={(e) => setName(e.target.value)} />
                  </div>
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="em">Email</Label>
                    <Input
                      id="em"
                      type="email"
                      value={email}
                      onChange={(e) => setEmail(e.target.value)}
                      placeholder="sponsor@example.org"
                    />
                  </div>
                </div>
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="amt">Amount (USD)</Label>
                    <Input id="amt" type="number" min="0" step="1" value={amount} onChange={(e) => setAmount(e.target.value)} />
                  </div>
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="rel">Link relationship</Label>
                    <NativeSelect id="rel" value={relId} onChange={(e) => setRelId(e.target.value)}>
                      <option value="">None</option>
                      {relationships.map((r) => (
                        <option key={r.id} value={r.id}>
                          {r.foundation_name}
                        </option>
                      ))}
                    </NativeSelect>
                  </div>
                </div>
                <div className="flex flex-col gap-1.5">
                  <Label htmlFor="gift">Link gift (optional)</Label>
                  <NativeSelect
                    id="gift"
                    value={donId}
                    onChange={(e) => {
                      const id = e.target.value;
                      setDonId(id);
                      const d = donations.find((x) => x.id === id);
                      if (d) {
                        setName(d.donor_name);
                        if (d.donor_email) setEmail(d.donor_email);
                        setAmount(String(Math.round(d.amount_cents / 100)));
                      }
                    }}
                  >
                    <option value="">None</option>
                    {donations.map((d) => (
                      <option key={d.id} value={d.id}>
                        {d.donor_name} · {moneyCents(d.amount_cents)}
                      </option>
                    ))}
                  </NativeSelect>
                </div>
                <div className="flex flex-col gap-1.5">
                  <Label htmlFor="purpose">Purpose</Label>
                  <Textarea id="purpose" value={purpose} onChange={(e) => setPurpose(e.target.value)} rows={3} />
                </div>
                <div>
                  <p className="mb-2 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">
                    Terms & conditions — all required
                  </p>
                  <ul className="space-y-2">
                    {required.map((t) => (
                      <li key={t.id}>
                        <label className="flex min-h-11 items-start gap-2.5 text-sm">
                          <input
                            type="checkbox"
                            className="mt-1"
                            checked={Boolean(terms[t.id])}
                            onChange={(e) => setTerms((prev) => ({ ...prev, [t.id]: e.target.checked }))}
                          />
                          <span>{t.label}</span>
                        </label>
                      </li>
                    ))}
                  </ul>
                </div>
                <Button type="submit" disabled={busy}>
                  {busy ? "Drafting…" : grok.available ? "Ask Grok to draft" : "Generate from template"}
                </Button>
              </form>
            </DialogContent>
          </Dialog>
        }
      />

      <Card className="mb-6">
        <CardContent className="flex flex-col gap-2 p-5 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <p className="text-[11px] tracking-[0.16em] text-muted-foreground uppercase">Outbound mailbox</p>
            <p className="mt-1 font-mono text-sm text-primary">{GRANTS_MAILBOX}</p>
            <p className="text-xs text-muted-foreground">Sent agreements post here. Receipts and thank-yous use donations@.</p>
          </div>
          <Button asChild variant="outline">
            <Link to="/donations/inbox">Open mailbox</Link>
          </Button>
        </CardContent>
      </Card>

      <div className="mb-4 flex flex-wrap gap-2">
        {(
          [
            ["all", `All · ${counts.all}`],
            ["sponsorship", `Sponsorship · ${counts.sponsorship}`],
            ["sponsored_research", `Research · ${counts.sponsored_research}`],
          ] as const
        ).map(([id, label]) => (
          <Button key={id} size="sm" variant={filter === id ? "default" : "outline"} onClick={() => setFilter(id)}>
            {label}
          </Button>
        ))}
      </div>

      <div className="overflow-hidden rounded-xl bg-card shadow-[var(--shadow-border)]">
        <div className="overflow-x-auto">
        <table className="w-full min-w-[720px] text-left text-sm">
          <thead>
            <tr className="bg-primary text-[11px] tracking-wider text-primary-foreground uppercase">
              <th className="px-4 py-3 font-semibold">Agreement</th>
              <th className="px-4 py-3 font-semibold">Kind</th>
              <th className="px-4 py-3 font-semibold">Amount</th>
              <th className="px-4 py-3 font-semibold">Updated</th>
              <th className="px-4 py-3 font-semibold">Status</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((a) => (
              <tr key={a.id} className="border-b border-border last:border-0">
                <td className="px-4 py-3">
                  <Link to="/agreements/$id" params={{ id: a.id }} className="font-medium hover:text-primary">
                    {a.title}
                  </Link>
                  <p className="text-xs text-muted-foreground">
                    {a.counterparty_name}
                    {a.relationship_foundation ? ` · ${a.relationship_foundation}` : ""}
                  </p>
                </td>
                <td className="px-4 py-3">
                  <Badge variant="muted">{AGREEMENT_KIND_LABEL[a.kind as AgreementKind] ?? a.kind}</Badge>
                </td>
                <td className="px-4 py-3 tabular">{a.amount_cents ? moneyCents(a.amount_cents) : "—"}</td>
                <td className="px-4 py-3">{formatDate(a.updated_at)}</td>
                <td className="px-4 py-3">
                  <Badge variant={statusVariant(a.status)}>
                    {AGREEMENT_STATUS_LABEL[a.status as AgreementStatus] ?? a.status}
                  </Badge>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        </div>
      </div>
    </AppShell>
  );
}
