"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import { AppShell } from "@/components/AppShell";
import { ContextReports } from "@/components/ContextReports";
import {
  archiveCustomer,
  getCustomer,
  policyDocumentDownloadUrl,
  propertyDocumentDownloadUrl,
  restoreCustomer,
} from "@/lib/api";
import { useCan } from "@/lib/abilities";
import {
  domainLabel,
  formatDate,
  formatMoney,
  premiumHeadline,
  serviceKindGlyph,
  serviceKindLabel,
  SIN_NOMBRE,
  sourceSystemLabel,
} from "@/lib/labels";
import type {
  CustomerDetail,
  Installment,
  Policy,
  Property,
  Transaction,
  TransactionSummaryRow,
} from "@/lib/types";

export default function ClienteDetailPage({
  params,
}: {
  params: { id: string };
}) {
  const { id } = params;
  return (
    <AppShell>
      <Detail id={id} />
    </AppShell>
  );
}

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

  useEffect(() => {
    let alive = true;
    setLoading(true);
    setError(null);
    getCustomer(id)
      .then((d) => {
        if (alive) {
          setData(d);
          setLoading(false);
        }
      })
      .catch((e) => {
        if (alive) {
          setError(
            e?.status === 404
              ? "No encontramos este cliente."
              : e?.message ?? "No se pudo cargar el cliente.",
          );
          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 hasUtilities = data.properties.length > 0;
  const hasInsurance = data.policies.length > 0;

  return (
    <div className="rise">
      <div className="detail-actionbar">
        <BackLink />
        <ContextReports
          entries={[
            {
              slug: "edo-cuenta-datos",
              label: "Estado de cuenta (reporte)",
              params: { customerId: data.id },
            },
          ]}
        />
        <CustomerActions
          customer={data}
          onChange={() => getCustomer(id).then(setData).catch(() => {})}
        />
      </div>
      <Hero data={data} hasUtilities={hasUtilities} hasInsurance={hasInsurance} />

      <DatosSection data={data} />
      <PropiedadesSection
        properties={data.properties}
        customerId={data.id}
        customerName={data.name}
      />
      <PolizasSection
        policies={data.policies}
        customerId={data.id}
        customerName={data.name}
      />
      <EstadoCuentaSection
        customerId={data.id}
        summary={data.transactionSummary}
        transactions={data.transactions}
      />
      <DocumentosSection data={data} />
    </div>
  );
}

function BackLink() {
  return (
    <Link href="/clientes" className="back-link">
      ← Volver a Clientes
    </Link>
  );
}

/** Edit / archive controls, each gated by the matching ability. */
function CustomerActions({
  customer,
  onChange,
}: {
  customer: CustomerDetail;
  onChange: () => void;
}) {
  const canEdit = useCan("customer:update");
  const canDelete = useCan("customer:delete");
  const [busy, setBusy] = useState(false);
  const archived = customer.archivedAt != null;

  async function toggleArchive() {
    const verb = archived ? "restaurar" : "archivar";
    if (!window.confirm(`¿Seguro que desea ${verb} este cliente?`)) return;
    setBusy(true);
    try {
      if (archived) await restoreCustomer(customer.id);
      else await archiveCustomer(customer.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">Archivado</span>}
      {canEdit && (
        <Link href={`/clientes/${customer.id}/editar`} className="btn btn-outline">
          Editar
        </Link>
      )}
      {canDelete && (
        <button
          type="button"
          className="btn btn-ghost"
          onClick={toggleArchive}
          disabled={busy}
        >
          {archived ? "Restaurar" : "Archivar"}
        </button>
      )}
    </div>
  );
}

/* ------------------------------------------------------------------ Hero */
function Hero({
  data,
  hasUtilities,
  hasInsurance,
}: {
  data: CustomerDetail;
  hasUtilities: boolean;
  hasInsurance: boolean;
}) {
  const provenance = data.legacyRefs
    .map((r) => `${sourceSystemLabel(r.sourceSystem)} #${r.legacyId}`)
    .join(" · ");

  const facts: { label: string; value: string }[] = [
    { label: "Cliente desde", value: formatDate(data.customerSince) },
    {
      label: "Cuota",
      value:
        data.feeAmount != null && data.feeAmount !== ""
          ? formatMoney(data.feeAmount, data.preferredCurrency)
          : "—",
    },
    { label: "Propiedades", value: String(data.properties.length) },
    { label: "Pólizas", value: String(data.policies.length) },
    { label: "Moneda", value: data.preferredCurrency ?? "—" },
  ];

  return (
    <div className="detail-hero">
      <div className="hero-top">
        <div>
          <h1
            className={`hero-name${
              data.name === SIN_NOMBRE ? " hero-name-missing" : ""
            }`}
          >
            {data.name}
          </h1>
          {data.nameSource && (
            <div className="hero-provenance">
              Nombre recuperado de {data.nameSource} — el registro original no
              tenía nombre.
            </div>
          )}
          {provenance && (
            <div className="hero-provenance">Origen: {provenance}</div>
          )}
        </div>
        <div className="hero-badges">
          {hasUtilities && (
            <span className="badge badge-servicios">
              <span className="dot" /> Servicios
            </span>
          )}
          {hasInsurance && (
            <span className="badge badge-seguros">
              <span className="dot" /> Seguros
            </span>
          )}
          <span
            className={`badge ${
              data.status ? "badge-on-dark" : "badge-negative"
            }`}
          >
            {data.status ? "Activo" : "Inactivo"}
          </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>
  );
}

/* ------------------------------------------------------- Datos del cliente */
function DatosSection({ data }: { data: CustomerDetail }) {
  const mxAddress = [data.addressLine1, data.addressLine2]
    .filter(Boolean)
    .join(", ");
  const cityLine = [
    data.city?.replace(/,\s*$/, ""),
    data.state,
    data.zipCode,
    data.country,
  ]
    .filter(Boolean)
    .join(", ");

  const idLine =
    data.identificationNumber || data.identificationType
      ? [
          data.identificationType,
          data.identificationNumber,
          data.identificationExpiration
            ? `vence ${formatDate(data.identificationExpiration)}`
            : null,
        ]
          .filter(Boolean)
          .join(" · ")
      : null;

  return (
    <section className="section">
      <SectionHead rule="datos" title="Datos del cliente" />
      <div className="card">
        <div className="kv-grid">
          <KV label="Teléfono" value={data.phone} mono />
          <KV label="Móvil" value={data.mobile} mono />
          <KV label="Fax" value={data.fax} mono />
          <KV label="Correo electrónico" value={data.email} />
          <KV label="Documento de identidad" value={idLine} />
          <KV
            label="Estado"
            value={data.status ? "Activo" : "Inactivo"}
          />
          {(mxAddress || cityLine) && (
            <div className="kv-block">
              <div className="kv-label">Domicilio</div>
              <div className="kv-value">
                {mxAddress && <div>{mxAddress}</div>}
                {cityLine && <div>{cityLine}</div>}
                {!mxAddress && !cityLine && "—"}
              </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>
  );
}

function KV({
  label,
  value,
  mono,
}: {
  label: string;
  value: string | null | undefined;
  mono?: boolean;
}) {
  return (
    <div>
      <div className="kv-label">{label}</div>
      <div className={`kv-value${mono && value ? " mono" : ""}`}>
        {value || "—"}
      </div>
    </div>
  );
}

/* ----------------------------------------------- Propiedades y servicios */
function PropiedadesSection({
  properties,
  customerId,
  customerName,
}: {
  properties: Property[];
  customerId: string;
  customerName: string;
}) {
  const canCreate = useCan("property:create");
  return (
    <section className="section">
      <div className="detail-actionbar">
        <SectionHead
          rule="servicios"
          title="Propiedades y servicios"
          count={properties.length}
        />
        {canCreate && (
          <Link
            href={`/servicios/nuevo?customerId=${customerId}&customerName=${encodeURIComponent(customerName)}`}
            className="btn btn-outline"
          >
            + Nueva propiedad
          </Link>
        )}
      </div>
      <div className="card">
        {properties.length === 0 ? (
          <div className="empty-inline">
            Este cliente no tiene propiedades registradas.
          </div>
        ) : (
          properties.map((p) => <PropertyCard key={p.id} p={p} />)
        )}
      </div>
    </section>
  );
}

function PropertyCard({ p }: { p: Property }) {
  const addr = [p.addressLine1, p.addressLine2].filter(Boolean).join(", ");
  const phones = [p.phone1, p.phone2, p.phone3].filter(Boolean);

  return (
    <div className="prop-card">
      <div className="prop-addr">
        <Link href={`/servicios/${p.id}`} className="policy-num-link">
          {addr || "Propiedad"}
        </Link>
      </div>
      <div className="prop-meta">
        {p.zone && <span>Zona: {p.zone}</span>}
        {phones.length > 0 && (
          <span className="mono">{phones.join(" · ")}</span>
        )}
      </div>

      {p.services.length > 0 && (
        <div className="svc-grid">
          {p.services.map((s) => (
            <div
              key={s.id}
              className={`svc-item${s.active ? "" : " inactive"}`}
            >
              <div className="svc-head">
                <span className="svc-kind">
                  <span className="svc-glyph" aria-hidden>
                    {serviceKindGlyph(s.kind)}
                  </span>
                  {serviceKindLabel(s.kind)}
                </span>
                {!s.active && (
                  <span className="badge badge-neutral">Inactivo</span>
                )}
              </div>
              <div className="svc-detail">
                {s.accountNumber && (
                  <span>
                    Cuenta: <span className="mono">{s.accountNumber}</span>
                  </span>
                )}
                {s.meterNumber && (
                  <span>
                    Medidor: <span className="mono">{s.meterNumber}</span>
                  </span>
                )}
                {s.route && (
                  <span>
                    Ruta: <span className="mono">{s.route}</span>
                  </span>
                )}
                {s.dueDay && <span>Día de pago: {s.dueDay}</span>}
                {s.notes && <span>{s.notes}</span>}
              </div>
            </div>
          ))}
        </div>
      )}

      {p.trustAccount && (
        <div className="trust-box">
          <div className="trust-title">Fideicomiso</div>
          <div className="trust-facts">
            {p.trustAccount.bankName && (
              <span>
                <strong>Banco:</strong> {p.trustAccount.bankName}
              </span>
            )}
            {p.trustAccount.trustNumber && (
              <span>
                <strong>No.:</strong>{" "}
                <span className="mono">{p.trustAccount.trustNumber}</span>
              </span>
            )}
            {p.trustAccount.bankFee && (
              <span>
                <strong>Comisión:</strong>{" "}
                {formatMoney(p.trustAccount.bankFee, "MXN")}
              </span>
            )}
            {p.trustAccount.dueDate1 && (
              <span>
                <strong>Vigencia:</strong>{" "}
                {formatDate(p.trustAccount.dueDate1)}
                {p.trustAccount.dueDate2
                  ? ` – ${formatDate(p.trustAccount.dueDate2)}`
                  : ""}
              </span>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

/* ------------------------------------------------------ Pólizas de seguro */
function PolizasSection({
  policies,
  customerId,
  customerName,
}: {
  policies: Policy[];
  customerId: string;
  customerName: string;
}) {
  const canCreate = useCan("policy:create");
  return (
    <section className="section">
      <div className="detail-actionbar">
        <SectionHead
          rule="seguros"
          title="Pólizas de seguro"
          count={policies.length}
        />
        {canCreate && (
          <Link
            href={`/polizas/nuevo?customerId=${customerId}&customerName=${encodeURIComponent(customerName)}`}
            className="btn btn-outline"
          >
            + Nueva póliza
          </Link>
        )}
      </div>
      <div className="card">
        {policies.length === 0 ? (
          <div className="empty-inline">
            Este cliente no tiene pólizas registradas.
          </div>
        ) : (
          policies.map((p) => <PolicyCard key={p.id} p={p} />)
        )}
      </div>
    </section>
  );
}

function PolicyCard({ p }: { p: Policy }) {
  const { value: headline, label: headlineLabel } = premiumHeadline(p);

  return (
    <div className="policy-card">
      <div className="policy-head">
        <div>
          <Link href={`/polizas/${p.id}`} className="policy-num policy-num-link">
            {p.policyNumber || "—"} →
          </Link>
          <div className="policy-type-row">
            {p.policyType?.name && (
              <span className="badge badge-seguros">
                <span className="dot" /> {p.policyType.name}
              </span>
            )}
            {p.insuranceProvider?.name && (
              <span>{p.insuranceProvider.name}</span>
            )}
            {p.agentName && (
              <>
                <span className="sep">·</span>
                <span>Agente: {p.agentName}</span>
              </>
            )}
            <span
              className={`badge ${
                p.liquidated ? "badge-positive" : "badge-neutral"
              }`}
            >
              {p.liquidated ? "Liquidada" : "Pendiente"}
            </span>
          </div>
          <div className="policy-type-row">
            <span className="kv-label" style={{ margin: 0 }}>
              Vigencia:
            </span>
            <span className="mono">
              {formatDate(p.policyFrom)} – {formatDate(p.policyTo)}
            </span>
          </div>
        </div>
        <div className="policy-figures">
          <div className="policy-total">
            {formatMoney(headline, p.currency)}
          </div>
          <div className="policy-total-label">{headlineLabel}</div>
        </div>
      </div>

      <div className="policy-body">
        {p.installments.length > 0 && (
          <div className="subpanel">
            <div className="subpanel-title">
              <span>Pagos</span>
              <span>{p.installments.length}</span>
            </div>
            {p.installments.map((inst) => (
              <InstallmentRow key={inst.id} inst={inst} />
            ))}
          </div>
        )}

        {p.vehicles.length > 0 && (
          <div className="subpanel">
            <div className="subpanel-title">
              <span>Vehículos</span>
              <span>{p.vehicles.length}</span>
            </div>
            <div className="mini-list">
              {p.vehicles.map((v) => (
                <div key={v.id}>
                  {[v.make, v.model, v.modelYear].filter(Boolean).join(" ") ||
                    "Vehículo"}
                  <div className="mini-sub">
                    {[
                      v.bodyType,
                      v.licensePlate ? `Placa ${v.licensePlate}` : null,
                    ]
                      .filter(Boolean)
                      .join(" · ")}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {p.insuredDrivers.length > 0 && (
          <div className="subpanel">
            <div className="subpanel-title">
              <span>Asegurados</span>
              <span>{p.insuredDrivers.length}</span>
            </div>
            <div className="mini-list">
              {p.insuredDrivers.map((d) => (
                <div key={d.id}>
                  {d.fullName || "—"}
                  {d.licenseNumber && (
                    <div className="mini-sub mono">Lic. {d.licenseNumber}</div>
                  )}
                </div>
              ))}
            </div>
          </div>
        )}

        {p.beneficiaries.length > 0 && (
          <div className="subpanel">
            <div className="subpanel-title">
              <span>Beneficiarios</span>
              <span>{p.beneficiaries.length}</span>
            </div>
            <div className="mini-list">
              {p.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>
  );
}

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"}
          {method && (
            <span className="muted" style={{ fontSize: 11 }}>
              {" "}
              · {method}
            </span>
          )}
        </span>
      </span>
      <span className="mono" style={{ fontWeight: 600 }}>
        {formatMoney(inst.amount, inst.currency)}
      </span>
    </div>
  );
}

/* ------------------------------------------------------- Estado de cuenta */
function EstadoCuentaSection({
  customerId,
  summary,
  transactions,
}: {
  customerId: string;
  summary: TransactionSummaryRow[];
  transactions: Transaction[];
}) {
  return (
    <section className="section">
      <SectionHead
        rule="cuenta"
        title="Estado de cuenta"
        count={transactions.length}
        countSuffix="movimientos"
      />

      {summary.length > 0 && (
        <div className="summary-grid">
          {summary.map((row, i) => (
            <div className={`summary-card ${row.domain}`} key={i}>
              <div className="summary-domain">
                <span className={`tx-dot ${row.domain}`} />
                {domainLabel(row.domain)} · {row.currency}
              </div>
              <div className="summary-total">
                {formatMoney(row.total, row.currency)}
              </div>
              <div className="summary-count">
                {row.count}{" "}
                {row.count === 1 ? "movimiento" : "movimientos"}
              </div>
            </div>
          ))}
        </div>
      )}

      <div className="card">
        {transactions.length === 0 ? (
          <div className="empty-inline">Sin movimientos registrados.</div>
        ) : (
          <div className="tx-scroll">
            <table className="tx-table">
              <thead>
                <tr>
                  <th>Fecha</th>
                  <th>Línea</th>
                  <th>Tipo</th>
                  <th>Referencia</th>
                  <th>Concepto</th>
                  <th className="num">Monto</th>
                </tr>
              </thead>
              <tbody>
                {transactions.map((t) => (
                  <TxRow key={t.id} t={t} />
                ))}
              </tbody>
            </table>
          </div>
        )}
        {transactions.length >= 100 && (
          <div className="section-note" style={{ padding: "0 16px 14px" }}>
            Mostrando los 100 movimientos más recientes.
          </div>
        )}
      </div>
      {transactions.length > 0 && (
        <p className="section-note">
          <Link href={`/estado-cuenta/${customerId}`} className="inline-link">
            Ver estado de cuenta completo →
          </Link>{" "}
          con saldo, saldo corrido y desglose por línea de negocio.
        </p>
      )}
    </section>
  );
}

function TxRow({ t }: { t: Transaction }) {
  const num = t.amount != null ? Number(t.amount) : NaN;
  const sign = !Number.isNaN(num) && num < 0 ? "neg" : "pos";
  const tipo =
    t.type?.nameEs || t.type?.nameEn || "—";
  const concept = t.message || t.period || "—";
  const voided = !!t.voidedAt;

  return (
    <tr style={voided ? { textDecoration: "line-through", opacity: 0.55 } : undefined}>
      <td className="mono" style={{ whiteSpace: "nowrap" }}>
        {formatDate(t.transactionDate)}
      </td>
      <td className="tx-domain-cell">
        <span className={`tx-dot ${t.domain}`} />
        {domainLabel(t.domain)}
      </td>
      <td>{tipo}</td>
      <td className="tx-ref">{t.reference || "—"}</td>
      <td className="tx-concept">
        {concept}
        {voided && (
          <span className="tx-cur" style={{ marginLeft: 6, textDecoration: "none" }}>
            (anulado)
          </span>
        )}
      </td>
      <td className="num">
        <span className={`tx-amount ${sign}`}>
          {formatMoney(t.amount, t.currency)}
        </span>{" "}
        <span className="tx-cur">{t.currency}</span>
      </td>
    </tr>
  );
}

/* ----------------------------------------------------------- Documentos */
function DocumentosSection({ data }: { data: CustomerDetail }) {
  type Doc = { type: string; scope: string; href: string | null };
  const docs: Doc[] = [];
  data.properties.forEach((p) => {
    const label = [p.addressLine1].filter(Boolean).join("") || "Propiedad";
    p.documents.forEach((d) =>
      docs.push({
        type: d.documentType || "Documento",
        scope: label,
        href: d.id ? propertyDocumentDownloadUrl(p.id, d.id) : null,
      }),
    );
  });
  data.policies.forEach((p) => {
    p.documents.forEach((d) =>
      docs.push({
        type: d.documentType || "Documento",
        scope: `Póliza ${p.policyNumber ?? ""}`.trim(),
        href: d.id ? policyDocumentDownloadUrl(p.id, d.id) : null,
      }),
    );
  });

  return (
    <section className="section">
      <SectionHead rule="docs" title="Documentos" count={docs.length} />
      <div className="card">
        {docs.length === 0 ? (
          <div className="empty-inline">
            No hay documentos registrados para este cliente.
          </div>
        ) : (
          <div className="doc-list">
            {docs.map((d, i) => (
              <div className="doc-item" key={i}>
                <span className="doc-icon" aria-hidden>
                  ▤
                </span>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div className="doc-type">{d.type}</div>
                  <div className="doc-key">{d.scope}</div>
                </div>
                {d.href && (
                  <a className="btn btn-ghost" href={d.href}>
                    Descargar
                  </a>
                )}
              </div>
            ))}
          </div>
        )}
      </div>
    </section>
  );
}

/* -------------------------------------------------------------- helpers */
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>
  );
}
