"use client";

import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import {
  getPolicyOcrStatus,
  listPolicyOcrBatches,
  uploadPolicyOcrBatch,
} from "@/lib/api";
import { useCan } from "@/lib/abilities";
import { formatDate } from "@/lib/labels";
import type { PolicyOcrBatch, PolicyOcrBatchStatus } from "@/lib/types";

/**
 * Insurance OCR intake — mirror of StatementIntake, scoped to the insurance
 * side. Today the only provider is GMX; the parser dispatches on a brand
 * wordmark (`Grupo Mexicano de Seguros` / `gmx.com.mx` / the GMX letterhead)
 * and a new portal only needs a new BRAND entry plus a parser file.
 *
 * Lives inside the `Pólizas` page rather than a top-level route because it
 * is one mode of one job (staff uploading whatever PDFs the office has on
 * hand that day, mixed service vs insurance), and the matching/review queue
 * already keys on the policyNumber → existing Policy transition that the
 * rest of /polizas owns.
 */

const STATUS_LABEL: Record<PolicyOcrBatchStatus, string> = {
  UPLOADED: "Recibido",
  PROCESSING: "Procesando…",
  READY_FOR_REVIEW: "Listo para revisar",
  COMPLETED: "Aplicado",
  FAILED: "Falló",
  DISCARDED: "Descartado",
};

export function PolicyOcrIntake() {
  const canIngest = useCan("policy:ingest");
  const [batches, setBatches] = useState<PolicyOcrBatch[]>([]);
  const [ocrAvailable, setOcrAvailable] = useState<boolean | null>(null);
  const [storageAvailable, setStorageAvailable] = useState<boolean | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      const [list, status] = await Promise.all([
        listPolicyOcrBatches(),
        getPolicyOcrStatus(),
      ]);
      setBatches(list.items);
      setOcrAvailable(status.ocrAvailable);
      setStorageAvailable(status.storageAvailable);
      setError(null);
    } catch (e) {
      setError((e as Error)?.message ?? "No se pudieron cargar los lotes.");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void load();
  }, [load]);

  const working = batches.some(
    (b) => b.status === "PROCESSING" || b.status === "UPLOADED",
  );
  useEffect(() => {
    if (!working) return;
    const t = setInterval(() => void load(), 4000);
    return () => clearInterval(t);
  }, [working, load]);

  const ready = ocrAvailable === true && storageAvailable === true;

  return (
    <div className="stack">
      {ocrAvailable === false && (
        <div className="state-box state-error">
          Este servidor no tiene OCR instalado, así que no se pueden leer PDFs
          de pólizas escaneados. La captura manual sigue funcionando.
        </div>
      )}

      {storageAvailable === false && (
        <div className="state-box state-error">
          Este servidor no tiene configurado el almacenamiento de documentos, así
          que no hay dónde guardar los PDFs. Mientras tanto, capture las
          pólizas a mano.
        </div>
      )}

      {canIngest && ready && <UploadCard onDone={load} />}

      {error && <div className="state-box state-error">{error}</div>}

      <section className="card" style={{ padding: 16 }}>
        <h2 className="section-title" style={{ marginTop: 0 }}>
          Lotes
        </h2>
        {loading ? (
          <div className="state-box">Cargando…</div>
        ) : batches.length === 0 ? (
          <div className="state-box">
            Todavía no hay lotes de pólizas. Descargue el certificado del portal
            de GMX y suéltelo arriba.
          </div>
        ) : (
          <div className="tx-scroll">
            <table className="tx-table">
              <thead>
                <tr>
                  <th>Fecha</th>
                  <th>Aseguradora</th>
                  <th>Referencia</th>
                  <th>Estado</th>
                  <th className="num">Páginas</th>
                  <th>Subido por</th>
                  <th />
                </tr>
              </thead>
              <tbody>
                {batches.map((b) => (
                  <tr key={b.id}>
                    <td style={{ whiteSpace: "nowrap" }}>{formatDate(b.createdAt)}</td>
                    <td>{b.provider}</td>
                    <td>{b.label || "—"}</td>
                    <td>
                      <StatusTag status={b.status} />
                      {b.error && (
                        <div className="page-sub" style={{ marginTop: 4 }}>
                          {b.error}
                        </div>
                      )}
                    </td>
                    <td className="num">{b._count?.documents ?? 0}</td>
                    <td>{b.uploadedBy?.name ?? "—"}</td>
                    <td>
                      <Link
                        className="btn btn-ghost"
                        href={`/polizas/captura/${b.id}`}
                      >
                        Revisar
                      </Link>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </section>
    </div>
  );
}

function StatusTag({ status }: { status: PolicyOcrBatchStatus }) {
  return <span className="tag">{STATUS_LABEL[status] ?? status}</span>;
}

function UploadCard({ onDone }: { onDone: () => void }) {
  const [files, setFiles] = useState<File[]>([]);
  const [label, setLabel] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function submit() {
    if (!files.length) return;
    setBusy(true);
    setError(null);
    try {
      await uploadPolicyOcrBatch(files, label.trim() || undefined);
      setFiles([]);
      setLabel("");
      onDone();
    } catch (e) {
      setError((e as Error)?.message ?? "No se pudo subir el lote.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <section className="card" style={{ padding: 16 }}>
      <h2 className="section-title" style={{ marginTop: 0 }}>
        Subir PDFs de pólizas (GMX)
      </h2>
      <div className="inline-form" style={{ flexWrap: "wrap", gap: 12 }}>
        <label>
          <span className="page-sub">Referencia (opcional)</span>
          <input
            className="input"
            placeholder="ej. GMX julio 2026"
            value={label}
            onChange={(e) => setLabel(e.target.value)}
          />
        </label>

        <label>
          <span className="page-sub">Archivos PDF</span>
          <input
            type="file"
            className="input"
            accept="application/pdf"
            multiple
            onChange={(e) => setFiles(Array.from(e.target.files ?? []))}
          />
        </label>

        <button
          type="button"
          className="btn btn-primary"
          disabled={!files.length || busy}
          onClick={submit}
        >
          {busy ? "Subiendo…" : `Procesar ${files.length || ""}`.trim()}
        </button>
      </div>

      {error && (
        <div className="state-box state-error" style={{ marginTop: 12 }}>
          {error}
        </div>
      )}

      <p className="page-sub" style={{ marginTop: 12 }}>
        Un lote puede traer varios PDFs. Cada página se procesa por separado; el
        sistema busca una póliza existente por número y, si no la encuentra,
        propone crear una nueva bajo el cliente que se elija en la revisión.
      </p>
    </section>
  );
}