import { nteeDescription } from '@novelpad/outreach-core';
import {
  serverGetMatchDetail,
  serverSetMatchReview,
} from '@novelpad/outreach-core/server';
import { Form, Link, redirect } from 'react-router';

import { db } from '#~/db.server.js';

import type { Route } from './+types/matches.$matchId.js';

export async function loader({ request, params }: Route.LoaderArgs) {
  if (request.method === 'HEAD') return;

  const detail = await serverGetMatchDetail(db, params.matchId);
  if (detail == null) {
    throw new Response('Match not found', { status: 404 });
  }
  return { detail };
}

export async function action({ request, params }: Route.ActionArgs) {
  if (request.method === 'HEAD') return;

  const formData = await request.formData();
  const decision = formData.get('decision');
  if (decision !== 'approved' && decision !== 'rejected') {
    throw new Response('Invalid review submission', { status: 400 });
  }

  await serverSetMatchReview(db, {
    matchId: params.matchId,
    reviewStatus: decision,
    rejectReason: decision === 'rejected' ? 'other' : undefined,
  });
  return redirect('/');
}

function dollars(n: number | null): string {
  if (n == null) return '—';
  return `$${n.toLocaleString('en-US')}`;
}

const SUBSCORE_MAX: Record<string, number> = {
  missionFit: 30,
  funderPrecedent: 25,
  capacityFit: 15,
  competition: 15,
  effort: 10,
  runway: 5,
};

export default function MatchDetail({ loaderData }: Route.ComponentProps) {
  const { detail } = loaderData ?? {};
  if (detail == null) return null;
  const { match, org, grant, funderGivingHistory, funderApplicationInfo } =
    detail;
  const applyInfo = (funderApplicationInfo ?? null) as {
    preselectedOnly?: boolean;
    recipientName?: string;
    formAndInfoAndMaterials?: string;
    submissionDeadlines?: string;
    restrictionsOnAwards?: string;
  } | null;
  const subscores = (match.subscores ?? {}) as Record<string, number>;
  const rationale = (match.rationale ?? {}) as Record<string, unknown>;
  const nhHistory = funderGivingHistory;

  return (
    <main className="container mx-auto max-w-4xl space-y-6 p-6">
      <nav>
        <Link to="/" className="text-blue-700 underline">
          ← Back to queue
        </Link>
      </nav>

      <header className="flex items-start justify-between gap-4">
        <div>
          <h1 className="text-2xl font-semibold">
            {org.name} ↔ {grant.funder}
          </h1>
          <p className="text-gray-600">
            Score {match.totalScore}/100
            {match.easyWin ? ' · Easy win' : ''}
            {match.isHero ? ' · Hero' : ''} · Status: {match.reviewStatus}
          </p>
        </div>
        <div className="flex shrink-0 gap-2">
          <Form method="post">
            <input type="hidden" name="decision" value="approved" />
            <button
              type="submit"
              className="rounded bg-green-600 px-4 py-2 text-white hover:bg-green-700"
            >
              Approve
            </button>
          </Form>
          <Form method="post">
            <input type="hidden" name="decision" value="rejected" />
            <button
              type="submit"
              className="rounded bg-red-600 px-4 py-2 text-white hover:bg-red-700"
            >
              Reject
            </button>
          </Form>
        </div>
      </header>

      <section className="grid gap-6 md:grid-cols-2">
        <div className="rounded border p-4">
          <h2 className="mb-2 text-lg font-semibold">Organization</h2>
          <dl className="space-y-1 text-sm">
            <div>
              <dt className="inline font-medium">Location: </dt>
              <dd className="inline">
                {[org.city, org.state].filter(Boolean).join(', ')}
              </dd>
            </div>
            <div>
              <dt className="inline font-medium">Focus (NTEE): </dt>
              <dd className="inline">
                {org.nteeCode ?? '—'}
                {nteeDescription(org.nteeCode) != null &&
                  ` — ${nteeDescription(org.nteeCode)}`}
              </dd>
            </div>
            <div>
              <dt className="inline font-medium">Annual revenue: </dt>
              <dd className="inline">{dollars(org.totalRevenue)}</dd>
            </div>
            <div>
              <dt className="inline font-medium">Mission (profile): </dt>
              <dd className="inline">
                {org.missionStatement ?? '—'}
                {org.profileConfidence != null &&
                  org.profileConfidence <= 0.2 && (
                    <span className="text-amber-700">
                      {' '}
                      (auto-generated stub — verify on their website)
                    </span>
                  )}
              </dd>
            </div>
          </dl>
          <div className="mt-3 space-x-3 text-sm">
            {org.ein != null && (
              <a
                className="text-blue-700 underline"
                href={`https://projects.propublica.org/nonprofits/organizations/${org.ein.replace(/^0+/, '')}`}
                target="_blank"
                rel="noreferrer"
              >
                ProPublica filings ↗
              </a>
            )}
            <a
              className="text-blue-700 underline"
              href={`https://www.google.com/search?q=${encodeURIComponent(`"${org.name}" ${org.city ?? ''} NH nonprofit`)}`}
              target="_blank"
              rel="noreferrer"
            >
              Search their site ↗
            </a>
          </div>
        </div>

        <div className="rounded border p-4">
          <h2 className="mb-2 text-lg font-semibold">Grant</h2>
          <dl className="space-y-1 text-sm">
            <div>
              <dt className="inline font-medium">Title: </dt>
              <dd className="inline">{grant.title}</dd>
            </div>
            <div>
              <dt className="inline font-medium">Award: </dt>
              <dd className="inline">
                {dollars(grant.awardFloor)} – {dollars(grant.awardCeiling)}
              </dd>
            </div>
            <div>
              <dt className="inline font-medium">Closes: </dt>
              <dd className="inline">
                {grant.closeDate == null
                  ? 'Rolling / no stated deadline'
                  : new Date(grant.closeDate).toLocaleDateString('en-US')}
              </dd>
            </div>
            <div>
              <dt className="inline font-medium">Source: </dt>
              <dd className="inline">{grant.source}</dd>
            </div>
            {grant.eligibilityEntityTypes != null &&
              grant.eligibilityEntityTypes.length > 0 && (
                <div>
                  <dt className="inline font-medium">Eligibility: </dt>
                  <dd className="inline">
                    {grant.eligibilityEntityTypes.join('; ')}
                  </dd>
                </div>
              )}
          </dl>
          <div className="mt-3 text-sm">
            <a
              className="text-blue-700 underline"
              href={grant.sourceUrl}
              target="_blank"
              rel="noreferrer"
            >
              {grant.source === 'irs_990pf'
                ? 'Funder on ProPublica ↗'
                : 'Grant listing ↗'}
            </a>
          </div>
        </div>
      </section>

      <section className="rounded border p-4">
        <h2 className="mb-2 text-lg font-semibold">Score breakdown</h2>
        <table className="w-full max-w-md text-sm">
          <tbody>
            {Object.entries(SUBSCORE_MAX).map(([key, max]) => (
              <tr key={key} className="border-b">
                <td className="py-1 capitalize">
                  {key.replace(/([A-Z])/g, ' $1').toLowerCase()}
                </td>
                <td className="py-1 text-right tabular-nums">
                  {subscores[key] ?? 0} / {max}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        {typeof rationale.similarity === 'number' && (
          <p className="mt-2 text-sm text-gray-600">
            Embedding similarity: {(rationale.similarity as number).toFixed(3)}
            {Array.isArray(rationale.gateFailures) &&
              (rationale.gateFailures as string[]).length > 0 &&
              ` · Ignored gate flags: ${(rationale.gateFailures as string[]).join(', ')}`}
          </p>
        )}
      </section>

      {applyInfo != null && (
        <section className="rounded border p-4">
          <h2 className="mb-2 text-lg font-semibold">
            How to apply (funder's own 990-PF, Part XV)
          </h2>
          {applyInfo.preselectedOnly === true && (
            <p className="mb-2 rounded bg-red-100 p-2 text-sm font-medium text-red-800">
              This funder states it only contributes to preselected
              organizations and does not accept unsolicited requests — do
              not pitch.
            </p>
          )}
          <dl className="space-y-1 text-sm">
            {applyInfo.formAndInfoAndMaterials != null && (
              <div>
                <dt className="inline font-medium">Application form: </dt>
                <dd className="inline">{applyInfo.formAndInfoAndMaterials}</dd>
              </div>
            )}
            {applyInfo.submissionDeadlines != null && (
              <div>
                <dt className="inline font-medium">Deadlines: </dt>
                <dd className="inline">{applyInfo.submissionDeadlines}</dd>
              </div>
            )}
            {applyInfo.restrictionsOnAwards != null && (
              <div>
                <dt className="inline font-medium">Restrictions: </dt>
                <dd className="inline">{applyInfo.restrictionsOnAwards}</dd>
              </div>
            )}
            {applyInfo.recipientName != null && (
              <div>
                <dt className="inline font-medium">Applications to: </dt>
                <dd className="inline">{applyInfo.recipientName}</dd>
              </div>
            )}
          </dl>
        </section>
      )}

      <section className="rounded border p-4">
        <h2 className="mb-2 text-lg font-semibold">Grant synopsis</h2>
        <p className="whitespace-pre-wrap text-sm">{grant.synopsis ?? '—'}</p>
      </section>

      {nhHistory.length > 0 && (
        <section className="rounded border p-4">
          <h2 className="mb-1 text-lg font-semibold">
            Funder giving history (from 990-PF filings)
          </h2>
          <p className="mb-3 text-sm text-gray-600">
            The concrete evidence behind the precedent score — who this
            funder actually paid, sorted in-state first.
          </p>
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b text-left">
                <th className="py-1 pr-2">Recipient</th>
                <th className="py-1 pr-2">City</th>
                <th className="py-1 pr-2 text-right">Amount</th>
                <th className="py-1 pr-2">Year</th>
                <th className="py-1">Purpose</th>
              </tr>
            </thead>
            <tbody>
              {nhHistory.map((g, i) => (
                <tr key={i} className="border-b align-top">
                  <td className="py-1 pr-2">{g.recipientName}</td>
                  <td className="py-1 pr-2">{g.recipientCity ?? '—'}</td>
                  <td className="py-1 pr-2 text-right tabular-nums">
                    {dollars(g.amount)}
                  </td>
                  <td className="py-1 pr-2">{g.taxYear}</td>
                  <td className="py-1">{g.purpose ?? '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </section>
      )}
    </main>
  );
}
