"use client";

import { FormEvent, useEffect, useState } from "react";
import { dateTimeCL } from "../lib/datetime";
import { userMessage } from "../lib/messages";

const apiBase = process.env.NEXT_PUBLIC_API_BASE_URL || "/api/v1";
type Row = Record<string, unknown>;
type Data = { repositorios: Row[]; metricas: Row; consultas: Row[] };
const blank: Row = { codigo: "", nombre: "", descripcion: "", tipo_conector: "HTTP_JSON",
  endpoint_base: "", metodo_http: "GET", codigo_parametro: "codigo", auth_tipo: "NINGUNA",
  auth_header: "", prioridad: 100, timeout_ms: 4000, max_intentos: 1, umbral_circuito: 3,
  activo: true, found_path: "", status_path: "", code_path: "", document_name_path: "",
  issuer_path: "", issued_at_path: "", signed_at_path: "", document_status_path: "",
  signature_status_path: "", hash_path: "", document_url_path: "",
  valid_values: ["VALIDO", "VALID", "VERIFIED", "VIGENTE"],
  invalid_values: ["INVALIDO", "INVALID", "REVOKED", "REVOCADO"],
  not_found_values: ["NO_ENCONTRADO", "NOT_FOUND", "MISSING"] };

function text(value: unknown) { return value === null || value === undefined ? "" : String(value); }
function list(value: FormDataEntryValue | null) { return text(value).split(",").map((item) => item.trim()).filter(Boolean); }
function detail(value: unknown, fallback: string) {
  if (typeof value === "string") return value;
  if (Array.isArray(value)) return value.map((item) => typeof item === "object" && item && "msg" in item ? String(item.msg) : String(item)).join(" · ");
  return fallback;
}

export default function VerificationManagement({ csrf, notify }: { csrf: () => Promise<string>; notify: (message: string) => void }) {
  const [data, setData] = useState<Data | null>(null), [editing, setEditing] = useState<Row | null>(null);
  const [credential, setCredential] = useState<Row | null>(null), [testing, setTesting] = useState<Row | null>(null);
  const [selected, setSelected] = useState<Row | null>(null), [busy, setBusy] = useState(false);
  async function request(path = "", options: RequestInit = {}) {
    const response = await fetch(`${apiBase}/panel/admin/verificacion${path}`, { credentials: "include", cache: "no-store", ...options });
    if (response.status === 401) { sessionStorage.removeItem("documenta:csrf"); window.location.replace("/acceso?motivo=sesion-expirada"); throw new Error("Sesión expirada"); }
    const body = await response.json();
    if (!response.ok) throw new Error(detail(body.detail, "No fue posible completar la operación."));
    return body;
  }
  async function load() { setBusy(true); try { setData(await request() as Data); } catch (reason) { notify(userMessage(reason, "No fue posible cargar la verificación.")); } finally { setBusy(false); } }
  useEffect(() => {
    let active = true;
    void (async () => {
      try {
        const response = await fetch(`${apiBase}/panel/admin/verificacion`, { credentials: "include", cache: "no-store" });
        if (response.status === 401) { window.location.replace("/acceso?motivo=sesion-expirada"); return; }
        const body = await response.json();
        if (!response.ok) throw new Error(detail(body.detail, "No fue posible cargar la verificación."));
        if (active) setData(body as Data);
      } catch (reason) { if (active) notify(userMessage(reason, "No fue posible cargar la verificación.")); }
    })();
    return () => { active = false; };
  }, [notify]);

  async function saveRepository(event: FormEvent<HTMLFormElement>) {
    event.preventDefault(); setBusy(true); const form = new FormData(event.currentTarget);
    const payload = { codigo: form.get("codigo"), nombre: form.get("nombre"), descripcion: form.get("descripcion") || null,
      tipo_conector: form.get("tipo_conector"), endpoint_base: form.get("endpoint_base") || null,
      metodo_http: form.get("metodo_http"), codigo_parametro: form.get("codigo_parametro"),
      auth_tipo: form.get("auth_tipo"), auth_header: form.get("auth_header") || null,
      prioridad: Number(form.get("prioridad")), timeout_ms: Number(form.get("timeout_ms")),
      max_intentos: Number(form.get("max_intentos")), umbral_circuito: Number(form.get("umbral_circuito")),
      activo: form.get("activo") === "on", found_path: form.get("found_path") || null,
      status_path: form.get("status_path") || null, code_path: form.get("code_path") || null,
      document_name_path: form.get("document_name_path") || null, issuer_path: form.get("issuer_path") || null,
      issued_at_path: form.get("issued_at_path") || null, signed_at_path: form.get("signed_at_path") || null,
      document_status_path: form.get("document_status_path") || null,
      signature_status_path: form.get("signature_status_path") || null, hash_path: form.get("hash_path") || null,
      document_url_path: form.get("document_url_path") || null, valid_values: list(form.get("valid_values")),
      invalid_values: list(form.get("invalid_values")), not_found_values: list(form.get("not_found_values")) };
    try { const token = await csrf(); const id = editing?.id; const body = await request(id ? `/repositories/${id}` : "/repositories", { method: id ? "PUT" : "POST", headers: { "Content-Type": "application/json", "X-CSRF-Token": token }, body: JSON.stringify(payload) }); setData(body.data); setEditing(null); notify(`Repositorio ${id ? "actualizado" : "creado"} correctamente.`); }
    catch (reason) { notify(userMessage(reason, "No fue posible guardar el repositorio.")); } finally { setBusy(false); }
  }
  async function rotateCredential(event: FormEvent<HTMLFormElement>) {
    event.preventDefault(); if (!credential) return; setBusy(true); const formElement = event.currentTarget; const form = new FormData(formElement);
    try { const token = await csrf(); const body = await request(`/repositories/${credential.id}/credentials`, { method: "POST", headers: { "Content-Type": "application/json", "X-CSRF-Token": token }, body: JSON.stringify({ secreto: form.get("secreto"), identificador_publico: form.get("identificador_publico") || null, motivo: form.get("motivo") }) }); formElement.reset(); setData(body.data); setCredential(null); notify("Credencial cifrada y rotada correctamente."); }
    catch (reason) { notify(userMessage(reason, "No fue posible rotar la credencial.")); } finally { setBusy(false); }
  }
  async function test(event: FormEvent<HTMLFormElement>) {
    event.preventDefault(); if (!testing) return; setBusy(true); const code = new FormData(event.currentTarget).get("codigo");
    try { const token = await csrf(); const body = await request(`/repositories/${testing.id}/test`, { method: "POST", headers: { "Content-Type": "application/json", "X-CSRF-Token": token }, body: JSON.stringify({ codigo: code }) }); notify(`${body.repositorio}: ${text(body.resultado).replaceAll("_", " ")} (${body.duracion_ms} ms).`); setTesting(null); await load(); }
    catch (reason) { notify(userMessage(reason, "No fue posible probar el repositorio.")); } finally { setBusy(false); }
  }
  async function openCheck(uuid: string) { setBusy(true); try { setSelected(await request(`/checks/${uuid}`)); } catch (reason) { notify(userMessage(reason, "No fue posible abrir la consulta.")); } finally { setBusy(false); } }

  const metrics = data?.metricas || {}, repositories = data?.repositorios || [], checks = data?.consultas || [];
  return <div className="verification-admin">
    <section className="panel-card verification-admin-intro"><div><span className="section-kicker">H11 · Motor federado</span><h2>Verificación documental</h2><p>Configura las fuentes, sus contratos JSON y credenciales. Documenta consulta cada repositorio en paralelo, aplica límites de tiempo y conserva evidencia normalizada.</p></div><button className="button button-primary" onClick={() => setEditing({ ...blank })}>Nuevo repositorio</button></section>
    <div className="metrics-grid verification-admin-metrics"><article className="metric-card"><small>consultas 24h</small><strong>{Number(metrics.consultas_24h || 0)}</strong></article><article className="metric-card"><small>verificadas 24h</small><strong>{Number(metrics.verificadas_24h || 0)}</strong></article><article className="metric-card"><small>indeterminadas 24h</small><strong>{Number(metrics.indeterminadas_24h || 0)}</strong></article><article className="metric-card"><small>promedio ms</small><strong>{Number(metrics.duracion_promedio_ms || 0)}</strong></article></div>
    <section className="panel-card"><div className="verification-admin-heading"><div><h2>Repositorios</h2><p>Prioridad menor significa consulta preferente. Los secretos nunca vuelven al navegador.</p></div><button className="table-action" onClick={() => void load()} disabled={busy}>Actualizar</button></div>
      <div className="verification-repository-list">{repositories.map((row) => <article key={Number(row.id)}><div className={`verification-health state-${text(row.estado_circuito).toLowerCase()}`}/><div><span>{text(row.codigo)} · prioridad {text(row.prioridad)}</span><h3>{text(row.nombre)}</h3><p>{text(row.descripcion) || text(row.endpoint_base) || "Repositorio interno"}</p><small>{text(row.tipo_conector).replaceAll("_", " ")} · timeout {text(row.timeout_ms)} ms · {Boolean(row.tiene_credencial) ? `credencial ${text(row.fingerprint).slice(0, 12)}…` : row.auth_tipo === "NINGUNA" ? "sin autenticación" : "credencial pendiente"}</small></div><div className="verification-repository-state"><b>{Boolean(row.activo) ? text(row.estado_circuito) : "INACTIVO"}</b><small>{row.ultima_prueba_en ? `Prueba ${dateTimeCL(row.ultima_prueba_en)}` : "Sin prueba registrada"}</small></div><div className="verification-repository-actions"><button onClick={() => setEditing(row)}>Editar</button>{row.tipo_conector !== "INTERNO_DOCUMENTA" && <button onClick={() => setCredential(row)}>Credencial</button>}<button onClick={() => setTesting(row)}>Probar</button></div></article>)}</div>
    </section>
    <section className="panel-card"><div className="verification-admin-heading"><div><h2>Monitoreo de consultas</h2><p>Códigos enmascarados, resultados por fuente y tiempos de respuesta.</p></div></div><div className="panel-table-wrap"><table><thead><tr><th>Fecha</th><th>Código</th><th>Estado</th><th>Fuentes</th><th>Duración</th><th/></tr></thead><tbody>{checks.map((row) => <tr key={text(row.uuid)}><td>{dateTimeCL(row.iniciada_en)}</td><td><code>{text(row.codigo_mascara)}</code></td><td><b>{text(row.estado).replaceAll("_", " ")}</b></td><td>{text(row.repositorios_exitosos)}/{text(row.repositorios_consultados)}</td><td>{text(row.duracion_ms)} ms</td><td><button className="table-action" onClick={() => void openCheck(text(row.uuid))}>Detalle</button></td></tr>)}</tbody></table></div>{!checks.length && <div className="panel-empty">Aún no hay consultas de verificación.</div>}</section>
    {editing && <Modal title={editing.id ? "Editar repositorio" : "Nuevo repositorio"} close={() => setEditing(null)}><RepositoryForm value={editing} save={saveRepository} busy={busy}/></Modal>}
    {credential && <Modal title={`Rotar credencial · ${text(credential.nombre)}`} close={() => setCredential(null)}><form className="verification-admin-form" onSubmit={rotateCredential}><label>Identificador público<input name="identificador_publico" maxLength={255}/></label><label>Secreto nuevo<input name="secreto" type="password" minLength={8} required autoComplete="new-password"/></label><label className="wide">Motivo de rotación<textarea name="motivo" minLength={5} required defaultValue="Configuración inicial del repositorio"/></label><p className="wide verification-secret-note">El secreto se cifra con AES-256-GCM. Después de guardar sólo se mostrará su huella SHA-256.</p><button className="button button-primary" disabled={busy}>Cifrar y rotar</button></form></Modal>}
    {testing && <Modal title={`Probar · ${text(testing.nombre)}`} close={() => setTesting(null)}><form className="verification-admin-form" onSubmit={test}><label className="wide">Código de prueba<input name="codigo" minLength={6} maxLength={120} required placeholder="Código conocido o inexistente"/></label><p className="wide verification-secret-note">La prueba usa el contrato y la credencial activa. El resultado queda en el estado operativo del repositorio, pero no crea una consulta pública.</p><button className="button button-primary" disabled={busy}>{busy ? "Consultando…" : "Ejecutar prueba"}</button></form></Modal>}
    {selected && <Modal title="Detalle de consulta" close={() => setSelected(null)}><CheckDetail value={selected}/></Modal>}
  </div>;
}

function Modal({ title, close, children }: { title: string; close: () => void; children: React.ReactNode }) { return <div className="admin-modal-backdrop"><section className="admin-modal admin-modal-large"><header><div><span className="section-kicker">Verificación documental</span><h2>{title}</h2></div><button className="modal-close" onClick={close} aria-label="Cerrar">×</button></header><div className="admin-modal-content">{children}</div></section></div>; }
function RepositoryForm({ value, save, busy }: { value: Row; save: (event: FormEvent<HTMLFormElement>) => void; busy: boolean }) {
  const external = text(value.tipo_conector) !== "INTERNO_DOCUMENTA";
  return <form className="verification-admin-form" onSubmit={save}><label>Código<input name="codigo" defaultValue={text(value.codigo)} pattern="[A-Za-z][A-Za-z0-9_-]*" required/></label><label>Nombre<input name="nombre" defaultValue={text(value.nombre)} required/></label><label className="wide">Descripción<textarea name="descripcion" defaultValue={text(value.descripcion)}/></label><label>Conector<select name="tipo_conector" defaultValue={text(value.tipo_conector)}><option value="HTTP_JSON">HTTP JSON</option><option value="INTERNO_DOCUMENTA">Interno Documenta</option></select></label><label>Prioridad<input name="prioridad" type="number" min="1" max="1000" defaultValue={Number(value.prioridad || 100)} required/></label><label className="wide">Endpoint HTTPS<input name="endpoint_base" type="url" defaultValue={text(value.endpoint_base)} required={external} placeholder="https://repositorio.cl/api/verificar"/></label><label>Método<select name="metodo_http" defaultValue={text(value.metodo_http)}><option>GET</option><option>POST</option></select></label><label>Parámetro del código<input name="codigo_parametro" defaultValue={text(value.codigo_parametro) || "codigo"} required/></label><label>Autenticación<select name="auth_tipo" defaultValue={text(value.auth_tipo)}><option value="NINGUNA">Sin autenticación</option><option value="BEARER">Bearer</option><option value="API_KEY_HEADER">API Key en header</option><option value="BASIC">Basic</option></select></label><label>Header API Key<input name="auth_header" defaultValue={text(value.auth_header)} placeholder="X-API-Key"/></label><label>Timeout (ms)<input name="timeout_ms" type="number" min="500" max="10000" defaultValue={Number(value.timeout_ms || 4000)} required/></label><label>Intentos<input name="max_intentos" type="number" min="1" max="3" defaultValue={Number(value.max_intentos || 1)} required/></label><label>Umbral circuito<input name="umbral_circuito" type="number" min="1" max="20" defaultValue={Number(value.umbral_circuito || 3)} required/></label><label className="verification-checkbox"><input name="activo" type="checkbox" defaultChecked={Boolean(value.activo)}/> Repositorio activo</label><fieldset className="wide"><legend>Mapeo de respuesta JSON</legend><p>Usa rutas separadas por punto. Ejemplo: <code>data.document.status</code>.</p><div className="verification-admin-form"><label>Estado encontrado (boolean)<input name="found_path" defaultValue={text(value.found_path)} placeholder="data.found"/></label><label>Estado del documento<input name="status_path" defaultValue={text(value.status_path)} placeholder="data.status"/></label><label>Código<input name="code_path" defaultValue={text(value.code_path)} placeholder="data.code"/></label><label>Nombre documento<input name="document_name_path" defaultValue={text(value.document_name_path)} placeholder="data.name"/></label><label>Emisor<input name="issuer_path" defaultValue={text(value.issuer_path)} placeholder="data.issuer"/></label><label>Fecha emisión<input name="issued_at_path" defaultValue={text(value.issued_at_path)} placeholder="data.issued_at"/></label><label>Fecha firma<input name="signed_at_path" defaultValue={text(value.signed_at_path)} placeholder="data.signed_at"/></label><label>Estado documental<input name="document_status_path" defaultValue={text(value.document_status_path)} placeholder="data.document_status"/></label><label>Estado firma<input name="signature_status_path" defaultValue={text(value.signature_status_path)} placeholder="data.signature_status"/></label><label>Hash<input name="hash_path" defaultValue={text(value.hash_path)} placeholder="data.sha256"/></label><label>URL oficial<input name="document_url_path" defaultValue={text(value.document_url_path)} placeholder="data.url"/></label><label>Valores válidos<input name="valid_values" defaultValue={(value.valid_values as string[] || blank.valid_values as string[]).join(", ")}/></label><label>Valores inválidos<input name="invalid_values" defaultValue={(value.invalid_values as string[] || blank.invalid_values as string[]).join(", ")}/></label><label>No encontrado<input name="not_found_values" defaultValue={(value.not_found_values as string[] || blank.not_found_values as string[]).join(", ")}/></label></div></fieldset><button className="button button-primary" disabled={busy}>{busy ? "Guardando…" : "Guardar repositorio"}</button></form>;
}
function CheckDetail({ value }: { value: Row }) { const check = value.consulta as Row, attempts = value.intentos as Row[]; return <div className="verification-check-detail"><dl><div><dt>Estado</dt><dd>{text(check.estado)}</dd></div><div><dt>Código</dt><dd>{text(check.codigo_mascara)}</dd></div><div><dt>Duración</dt><dd>{text(check.duracion_ms)} ms</dd></div><div><dt>Fecha</dt><dd>{dateTimeCL(check.iniciada_en)}</dd></div></dl>{attempts.map((row, index) => <article key={index}><header><strong>{text(row.nombre)}</strong><b>{text(row.resultado)}</b></header><p>{row.error_codigo ? `Error: ${text(row.error_codigo)}` : `HTTP ${text(row.http_status) || "interno"} · ${text(row.duracion_ms)} ms`}</p>{Boolean(row.evidencia) && <pre>{JSON.stringify(row.evidencia, null, 2)}</pre>}</article>)}</div>; }
