import { createFileRoute, useRouter } from "@tanstack/react-router";
import { useState } from "react";
import { Sparkles, Check } from "lucide-react";
import { toast } from "sonner";
import { AppShell, PageHeader } from "@/components/app-shell";
import { OrgProfileEditDialog } from "@/components/org-profile-edit";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input, Textarea } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { ACCEPTANCE, DATA_SOURCES, DONATIONS_MAILBOX, GRANTS_MAILBOX, ORG_ADDRESS_FULL, ORG_TYPE, PATENT_NOTICE, REGISTRANT_EMAIL, REGISTRANT_NAME } from "@/lib/constants";
import { PAPER_ROLES, PRIVILEGE_ROWS, ROLE_DISPLAY, mapAppRoleToPaper } from "@/lib/privileges";
import { useRoleStore } from "@/lib/role-store";
import { formatEin } from "@/lib/utils";
import {
  getAppSettings,
  getOrgProfile,
  getShellMeta,
  rescoreCatalog,
  updateOrgProfile,
  updateSettings,
} from "@/lib/server/api-core";

export const Route = createFileRoute("/settings")({
  loader: async () => {
    const [meta, org, settings] = await Promise.all([getShellMeta(), getOrgProfile(), getAppSettings()]);
    return { meta, org, settings };
  },
  component: SettingsPage,
});

function SettingsPage() {
  const { meta, org, settings } = Route.useLoaderData();
  const router = useRouter();
  const [editOpen, setEditOpen] = useState(false);
  const [mission, setMission] = useState(org.mission_text);
  const [keywords, setKeywords] = useState(org.focus_keywords.join(", "));
  const [zero, setZero] = useState(org.zero_equity_language);
  const [geo, setGeo] = useState(org.geography);
  const [hold, setHold] = useState(settings.solicitation_hold);
  const [threshold, setThreshold] = useState(String(settings.small_grant_threshold));
  const [minGrants, setMinGrants] = useState(String(settings.min_grant_count));
  const [floor, setFloor] = useState(String(settings.asset_floor));
  const [ceil, setCeil] = useState(String(settings.asset_ceiling));
  const [scoring, setScoring] = useState(false);
  const role = useRoleStore((s) => s.role);
  const paper = mapAppRoleToPaper(role);

  async function saveOrg(e: React.FormEvent) {
    e.preventDefault();
    const res = await updateOrgProfile({
      data: {
        mission_text: mission,
        focus_keywords: keywords.split(",").map((s) => s.trim()).filter(Boolean),
        zero_equity_language: zero,
        geography: geo,
      },
    });
    toast.success(`OrgProfile versioned · rescored ${res.opportunities} opportunities`);
    await router.invalidate();
  }

  async function saveSettings(e: React.FormEvent) {
    e.preventDefault();
    await updateSettings({
      data: {
        solicitation_hold: hold,
        small_grant_threshold: Number(threshold),
        min_grant_count: Number(minGrants),
        asset_floor: Number(floor),
        asset_ceiling: Number(ceil),
      },
    });
    toast.success("Settings saved");
    await router.invalidate();
  }

  async function rescore() {
    setScoring(true);
    try {
      const res = await rescoreCatalog();
      toast.success(`Rescored ${res.opportunities} opportunities, ${res.foundations} foundations`);
      await router.invalidate();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Rescore failed");
    } finally {
      setScoring(false);
    }
  }

  return (
    <AppShell hold={hold} unread={meta.unread} noticeCount={meta.noticeCount} inboxUnread={meta.inboxUnread}>
      <PageHeader
        kicker={`Version ${org.version} · ${ORG_TYPE}`}
        title="Org profile"
        description={`${org.name} · EIN ${formatEin(org.ein)}. Scoring is versioned so keyword changes stay traceable.`}
        actions={
          <div className="flex flex-wrap gap-2">
            <Button variant="gold" onClick={() => setEditOpen(true)}>
              <Sparkles className="size-4" />
              Edit
            </Button>
            <Button variant="outline" onClick={() => void rescore()} disabled={scoring}>
              {scoring ? "Rescoring…" : "Rescore catalog"}
            </Button>
          </div>
        }
      />

      <OrgProfileEditDialog org={org} open={editOpen} onOpenChange={setEditOpen} />

      <Card className="mb-4">
        <CardContent className="p-5">
          <p className="mb-3 text-[11px] font-medium tracking-[0.16em] text-muted-foreground uppercase">
            Registered agent
          </p>
          <dl className="grid gap-3 sm:grid-cols-3 text-sm">
            <div>
              <dt className="text-muted-foreground">Name</dt>
              <dd className="font-medium">{REGISTRANT_NAME}</dd>
            </div>
            <div>
              <dt className="text-muted-foreground">Email</dt>
              <dd className="font-medium">{REGISTRANT_EMAIL}</dd>
            </div>
            <div>
              <dt className="text-muted-foreground">Office</dt>
              <dd className="font-medium">{ORG_ADDRESS_FULL}</dd>
            </div>
          </dl>
        </CardContent>
      </Card>

      <div className="grid gap-4 lg:grid-cols-2">
        <Card>
          <CardContent className="p-5">
            <form className="flex flex-col gap-4" onSubmit={saveOrg}>
              <div className="flex flex-col gap-1.5">
                <Label>Mission</Label>
                <Textarea className="min-h-32" value={mission} onChange={(e) => setMission(e.target.value)} />
              </div>
              <div className="flex flex-col gap-1.5">
                <Label>Focus keywords</Label>
                <Textarea className="min-h-20" value={keywords} onChange={(e) => setKeywords(e.target.value)} />
              </div>
              <div className="flex flex-col gap-1.5">
                <Label>Zero-equity / claim boundary</Label>
                <Textarea className="min-h-28" value={zero} onChange={(e) => setZero(e.target.value)} />
              </div>
              <div className="flex flex-col gap-1.5">
                <Label>Geography</Label>
                <Input value={geo} onChange={(e) => setGeo(e.target.value)} />
              </div>
              <Button type="submit">Save profile</Button>
            </form>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-5">
            <form className="flex flex-col gap-4" onSubmit={saveSettings}>
              <div className="flex items-center justify-between gap-3 rounded-lg bg-muted px-3 py-3">
                <div>
                  <p className="text-sm font-medium">Solicitation hold</p>
                  <p className="text-xs text-muted-foreground">
                    Super Admin drafts and logs requests. It never mails them. A staff member sends.
                  </p>
                </div>
                <Switch checked={hold} onCheckedChange={setHold} />
              </div>
              <div className="flex flex-col gap-1.5">
                <Label>Small-grant threshold (USD)</Label>
                <Input type="number" value={threshold} onChange={(e) => setThreshold(e.target.value)} />
              </div>
              <div className="flex flex-col gap-1.5">
                <Label>Minimum grant count</Label>
                <Input type="number" value={minGrants} onChange={(e) => setMinGrants(e.target.value)} />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="flex flex-col gap-1.5">
                  <Label>Asset floor</Label>
                  <Input type="number" value={floor} onChange={(e) => setFloor(e.target.value)} />
                </div>
                <div className="flex flex-col gap-1.5">
                  <Label>Asset ceiling</Label>
                  <Input type="number" value={ceil} onChange={(e) => setCeil(e.target.value)} />
                </div>
              </div>
              <Button type="submit">Save gates</Button>
            </form>
          </CardContent>
        </Card>
      </div>

      <Card className="mt-4">
        <CardContent className="p-5">
          <p className="mb-3 text-[11px] font-medium tracking-[0.16em] text-muted-foreground uppercase">
            cPanel mailboxes · Super Admin
          </p>
          <p className="mb-4 text-sm text-muted-foreground">
            Provisioned on the CFL cPanel. Award and DonorBox traffic forwards into the Donations inbox so a secured grant is recorded as a Layer 4 gift, not merged into the foundation pipeline.
          </p>
          <dl className="grid gap-4 sm:grid-cols-2 text-sm">
            <div>
              <dt className="text-[11px] tracking-wide text-muted-foreground uppercase">Donations</dt>
              <dd className="mt-1 font-mono text-primary">{DONATIONS_MAILBOX}</dd>
            </div>
            <div>
              <dt className="text-[11px] tracking-wide text-muted-foreground uppercase">Grant correspondence</dt>
              <dd className="mt-1 font-mono text-primary">{GRANTS_MAILBOX}</dd>
            </div>
          </dl>
        </CardContent>
      </Card>

      <Card className="mt-4">
        <CardContent className="p-5">
          <p className="mb-3 text-[11px] font-medium tracking-[0.16em] text-muted-foreground uppercase">
            Data sources · SPEC-003 §3
          </p>
          <div className="overflow-hidden rounded-lg">
            <table className="w-full min-w-[640px] text-left text-sm">
              <thead>
                <tr className="bg-primary text-[11px] tracking-wider text-primary-foreground uppercase">
                  <th className="px-3 py-2 font-semibold">Source</th>
                  <th className="px-3 py-2 font-semibold">Access</th>
                  <th className="px-3 py-2 font-semibold">Auth</th>
                  <th className="px-3 py-2 font-semibold">Role</th>
                  <th className="px-3 py-2 font-semibold">Layer</th>
                </tr>
              </thead>
              <tbody>
                {DATA_SOURCES.map((s) => (
                  <tr key={s.name} className="border-t border-border">
                    <td className="py-2 pr-3">{s.name}</td>
                    <td className="py-2 pr-3 text-muted-foreground">{s.cost}</td>
                    <td className="py-2 pr-3 text-muted-foreground">{s.auth}</td>
                    <td className="py-2 pr-3">{s.role}</td>
                    <td className="py-2">
                      <Badge variant="muted">{s.layer}</Badge>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </CardContent>
      </Card>

      <Card className="mt-4">
        <CardContent className="p-5">
          <p className="mb-3 text-[11px] font-medium tracking-[0.16em] text-muted-foreground uppercase">
            Acceptance criteria · A1–A16
          </p>
          <ol className="flex flex-col gap-2">
            {ACCEPTANCE.map((a) => (
              <li key={a.id} className="flex items-start gap-3 text-sm">
                <Badge variant={a.phase === 1 ? "success" : a.phase === 2 ? "warning" : "muted"} className="mt-0.5 shrink-0">
                  {a.id} · P{a.phase}
                </Badge>
                <span>{a.criterion}</span>
              </li>
            ))}
          </ol>
        </CardContent>
      </Card>

      <Card className="mt-4">
        <CardContent className="overflow-x-auto p-5">
          <p className="mb-3 text-[11px] font-medium tracking-[0.16em] text-muted-foreground uppercase">
            Paper privileges
          </p>
          <p className="mb-4 text-sm text-muted-foreground">
            Preview role <span className="font-medium text-foreground">{ROLE_DISPLAY[role]}</span> maps to paper role{" "}
            <span className="font-medium text-foreground">{ROLE_DISPLAY[paper]}</span>. Super Admin and Administrator
            share the back office.
          </p>
          <table className="w-full min-w-[52rem] text-left text-sm">
            <thead className="text-[11px] tracking-wide text-muted-foreground uppercase">
              <tr className="border-b border-border">
                <th className="pb-2 font-medium">Action</th>
                {PAPER_ROLES.map((r) => (
                  <th key={r} className="pb-2 text-center font-medium">
                    {ROLE_DISPLAY[r]}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {PRIVILEGE_ROWS.map((row) => (
                <tr key={row.action} className="border-b border-border/70">
                  <td className="py-3 pr-4 font-medium">{row.action}</td>
                  {PAPER_ROLES.map((r) => {
                    const allowed = row.roles.includes(r);
                    return (
                      <td key={r} className="py-3 text-center">
                        {allowed ? (
                          <span className="inline-flex size-6 items-center justify-center rounded-full bg-success/15 text-success">
                            <Check className="size-3.5" />
                          </span>
                        ) : (
                          <span className="text-muted-foreground">—</span>
                        )}
                      </td>
                    );
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </CardContent>
      </Card>

      <p className="mt-6 max-w-3xl text-[11px] leading-relaxed text-muted-foreground">{PATENT_NOTICE}</p>
    </AppShell>
  );
}
