import { createFileRoute, Link, useRouter } from "@tanstack/react-router";
import { ArrowLeft, Mail } from "lucide-react";
import { 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 { NativeSelect, Textarea } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  METHOD_LABEL,
  RESPONSE_LABEL,
  RESPONSE_TYPES,
  SOLICITATION_STATUS_LABEL,
  SOLICITATION_STATUSES,
  type Method,
  type ResponseType,
  type SolicitationStatus,
} from "@/lib/constants";
import { getShellMeta } from "@/lib/server/api-core";
import {
  addSolicitationResponse,
  archiveSolicitation,
  getSolicitation,
  updateSolicitationStatus,
} from "@/lib/server/api-pipeline";
import { formatDate, formatDateTime, moneyRange, relativeDeadline } from "@/lib/utils";

export const Route = createFileRoute("/outreach/$id")({
  loader: async ({ params }) => {
    const [meta, detail] = await Promise.all([getShellMeta(), getSolicitation({ data: { id: params.id } })]);
    return { meta, detail };
  },
  component: SolicitationDetail,
});

function statusVariant(status: string) {
  if (status === "sent" || status === "awarded") return "success" as const;
  if (status === "hold" || status === "queued") return "warning" as const;
  if (status === "declined" || status === "archived") return "destructive" as const;
  return "muted" as const;
}

function SolicitationDetail() {
  const { meta, detail } = Route.useLoaderData();
  const router = useRouter();
  const { solicitation: s, responses, events } = detail;
  const [status, setStatus] = useState<SolicitationStatus>((s?.status as SolicitationStatus) ?? "queued");
  const [respType, setRespType] = useState<ResponseType>("replied");
  const [reply, setReply] = useState("");
  const [saving, setSaving] = useState(false);

  if (!s) {
    return (
      <AppShell>
        <p>Not found.</p>
      </AppShell>
    );
  }

  async function save() {
    setSaving(true);
    try {
      await updateSolicitationStatus({ data: { id: s.id, status } });
      toast.success("Status saved");
      await router.invalidate();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Could not save");
    } finally {
      setSaving(false);
    }
  }

  async function appendReply() {
    try {
      await addSolicitationResponse({
        data: { solicitationId: s.id, response_type: respType, raw_content: reply || undefined },
      });
      toast.success("Response appended — prior history is unchanged");
      setReply("");
      await router.invalidate();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed");
    }
  }

  async function archive() {
    try {
      await archiveSolicitation({ data: { id: s.id } });
      toast.success("Archived");
      await router.invalidate();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Could not archive");
    }
  }

  return (
    <AppShell hold={meta.hold} unread={meta.unread} noticeCount={meta.noticeCount} inboxUnread={meta.inboxUnread}>
      <div className="mb-4">
        <Link to="/outreach" className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-primary">
          <ArrowLeft className="size-4" />
          Back to what we sent
        </Link>
      </div>
      <PageHeader
        kicker="What we sent · letter record"
        title={s.foundation_name ?? "Sent request"}
        description={`${s.sent_at ? `Mailed ${formatDateTime(s.sent_at)}` : "Not mailed — sitting on hold"}${s.contact_name ? ` · ${s.contact_name}` : ""}${s.contact_role ? ` · ${s.contact_role}` : ""}`}
        actions={
          <Badge variant={statusVariant(s.status)}>
            {SOLICITATION_STATUS_LABEL[s.status as SolicitationStatus] ?? s.status}
          </Badge>
        }
      />

      <div className="grid gap-4 lg:grid-cols-[1fr_320px]">
        <div className="flex flex-col gap-4">
          <Card>
            <CardContent className="p-5">
              <p className="mb-4 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">Grantor & send record</p>
              <dl className="grid gap-4 sm:grid-cols-3 text-sm">
                <Field label="Foundation" value={s.foundation_name} />
                <Field label="Named contact" value={`${s.contact_name}${s.contact_role ? ` · ${s.contact_role}` : ""}`} />
                <Field
                  label="Location"
                  value={[s.foundation_city, s.foundation_state].filter(Boolean).join(", ") || "—"}
                />
                <Field label="How" value={METHOD_LABEL[s.method as Method] ?? s.method} />
                <Field label="Date sent" value={s.sent_at ? formatDateTime(s.sent_at) : "Not sent"} />
                <Field label="Sent by" value={s.sent_by} />
                <Field label="Amount band" value={moneyRange(s.amount_min ?? null, s.amount_max ?? null)} />
                <Field label="Package" value={s.package_filename ?? s.package_ref} />
                <Field label="Pipeline stage" value={s.relationship_stage} />
              </dl>
              {s.hold_reason ? <p className="mt-4 text-sm text-warning">{s.hold_reason}</p> : null}
              {s.notes ? <p className="mt-3 text-sm text-muted-foreground">{s.notes}</p> : null}
            </CardContent>
          </Card>

          <Card>
            <CardContent className="p-5">
              <p className="mb-1 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">
                Original request for proposal
              </p>
              <p className="mb-4 text-xs text-muted-foreground">
                The RFP this letter answered — what the grantor asked for, before we wrote anything.
              </p>
              {s.opportunity_title ? (
                <div className="text-sm">
                  <p className="font-medium">{s.opportunity_title}</p>
                  <p className="mt-1 text-muted-foreground">{s.funder_name}</p>
                  <dl className="mt-4 grid gap-3 sm:grid-cols-2">
                    <Field label="Deadline" value={`${formatDate(s.deadline ?? null)} · ${relativeDeadline(s.deadline ?? null)}`} />
                    <Field label="Ask band" value={moneyRange(s.amount_min ?? null, s.amount_max ?? null)} />
                  </dl>
                  {s.eligibility_raw ? (
                    <p className="mt-3 leading-relaxed text-muted-foreground">{s.eligibility_raw}</p>
                  ) : null}
                  {s.opportunity_id ? (
                    <Link
                      to="/opportunities/$id"
                      params={{ id: s.opportunity_id }}
                      className="mt-3 inline-block text-sm text-primary hover:underline"
                    >
                      Open opportunity record
                    </Link>
                  ) : null}
                </div>
              ) : (
                <p className="text-sm text-muted-foreground">No RFP attached to this solicitation.</p>
              )}
            </CardContent>
          </Card>

          <Card>
            <CardContent className="p-5">
              <p className="mb-1 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">
                The letter that went out
              </p>
              <p className="mb-4 text-xs text-muted-foreground">
                Exact snapshot of what CFL sent (or would send). This is not the catalog listing — it is the request.
              </p>
              {s.package_text ? (
                <pre className="max-h-[22rem] overflow-auto whitespace-pre-wrap font-sans text-sm leading-relaxed text-foreground/90">
                  {s.package_text}
                </pre>
              ) : (
                <p className="text-sm text-muted-foreground">No letter snapshot was stored for this send.</p>
              )}
            </CardContent>
          </Card>

          <Card>
            <CardContent className="p-5">
              <p className="mb-4 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">
                Response history · append-only
              </p>
              {responses.length === 0 ? (
                <p className="text-sm text-muted-foreground">None logged.</p>
              ) : (
                <ol className="space-y-4">
                  {responses.map((r) => (
                    <li key={r.id} className="border-l-2 border-primary/40 pl-4 text-sm">
                      <p className="font-medium">
                        {RESPONSE_LABEL[r.response_type as ResponseType] ?? r.response_type}
                      </p>
                      <p className="text-muted-foreground">
                        {formatDateTime(r.responded_at)} · {r.actor_id}
                      </p>
                      {r.raw_content ? (
                        <p className="mt-2 whitespace-pre-wrap leading-relaxed">{r.raw_content}</p>
                      ) : null}
                      {r.notes ? <p className="mt-1 text-muted-foreground">{r.notes}</p> : null}
                    </li>
                  ))}
                </ol>
              )}
            </CardContent>
          </Card>
        </div>

        <div className="flex flex-col gap-4 lg:sticky lg:top-20 lg:self-start">
          <Card>
            <CardContent className="p-5">
              <p className="mb-3 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">Review status</p>
              <Badge variant={statusVariant(s.status)} className="mb-4">
                {SOLICITATION_STATUS_LABEL[s.status as SolicitationStatus] ?? s.status}
              </Badge>
              <div className="flex flex-col gap-1.5">
                <Label>Update status</Label>
                <NativeSelect value={status} onChange={(e) => setStatus(e.target.value as SolicitationStatus)}>
                  {SOLICITATION_STATUSES.map((st) => (
                    <option key={st} value={st}>
                      {SOLICITATION_STATUS_LABEL[st]}
                    </option>
                  ))}
                </NativeSelect>
              </div>
              <div className="mt-4 flex flex-col gap-1.5">
                <Label>Log a response</Label>
                <NativeSelect value={respType} onChange={(e) => setRespType(e.target.value as ResponseType)}>
                  {RESPONSE_TYPES.map((t) => (
                    <option key={t} value={t}>
                      {RESPONSE_LABEL[t]}
                    </option>
                  ))}
                </NativeSelect>
                <Textarea
                  className="mt-2"
                  value={reply}
                  onChange={(e) => setReply(e.target.value)}
                  placeholder="Paste the foundation’s reply. Prior responses are never overwritten."
                />
              </div>
              <Button className="mt-4 w-full" onClick={save} disabled={saving}>
                Save changes
              </Button>
              <Button className="mt-2 w-full" variant="outline" onClick={appendReply}>
                Append response
              </Button>
              <Button className="mt-2 w-full" variant="archive" onClick={archive}>
                Archive request
              </Button>
              <Link
                to="/donations/inbox"
                className="mt-4 inline-flex items-center gap-1.5 text-sm text-primary hover:underline"
              >
                <Mail className="size-4" />
                Open donations mailbox
              </Link>
            </CardContent>
          </Card>
          <Card>
            <CardContent className="p-5">
              <p className="mb-3 text-[11px] tracking-[0.16em] text-muted-foreground uppercase">Audit</p>
              <ul className="space-y-2 text-xs text-muted-foreground">
                {events.map((e) => (
                  <li key={e.id}>
                    {formatDateTime(e.created_at)} · {e.event_type}
                    {e.notes ? ` — ${e.notes}` : ""}
                  </li>
                ))}
              </ul>
            </CardContent>
          </Card>
        </div>
      </div>
    </AppShell>
  );
}

function Field({
  label,
  value,
  href,
}: {
  label: string;
  value?: string | null;
  href?: string | null;
}) {
  return (
    <div>
      <dt className="text-[11px] tracking-wide text-muted-foreground uppercase">{label}</dt>
      <dd className="mt-0.5">
        {href ? (
          <a href={href} className="text-primary hover:underline" target="_blank" rel="noreferrer">
            {value}
          </a>
        ) : (
          value || "—"
        )}
      </dd>
    </div>
  );
}
