// app/admin/conciliacion/page.tsx
// Reconciliation view (admin.md section 2.4) surfacing the four mismatch classes,
// never silently. Reads from lib/reconcile (agent D) when available, otherwise
// queries the DB directly for the locally-detectable classes and clearly notes
// which classes require a provider pull (the nightly job). The "reconciled
// through" timestamp shows when the pool was last proven against the provider.

import * as React from "react";
import { redirect } from "next/navigation";
import { requireRole, AuthError } from "@/lib/auth";
import { listRaffles, getReconcileView } from "@/app/admin/_lib/queries";
import { RaffleSwitcher } from "@/components/admin/RaffleSwitcher";
import { Card, Badge } from "@/components/ui";

export const dynamic = "force-dynamic";

const CLASS_LABELS: Record<1 | 2 | 3 | 4, string> = {
  1: "Confirmado local sin pago en el proveedor",
  2: "Pagado en el proveedor pero pendiente local (webhook perdido)",
  3: "Reembolsado pero oportunidades no anuladas",
  4: "Monto distinto entre local y proveedor",
};

export default async function ReconciliationPage({
  searchParams,
}: {
  searchParams: Promise<{ raffle?: string }>;
}) {
  try {
    await requireRole("viewer");
  } catch (err) {
    if (err instanceof AuthError) redirect("/admin/login");
    throw err;
  }

  const raffles = await listRaffles();
  if (raffles.length === 0) {
    return (
      <div>
        <h1 className="font-impact text-heading-lg font-bold text-ink-strong">
          Conciliación
        </h1>
        <p className="mt-4 font-body text-body-lg text-muted">
          Aún no hay sorteos creados.
        </p>
      </div>
    );
  }

  const { raffle: raffleParam } = await searchParams;
  const selected = raffles.find((r) => r.id === raffleParam) ?? raffles[0];
  const view = await getReconcileView(selected.id);

  const hasCriticalClass = view.classCounts[1] > 0 || view.classCounts[3] > 0;

  return (
    <div className="flex flex-col gap-lg">
      <div className="flex flex-wrap items-center justify-between gap-md">
        <h1 className="font-impact text-heading-lg font-bold text-ink-strong">
          Conciliación
        </h1>
        <RaffleSwitcher
          raffles={raffles.map((r) => ({ id: r.id, name: r.name, status: r.status }))}
          selectedId={selected.id}
        />
      </div>

      <p className="font-body text-caption text-muted">
        Fuente: {view.source === "lib/reconcile" ? "trabajo de conciliación" : "consulta directa a la base de datos"}.{" "}
        {view.reconciledThrough
          ? `Conciliado hasta ${new Date(view.reconciledThrough).toLocaleString("es-PE")}.`
          : "El pool aún no fue contrastado con el proveedor."}
      </p>

      {/* Class summary tiles */}
      <section
        aria-label="Resumen de discrepancias"
        className="grid grid-cols-1 gap-md sm:grid-cols-2 lg:grid-cols-4"
      >
        {([1, 2, 3, 4] as const).map((k) => {
          const count = view.classCounts[k];
          const critical = k === 1 || k === 3;
          return (
            <Card key={k} elevation="tight" className="p-lg">
              <div className="flex items-center gap-2">
                <span className="font-impact text-heading-md font-bold text-ink-strong">
                  {count}
                </span>
                {count > 0 ? (
                  <Badge tone={critical ? "primary" : "neutral"}>
                    {critical ? "Crítico" : "Revisar"}
                  </Badge>
                ) : (
                  <Badge tone="blue">OK</Badge>
                )}
              </div>
              <p className="mt-2 font-body text-caption text-muted-label">
                Clase {k}: {CLASS_LABELS[k]}
              </p>
            </Card>
          );
        })}
      </section>

      {hasCriticalClass ? (
        <p
          role="alert"
          className="rounded-md border border-primary bg-primary-tint/20 px-4 py-3 font-body text-body-md font-bold text-ink-strong"
        >
          Hay discrepancias críticas (clase 1 o clase 3). Resuélvelas antes de
          congelar el snapshot del sorteo: una clase 1 mete dinero inexistente al
          pool y una clase 3 deja una oportunidad reembolsada en el pool.
        </p>
      ) : null}

      <Card elevation="tight" className="p-lg">
        <h2 className="font-display text-heading-md font-bold text-ink-strong">
          Discrepancias detectadas
        </h2>
        {view.mismatches.length === 0 ? (
          <p className="mt-3 font-body text-body-md text-muted">
            No se detectaron discrepancias con los datos locales disponibles.
          </p>
        ) : (
          <div className="mt-4 overflow-x-auto">
            <table className="w-full border-collapse text-left">
              <caption className="sr-only">
                Discrepancias de conciliación por compra
              </caption>
              <thead>
                <tr className="border-b border-hairline">
                  <Th>Clase</Th>
                  <Th>Tipo</Th>
                  <Th>Compra</Th>
                  <Th>Cargo proveedor</Th>
                  <Th>Detalle</Th>
                </tr>
              </thead>
              <tbody>
                {view.mismatches.map((m, i) => (
                  <tr key={i} className="border-b border-hairline last:border-0">
                    <Td>{m.klass}</Td>
                    <Td>{m.label}</Td>
                    <Td>
                      <span className="break-all text-caption">{m.purchaseId}</span>
                    </Td>
                    <Td>
                      <span className="break-all text-caption">
                        {m.providerChargeId ?? "sin cargo"}
                      </span>
                    </Td>
                    <Td>{m.detail}</Td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Card>

      {view.notes.length > 0 ? (
        <Card elevation="flat" className="border border-hairline p-lg">
          <h3 className="font-body text-body-lg font-bold text-ink-strong">
            Notas
          </h3>
          <ul className="mt-2 flex list-disc flex-col gap-1.5 pl-5 font-body text-caption text-muted">
            {view.notes.map((n, i) => (
              <li key={i}>{n}</li>
            ))}
          </ul>
        </Card>
      ) : null}
    </div>
  );
}

function Th({ children }: { children: React.ReactNode }) {
  return (
    <th
      scope="col"
      className="py-2 pr-4 font-body text-caption font-medium text-muted-label"
    >
      {children}
    </th>
  );
}
function Td({ children }: { children: React.ReactNode }) {
  return (
    <td className="py-2 pr-4 align-top font-body text-body-md text-ink-strong">
      {children}
    </td>
  );
}
