"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import { AppShell } from "@/components/AppShell";
import { ContextReports } from "@/components/ContextReports";
import {
  addPolicyChild,
  archivePolicy,
  getLookups,
  getPolicy,
  policyDocumentDownloadUrl,
  removePolicyChild,
  removePolicyDocument,
  restorePolicy,
  updatePolicyChild,
  uploadPolicyDocument,
} from "@/lib/api";
import { useCan } from "@/lib/abilities";
import { ChildCollection, type ChildConfig } from "@/components/ChildCollection";
import {
  expiryPhrase,
  formatDate,
  formatMoney,
  policyStatusLabel,
  premiumHeadline,
  SIN_NOMBRE,
} from "@/lib/labels";
import type { AdjusterRow, Installment, PolicyDetail } from "@/lib/types";

export default function PolizaDetailPage({
  params,
}: {
  params: { id: string };
}) {
  // Next 14 passes `params` as a plain object here — no `use()` unwrapping.
  const { id } = params;
  return (
    <AppShell>
      <Detail id={id} />
    </AppShell>
  );
}

function Detail({ id }: { id: string }) {
  const [data, setData] = useState<PolicyDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let alive = true;
    setLoading(true);
    setError(null);
    getPolicy(id)
      .then((d) => {
        if (alive) {
          setData(d);
          setLoading(false);
        }
      })
      .catch((e) => {
        if (alive) {
          setError(
            e?.status === 404
              ? "No encontramos esta póliza."
              : e?.message ?? "No se pudo cargar la póliza.",
          );
          setLoading(false);
        }
      });
    return () => {
      alive = false;
    };
  }, [id]);

  if (loading) return <DetailSkeleton />;

  if (error)
    return (
      <>
        <BackLink />
        <div className="state-error" role="alert">
          {error}
        </div>
      </>
    );

  if (!data) return null;

  const reload = () => getPolicy(id).then(setData).catch(() => {});

  return (
    <div className="rise">
      <div className="detail-actionbar">
        <BackLink />
        <ContextReports
          entries={[
            {
              slug: "edo-cuenta-datos",
              label: "Estado de cuenta del cliente",
              params: { customerId: data.customer.id },
            },
          ]}
        />
        <PolicyActions data={data} onChange={reload} />
      </div>
      <Hero data={data} />
      <ClienteSection data={data} />
      <CondicionesSection data={data} />
      {data.installments.length > 0 && <PagosSection data={data} />}
      {data.vehicles.length > 0 && <VehiculosSection data={data} />}
      {(data.insuredDrivers.length > 0 || data.beneficiaries.length > 0) && (
        <PersonasSection data={data} />
      )}
      {data.claims.length > 0 && <SiniestrosSection data={data} />}
      <CoberturasSection data={data} />
      <DocumentosSection data={data} onChange={reload} />
      <ChildrenEditor data={data} onChange={reload} />
    </div>
  );
}

/** Edit / archive controls for the policy header. */
function PolicyActions({
  data,
  onChange,
}: {
  data: PolicyDetail;
  onChange: () => void;
}) {
  const canEdit = useCan("policy:update");
  const canDelete = useCan("policy:delete");
  const [busy, setBusy] = useState(false);
  const archived = data.archivedAt != null;

  async function toggle() {
    const verb = archived ? "restaurar" : "archivar";
    if (!window.confirm(`¿Seguro que desea ${verb} esta póliza?`)) return;
    setBusy(true);
    try {
      if (archived) await restorePolicy(data.id);
      else await archivePolicy(data.id);
      onChange();
    } catch (e) {
      window.alert((e as Error)?.message ?? "No se pudo completar la acción.");
    } finally {
      setBusy(false);
    }
  }

  if (!canEdit && !canDelete) return null;
  return (
    <div className="row-actions">
      {archived && <span className="badge badge-negative">Archivada</span>}
      {canEdit && (
        <Link href={`/polizas/${data.id}/editar`} className="btn btn-outline">
          Editar
        </Link>
      )}
      {canDelete && (
        <button type="button" className="btn btn-ghost" onClick={toggle} disabled={busy}>
          {archived ? "Restaurar" : "Archivar"}
        </button>
      )}
    </div>
  );
}

/** Editable child collections — only shown to users who can edit the policy. */
function ChildrenEditor({
  data,
  onChange,
}: {
  data: PolicyDetail;
  onChange: () => void;
}) {
  const canEdit = useCan("policy:update");
  const [adjusters, setAdjusters] = useState<AdjusterRow[]>([]);

  useEffect(() => {
    if (canEdit) getLookups().then((l) => setAdjusters(l.adjusters)).catch(() => {});
  }, [canEdit]);

  if (!canEdit) return null;

  const INSTALLMENTS: ChildConfig = {
    apiKind: "installments",
    title: "Pagos",
    fields: [
      { key: "sequence", label: "Sec.", type: "number" },
      { key: "amount", label: "Monto", type: "number" },
      { key: "currency", label: "Moneda", type: "select",
        options: [{ value: "MXN", label: "MXN" }, { value: "USD", label: "USD" }] },
      { key: "dueDate", label: "Vence", type: "date" },
      { key: "paidDate", label: "Pagado", type: "date" },
      { key: "checkNumber", label: "Cheque" },
      { key: "isCash", label: "Efectivo", type: "checkbox" },
    ],
  };
  const VEHICLES: ChildConfig = {
    apiKind: "vehicles",
    title: "Vehículos",
    fields: [
      { key: "make", label: "Marca" },
      { key: "model", label: "Modelo" },
      { key: "modelYear", label: "Año" },
      { key: "licensePlate", label: "Placa" },
      { key: "vinNumber", label: "VIN" },
      { key: "stateCode", label: "Estado" },
    ],
  };
  const DRIVERS: ChildConfig = {
    apiKind: "drivers",
    title: "Conductores",
    fields: [
      { key: "fullName", label: "Nombre" },
      { key: "birthDate", label: "Nacimiento", type: "date" },
      { key: "sex", label: "Sexo" },
      { key: "occupation", label: "Ocupación" },
      { key: "licenseNumber", label: "Licencia" },
      { key: "licenseState", label: "Estado" },
    ],
  };
  const BENEFICIARIES: ChildConfig = {
    apiKind: "beneficiaries",
    title: "Beneficiarios",
    fields: [
      { key: "name", label: "Nombre" },
      { key: "phone", label: "Teléfono" },
      { key: "email", label: "Correo" },
      { key: "address", label: "Dirección" },
    ],
  };
  const CLAIMS: ChildConfig = {
    apiKind: "claims",
    title: "Siniestros",
    fields: [
      { key: "claimType", label: "Tipo" },
      { key: "incidentDate", label: "Fecha", type: "date" },
      { key: "description", label: "Descripción" },
      { key: "adjusterId", label: "Ajustador", type: "select",
        options: adjusters.map((a) => ({ value: a.id, label: a.name ?? a.company ?? a.id })) },
      { key: "claimedAmount", label: "Reclamado", type: "number" },
      { key: "settledAmount", label: "Pagado", type: "number" },
      { key: "resolved", label: "Resuelto", type: "checkbox" },
    ],
  };

  const bind = (cfg: ChildConfig, rows: Record<string, unknown>[]) => (
    <ChildCollection
      config={cfg}
      rows={rows}
      canEdit={canEdit}
      onAdd={async (p) => { await addPolicyChild(data.id, cfg.apiKind, p); onChange(); }}
      onSave={async (cid, p) => { await updatePolicyChild(data.id, cfg.apiKind, cid, p); onChange(); }}
      onRemove={async (cid) => { await removePolicyChild(data.id, cfg.apiKind, cid); onChange(); }}
    />
  );

  return (
    <section className="section">
      <div className="section-head">
        <span className="section-rule cuenta" aria-hidden />
        <h2 className="section-title">Administrar detalles</h2>
      </div>
      {bind(INSTALLMENTS, data.installments as unknown as Record<string, unknown>[])}
      {bind(VEHICLES, data.vehicles as unknown as Record<string, unknown>[])}
      {bind(DRIVERS, data.insuredDrivers as unknown as Record<string, unknown>[])}
      {bind(BENEFICIARIES, data.beneficiaries as unknown as Record<string, unknown>[])}
      {bind(CLAIMS, data.claims as unknown as Record<string, unknown>[])}
    </section>
  );
}

function BackLink() {
  return (
    <Link href="/polizas" className="back-link">
      ← Volver a Pólizas
    </Link>
  );
}

/* ------------------------------------------------------------------ Hero */
function Hero({ data }: { data: PolicyDetail }) {
  const premium = premiumHeadline(data);
  const phrase = expiryPhrase(data.daysToExpiry);
  const provenance = [data.legacySourceTable, data.legacyId]
    .filter(Boolean)
    .join(" #");

  const facts: { label: string; value: string }[] = [
    { label: "Vigencia desde", value: formatDate(data.policyFrom) },
    { label: "Vigencia hasta", value: formatDate(data.policyTo) },
    { label: premium.label, value: formatMoney(premium.value, data.currency) },
    { label: "Moneda", value: data.currency ?? "—" },
    { label: "Agente", value: data.agentName || "—" },
  ];

  return (
    <div className="detail-hero">
      <div className="hero-top">
        <div>
          <h1 className="hero-name mono">{data.policyNumber || "—"}</h1>
          <div className="hero-provenance">
            {[data.policyType?.name, data.insuranceProvider?.name]
              .filter(Boolean)
              .join(" · ") || "Sin ramo ni aseguradora registrados"}
          </div>
          {provenance && (
            <div className="hero-provenance">Origen: {provenance}</div>
          )}
        </div>
        <div className="hero-badges">
          <span className={`badge status-${data.status}`}>
            {policyStatusLabel(data.status)}
            {phrase && data.status !== "expired" ? ` · ${phrase}` : ""}
          </span>
          <span
            className={`badge ${
              data.liquidated ? "badge-positive" : "badge-negative"
            }`}
          >
            {data.liquidated ? "Liquidada" : "Sin liquidar"}
          </span>
          {data.endorsement && (
            <span className="badge badge-on-dark">Endoso</span>
          )}
        </div>
      </div>
      <div className="hero-facts">
        {facts.map((f) => (
          <div key={f.label}>
            <div className="hero-fact-label">{f.label}</div>
            <div className="hero-fact-value">{f.value}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* -------------------------------------------------------------- Cliente */
function ClienteSection({ data }: { data: PolicyDetail }) {
  const c = data.customer;
  const location = [c.city?.replace(/,\s*$/, ""), c.state]
    .filter(Boolean)
    .join(", ");

  return (
    <section className="section">
      <SectionHead rule="datos" title="Cliente" />
      <div className="card">
        <Link href={`/clientes/${c.id}`} className="owner-link">
          <div>
            <div
              className={`owner-name${
                c.name === SIN_NOMBRE ? " cust-name-missing" : ""
              }`}
            >
              {c.name}
            </div>
            <div className="cust-sub">
              {location && <span>{location}</span>}
              {location && (c.phone || c.email) && (
                <span className="sep">·</span>
              )}
              {(c.phone || c.mobile) && <span>{c.phone || c.mobile}</span>}
              {c.email && (
                <>
                  <span className="sep">·</span>
                  <span>{c.email}</span>
                </>
              )}
            </div>
          </div>
          <span className="owner-cta">Ver expediente →</span>
        </Link>

        {data.properties.length > 0 && (
          <div className="linked-props">
            <div className="kv-label">Propiedades cubiertas</div>
            {data.properties.map((p) => (
              <Link
                key={p.id}
                href={`/servicios/${p.id}`}
                className="linked-prop link"
              >
                {[p.addressLine1, p.addressLine2].filter(Boolean).join(", ") ||
                  "Propiedad"}
                {p.zone && <span className="muted"> · Zona {p.zone}</span>}
              </Link>
            ))}
          </div>
        )}
      </div>
    </section>
  );
}

/* ---------------------------------------------------------- Condiciones */
function CondicionesSection({ data }: { data: PolicyDetail }) {
  const cur = data.currency;
  return (
    <section className="section">
      <SectionHead rule="seguros" title="Condiciones y primas" />
      <div className="card">
        <div className="kv-grid">
          <KV label="Fecha de emisión" value={formatDate(data.policyDate)} />
          <KV
            label="Periodo de cobertura"
            value={
              data.coveragePeriodDays ? `${data.coveragePeriodDays} días` : null
            }
          />
          <KV label="Prima neta" value={formatMoney(data.netPremium, cur)} />
          <KV label="Derecho de póliza" value={formatMoney(data.policyFee, cur)} />
          <KV label="Comisión" value={formatMoney(data.commission, cur)} />
          <KV label="Honorarios" value={formatMoney(data.brokerFee, cur)} />
          {/* The legacy `total` is 0 or null on all but 2 of 2378 policies —
              only show it when it actually carries a figure. */}
          {data.total != null && Number(data.total) > 0 && (
            <KV label="Total" value={formatMoney(data.total, cur)} />
          )}
          <KV
            label="Liquidación"
            value={
              data.liquidated
                ? [
                    data.liquidationNumber
                      ? `No. ${data.liquidationNumber}`
                      : null,
                    data.liquidationDate
                      ? formatDate(data.liquidationDate)
                      : null,
                  ]
                    .filter(Boolean)
                    .join(" · ") || "Liquidada"
                : "Pendiente"
            }
          />
          {data.observations && (
            <div className="kv-block">
              <div className="kv-label">Observaciones</div>
              <div className="kv-value">{data.observations}</div>
            </div>
          )}
          {data.notes && (
            <div className="kv-block">
              <div className="kv-label">Notas</div>
              <div className="kv-value">{data.notes}</div>
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

/* --------------------------------------------------------------- Pagos */
function PagosSection({ data }: { data: PolicyDetail }) {
  const paid = data.installments.filter((i) => i.paidDate).length;
  return (
    <section className="section">
      <SectionHead
        rule="cuenta"
        title="Pagos"
        count={data.installments.length}
        countSuffix={`· ${paid} pagados`}
      />
      <div className="card">
        <div className="subpanel" style={{ margin: 16 }}>
          {data.installments.map((inst) => (
            <InstallmentRow key={inst.id} inst={inst} />
          ))}
        </div>
      </div>
    </section>
  );
}

function InstallmentRow({ inst }: { inst: Installment }) {
  const method = inst.isCash
    ? "Efectivo"
    : inst.checkNumber
    ? `Ref. ${inst.checkNumber}`
    : null;
  return (
    <div className="pay-row">
      <span style={{ display: "flex", alignItems: "center", gap: 9 }}>
        <span className="pay-seq">{inst.sequence}</span>
        <span>
          {inst.paidDate ? formatDate(inst.paidDate) : "Sin pagar"}
          {inst.dueDate && !inst.paidDate && (
            <span className="muted" style={{ fontSize: 11 }}>
              {" "}
              · vence {formatDate(inst.dueDate)}
            </span>
          )}
          {method && (
            <span className="muted" style={{ fontSize: 11 }}>
              {" "}
              · {method}
            </span>
          )}
        </span>
      </span>
      <span className="mono" style={{ fontWeight: 600 }}>
        {formatMoney(inst.amount, inst.currency)}
      </span>
    </div>
  );
}

/* ----------------------------------------------------------- Vehículos */
function VehiculosSection({ data }: { data: PolicyDetail }) {
  return (
    <section className="section">
      <SectionHead
        rule="servicios"
        title="Vehículos asegurados"
        count={data.vehicles.length}
      />
      <div className="card">
        <div className="veh-grid">
          {data.vehicles.map((v) => (
            <div className="veh-card" key={v.id}>
              <div className="veh-title">
                {[v.make, v.model, v.modelYear].filter(Boolean).join(" ") ||
                  "Vehículo"}
              </div>
              <div className="veh-facts">
                {v.bodyType && <span>{v.bodyType}</span>}
                {v.licensePlate && (
                  <span>
                    Placa: <span className="mono">{v.licensePlate}</span>
                  </span>
                )}
                {v.vinNumber && (
                  <span>
                    Serie: <span className="mono">{v.vinNumber}</span>
                  </span>
                )}
                {v.engineNumber && (
                  <span>
                    Motor: <span className="mono">{v.engineNumber}</span>
                  </span>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------------------- Asegurados y beneficiarios */
function PersonasSection({ data }: { data: PolicyDetail }) {
  return (
    <section className="section">
      <SectionHead rule="datos" title="Asegurados y beneficiarios" />
      <div className="card">
        <div className="policy-body">
          {data.insuredDrivers.length > 0 && (
            <div className="subpanel">
              <div className="subpanel-title">
                <span>Asegurados</span>
                <span>{data.insuredDrivers.length}</span>
              </div>
              <div className="mini-list">
                {data.insuredDrivers.map((d) => (
                  <div key={d.id}>
                    {d.fullName || "—"}
                    {d.licenseNumber && (
                      <div className="mini-sub mono">Lic. {d.licenseNumber}</div>
                    )}
                  </div>
                ))}
              </div>
            </div>
          )}
          {data.beneficiaries.length > 0 && (
            <div className="subpanel">
              <div className="subpanel-title">
                <span>Beneficiarios</span>
                <span>{data.beneficiaries.length}</span>
              </div>
              <div className="mini-list">
                {data.beneficiaries.map((b) => (
                  <div key={b.id}>
                    {b.name || "—"}
                    {(b.phone || b.email) && (
                      <div className="mini-sub">
                        {[b.phone, b.email].filter(Boolean).join(" · ")}
                      </div>
                    )}
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

/* --------------------------------------------------------- Siniestros */
function SiniestrosSection({ data }: { data: PolicyDetail }) {
  return (
    <section className="section">
      <SectionHead rule="cuenta" title="Siniestros" count={data.claims.length} />
      <div className="card">
        {data.claims.map((c) => (
          <div className="prop-card" key={c.id}>
            <div className="prop-addr">{c.claimType || "Siniestro"}</div>
            <div className="prop-meta">
              {c.incidentDate && (
                <span>Ocurrido: {formatDate(c.incidentDate)}</span>
              )}
              {c.reportedDate && (
                <span>Reportado: {formatDate(c.reportedDate)}</span>
              )}
              {c.adjuster?.name && <span>Ajustador: {c.adjuster.name}</span>}
            </div>
            <div className="kv-grid" style={{ marginTop: 12 }}>
              <KV
                label="Monto reclamado"
                value={formatMoney(c.claimedAmount, data.currency)}
              />
              <KV
                label="Monto liquidado"
                value={formatMoney(c.settledAmount, data.currency)}
              />
              <KV label="Fecha de finiquito" value={formatDate(c.settlementDate)} />
              {c.description && (
                <div className="kv-block">
                  <div className="kv-label">Descripción</div>
                  <div className="kv-value">{c.description}</div>
                </div>
              )}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

/* -------------------------------------------------------- Coberturas */
/** The legacy tables carry per-line coverage columns the target schema does
 *  not model; the migration preserved them verbatim in `coveragesJson`. */
function CoberturasSection({ data }: { data: PolicyDetail }) {
  const entries = Object.entries(data.coveragesJson ?? {}).filter(
    ([, v]) => v !== null && v !== "" && v !== 0,
  );
  if (entries.length === 0) return null;

  return (
    <section className="section">
      <SectionHead rule="seguros" title="Coberturas" count={entries.length} />
      <div className="card">
        <div className="kv-grid">
          {entries.map(([k, v]) => (
            <div key={k}>
              <div className="kv-label">{k}</div>
              <div className="kv-value">{String(v)}</div>
            </div>
          ))}
        </div>
        <div className="section-note" style={{ padding: "0 22px 18px" }}>
          Campos de cobertura conservados tal cual desde el sistema anterior.
        </div>
      </div>
    </section>
  );
}

/* -------------------------------------------------------- Documentos */
function DocumentosSection({
  data,
  onChange,
}: {
  data: PolicyDetail;
  onChange: () => void;
}) {
  const canEdit = useCan("policy:update");
  const [file, setFile] = useState<File | null>(null);
  const [type, setType] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function upload() {
    if (!file) return;
    setBusy(true);
    setError(null);
    try {
      await uploadPolicyDocument(data.id, file, type.trim() || undefined);
      setFile(null);
      setType("");
      onChange();
    } catch (e) {
      setError((e as Error)?.message ?? "No se pudo subir el archivo.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <section className="section">
      <SectionHead rule="docs" title="Documentos" count={data.documents.length} />
      <div className="card">
        {data.documents.length === 0 ? (
          <div className="empty-inline">
            No hay documentos registrados para esta póliza.
          </div>
        ) : (
          <div className="doc-list">
            {data.documents.map((d, i) => (
              <div className="doc-item" key={d.id ?? i}>
                <span className="doc-icon" aria-hidden>
                  ▤
                </span>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div className="doc-type">{d.documentType || "Documento"}</div>
                  <div className="doc-key">{d.storageKey || "—"}</div>
                </div>
                {d.id && (
                  <a
                    className="btn btn-ghost"
                    href={policyDocumentDownloadUrl(data.id, d.id)}
                  >
                    Descargar
                  </a>
                )}
                {canEdit && d.id && (
                  <button
                    type="button"
                    className="btn btn-ghost"
                    onClick={async () => {
                      if (!window.confirm("¿Eliminar este documento?")) return;
                      try {
                        await removePolicyDocument(data.id, d.id!);
                        onChange();
                      } catch (e) {
                        window.alert((e as Error)?.message ?? "No se pudo eliminar.");
                      }
                    }}
                  >
                    Eliminar
                  </button>
                )}
              </div>
            ))}
          </div>
        )}
        {canEdit && (
          <div style={{ padding: "0 22px 18px" }}>
            {error && (
              <div className="state-box state-error" style={{ marginBottom: 12 }}>
                {error}
              </div>
            )}
            <div className="inline-form">
              <input
                className="input"
                placeholder="Tipo (ej. CARATULA)"
                value={type}
                onChange={(e) => setType(e.target.value)}
              />
              <input
                type="file"
                className="input"
                onChange={(e) => setFile(e.target.files?.[0] ?? null)}
              />
              <button
                type="button"
                className="btn btn-primary"
                disabled={!file || busy}
                onClick={upload}
              >
                {busy ? "Subiendo…" : "Subir"}
              </button>
            </div>
          </div>
        )}
      </div>
    </section>
  );
}

/* ------------------------------------------------------------ helpers */
function KV({
  label,
  value,
}: {
  label: string;
  value: string | null | undefined;
}) {
  return (
    <div>
      <div className="kv-label">{label}</div>
      <div className="kv-value">{value || "—"}</div>
    </div>
  );
}

function SectionHead({
  rule,
  title,
  count,
  countSuffix,
}: {
  rule: string;
  title: string;
  count?: number;
  countSuffix?: string;
}) {
  return (
    <div className="section-head">
      <span className={`section-rule ${rule}`} aria-hidden />
      <h2 className="section-title">{title}</h2>
      {count != null && (
        <span className="section-count">
          {count} {countSuffix ?? ""}
        </span>
      )}
    </div>
  );
}

function DetailSkeleton() {
  return (
    <div>
      <div
        className="skeleton"
        style={{ height: 16, width: 140, marginBottom: 18 }}
      />
      <div className="skeleton" style={{ height: 180, borderRadius: 16 }} />
      <div
        className="skeleton"
        style={{ height: 200, borderRadius: 16, marginTop: 34 }}
      />
      <div
        className="skeleton"
        style={{ height: 260, borderRadius: 16, marginTop: 34 }}
      />
    </div>
  );
}
