import { createFileRoute, Link, useRouter } from "@tanstack/react-router";
import { useState } from "react";
import { toast } from "sonner";
import { AppShell, PageHeader } from "@/components/app-shell";
import { FitBar, FitScore } from "@/components/fit-score";
import { PriorityBadge } from "@/components/priority-badge";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { getShellMeta } from "@/lib/server/api-core";
import { addRfpByUrl, listOpportunities, runGrantsGovSearch } from "@/lib/server/api-opps";
import { scoreUnscoredWithGrok } from "@/lib/server/api-ai";
import { formatDate, money, relativeDeadline } from "@/lib/utils";

export const Route = createFileRoute("/opportunities/")({
  loader: async () => {
    const [meta, opportunities] = await Promise.all([getShellMeta(), listOpportunities()]);
    return { meta, opportunities };
  },
  component: OpportunitiesPage,
});

function OpportunitiesPage() {
  const { meta, opportunities } = Route.useLoaderData();
  const router = useRouter();
  const [q, setQ] = useState("");
  const [hideKnock, setHideKnock] = useState(false);
  const [searching, setSearching] = useState(false);
  const [scoring, setScoring] = useState(false);
  const [open, setOpen] = useState(false);
  const [url, setUrl] = useState("");
  const [title, setTitle] = useState("");
  const [funder, setFunder] = useState("");
  const [deadline, setDeadline] = useState("");

  const filtered = opportunities.filter((o) => {
    if (hideKnock && o.knockout_reason) return false;
    if (!q) return true;
    const blob = `${o.title} ${o.funder_name} ${o.source}`.toLowerCase();
    return blob.includes(q.toLowerCase());
  });

  async function searchGov() {
    setSearching(true);
    try {
      const res = await runGrantsGovSearch({ data: { keyword: q || undefined } });
      toast.message(
        `Checked ${res.ingested} Grants.gov listings; ${res.created} ${res.created === 1 ? "was" : "were"} new to the catalog.`,
        {
          description: res.errors[0]?.message ?? "Nothing was submitted to a funder.",
        },
      );
      await router.invalidate();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Search failed");
    } finally {
      setSearching(false);
    }
  }

  async function addUrl(e: React.FormEvent) {
    e.preventDefault();
    try {
      const res = await addRfpByUrl({
        data: { url, title: title || undefined, funder_name: funder || undefined, deadline: deadline || undefined },
      });
      toast.success("RFP parsed into an opportunity");
      setOpen(false);
      await router.invalidate();
      await router.navigate({ to: "/opportunities/$id", params: { id: res.id } });
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Could not parse URL");
    }
  }

  return (
    <AppShell hold={meta.hold} unread={meta.unread} noticeCount={meta.noticeCount} inboxUnread={meta.inboxUnread}>
      <PageHeader
        kicker="Layer 1 · 2"
        title="Opportunities"
        description="Federal and URL-sourced RFPs. Keyword fit is automatic. Grok scores whether the grant is important enough to go after."
        actions={
          <>
            <Button
              variant="outline"
              disabled={scoring}
              onClick={async () => {
                setScoring(true);
                try {
                  const res = await scoreUnscoredWithGrok({ data: { limit: 5 } });
                  toast.message(`Grok scored ${res.scored} opportunit${res.scored === 1 ? "y" : "ies"}`, {
                    description: res.errors[0]?.error ?? (res.available ? undefined : "Grok key missing — knockouts still skip."),
                  });
                  await router.invalidate();
                } catch (err) {
                  toast.error(err instanceof Error ? err.message : "Score failed");
                } finally {
                  setScoring(false);
                }
              }}
            >
              {scoring ? "Scoring…" : "Ask Grok: go after?"}
            </Button>
            <Button variant="outline" onClick={searchGov} disabled={searching}>
              {searching ? "Searching…" : "Grants.gov search"}
            </Button>
            <Dialog open={open} onOpenChange={setOpen}>
              <DialogTrigger asChild>
                <Button>Add RFP by URL</Button>
              </DialogTrigger>
              <DialogContent title="Add RFP by URL" description="Eligibility and deadline are parsed from the page when possible.">
                <form className="flex flex-col gap-3" onSubmit={addUrl}>
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="url">URL</Label>
                    <Input id="url" required value={url} onChange={(e) => setUrl(e.target.value)} placeholder="https://" />
                  </div>
                  <div className="flex flex-col gap-1.5">
                    <Label htmlFor="title">Title (optional)</Label>
                    <Input id="title" value={title} onChange={(e) => setTitle(e.target.value)} />
                  </div>
                  <div className="grid gap-3 sm:grid-cols-2">
                    <div className="flex flex-col gap-1.5">
                      <Label htmlFor="funder">Funder</Label>
                      <Input id="funder" value={funder} onChange={(e) => setFunder(e.target.value)} />
                    </div>
                    <div className="flex flex-col gap-1.5">
                      <Label htmlFor="deadline">Deadline</Label>
                      <Input id="deadline" type="date" value={deadline} onChange={(e) => setDeadline(e.target.value)} />
                    </div>
                  </div>
                  <Button type="submit">Parse and score</Button>
                </form>
              </DialogContent>
            </Dialog>
          </>
        }
      />

      <div className="mb-4 flex flex-col gap-3 sm:flex-row sm:items-center">
        <Input
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Filter title, funder, source"
          className="sm:max-w-xs"
        />
        <label className="flex min-h-10 items-center gap-2 text-sm">
          <input type="checkbox" checked={hideKnock} onChange={(e) => setHideKnock(e.target.checked)} />
          Hide knockouts
        </label>
        <p className="text-sm text-muted-foreground sm:ml-auto">{filtered.length} records</p>
      </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">Opportunity</th>
              <th className="px-4 py-3 font-semibold">Fit</th>
              <th className="px-4 py-3 font-semibold">Go after</th>
              <th className="px-4 py-3 font-semibold">Amount</th>
              <th className="px-4 py-3 font-semibold">Deadline</th>
              <th className="px-4 py-3 font-semibold">Source</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((o) => (
              <tr key={o.id} className="border-b border-border last:border-0">
                <td className="px-4 py-3">
                  <Link to="/opportunities/$id" params={{ id: o.id }} className="font-medium hover:text-primary">
                    {o.title}
                  </Link>
                  <p className="text-muted-foreground">{o.funder_name}</p>
                  {o.knockout_reason ? (
                    <p className="mt-1 text-xs text-destructive">{o.knockout_reason}</p>
                  ) : o.fit_reason ? (
                    <p className="mt-1 line-clamp-2 text-xs text-muted-foreground">{o.fit_reason}</p>
                  ) : null}
                </td>
                <td className="px-4 py-3">
                  <FitScore score={o.fit_score} knockout={o.knockout_reason} />
                  {o.fit_score != null && !o.knockout_reason ? (
                    <div className="mt-2 w-20">
                      <FitBar score={o.fit_score} />
                    </div>
                  ) : null}
                </td>
                <td className="px-4 py-3">
                  <PriorityBadge priority={o.ai_priority} importance={o.ai_importance} />
                </td>
                <td className="px-4 py-3 tabular">
                  {o.amount_min || o.amount_max
                    ? `${money(o.amount_min, { compact: true })}–${money(o.amount_max, { compact: true })}`
                    : "—"}
                </td>
                <td className="px-4 py-3">
                  <p>{formatDate(o.deadline)}</p>
                  <p className="text-xs text-muted-foreground">{relativeDeadline(o.deadline)}</p>
                </td>
                <td className="px-4 py-3">
                  <Badge variant="muted">{o.source}</Badge>
                  {o.status === "closed" ? (
                    <Badge variant="outline" className="ml-1">
                      closed
                    </Badge>
                  ) : null}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        </div>
      </div>
    </AppShell>
  );
}
