"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { AppShell } from "@/components/AppShell";
import { ContextReports } from "@/components/ContextReports";
import { useCan } from "@/lib/abilities";
import {
  EXPIRY_WINDOW_DAYS,
  getPolicyFacets,
  getPolicyStats,
  listPolicies,
} from "@/lib/api";
import {
  expiryPhrase,
  formatDate,
  formatMoney,
  formatNumber,
  policyStatusLabel,
  premiumHeadline,
  SIN_NOMBRE,
} from "@/lib/labels";
import type {
  PolicyFacets,
  PolicyListItem,
  PolicyListResponse,
  PolicySort,
  PolicyStats,
  PolicyStatus,
} from "@/lib/types";

type StatusFilter = "all" | PolicyStatus;

const STATUS_FILTERS: { key: StatusFilter; label: string }[] = [
  { key: "all", label: "Todas" },
  { key: "expiring", label: "Por vencer" },
  { key: "active", label: "Vigentes" },
  { key: "expired", label: "Vencidas" },
  { key: "undated", label: "Sin vigencia" },
];

const SORTS: { key: PolicySort; label: string }[] = [
  { key: "expiry_desc", label: "Vencimiento (más reciente)" },
  { key: "expiry_asc", label: "Vencimiento (más próximo)" },
  { key: "customer", label: "Cliente (A–Z)" },
  { key: "number", label: "Número de póliza" },
  { key: "premium_desc", label: "Prima (mayor a menor)" },
];

export default function PolizasPage() {
  return (
    <AppShell>
      <PolizasBrowser />
    </AppShell>
  );
}

function PolizasBrowser() {
  const canCreate = useCan("policy:create");
  const canIngest = useCan("policy:ingest");
  const [stats, setStats] = useState<PolicyStats | null>(null);
  const [facets, setFacets] = useState<PolicyFacets | null>(null);

  const [query, setQuery] = useState("");
  const [status, setStatus] = useState<StatusFilter>("all");
  const [typeId, setTypeId] = useState("");
  const [providerId, setProviderId] = useState("");
  const [sort, setSort] = useState<PolicySort>("expiry_desc");

  const [data, setData] = useState<PolicyListResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const debounceRef = useRef<ReturnType<typeof setTimeout>>();

  useEffect(() => {
    getPolicyStats().then(setStats).catch(() => setStats(null));
    getPolicyFacets().then(setFacets).catch(() => setFacets(null));
  }, []);

  const runSearch = useCallback(
    (p: number) => {
      setLoading(true);
      setError(null);
      listPolicies({
        query: query || undefined,
        status: status === "all" ? undefined : status,
        typeId: typeId || undefined,
        providerId: providerId || undefined,
        sort,
        days: EXPIRY_WINDOW_DAYS,
        page: p,
        pageSize: 25,
      })
        .then((res) => {
          setData(res);
          setLoading(false);
        })
        .catch((e) => {
          setError(e?.message ?? "No se pudieron cargar las pólizas.");
          setLoading(false);
        });
    },
    [query, status, typeId, providerId, sort],
  );

  // Debounced re-query whenever any filter changes; always back to page 1.
  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => runSearch(1), 280);
    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
  }, [runSearch]);

  function goToPage(p: number) {
    runSearch(p);
    if (typeof window !== "undefined")
      window.scrollTo({ top: 0, behavior: "smooth" });
  }

  const filtered =
    query !== "" || status !== "all" || typeId !== "" || providerId !== "";

  return (
    <>
      <div className="page-head rise">
        <p className="eyebrow">Cartera de seguros</p>
        <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
          <h1 className="page-title" style={{ margin: 0 }}>Pólizas</h1>
          <span style={{ flex: 1 }} />
          <ContextReports
            entries={[
              { slug: "vigente", label: "Por vencer (Lic.)", params: { typeName: "LICENCIAS" } },
              { slug: "vigente", label: "Por vencer (Mult.)", params: { typeName: "MULT" } },
              { slug: "vigente", label: "Por vencer (Incen.)", params: { typeName: "INCEN" } },
            ]}
          />
          {canIngest && (
            <Link href="/polizas/captura" className="btn btn-outline">
              + Captura OCR
            </Link>
          )}
          {canCreate && (
            <Link href="/polizas/nuevo" className="btn btn-primary">+ Nueva póliza</Link>
          )}
        </div>
        <StatStrip
          stats={stats}
          status={status}
          onPickStatus={(s) => setStatus(s)}
        />
        <PremiumStrip stats={stats} />
      </div>

      <div className="toolbar">
        <div className="search-box">
          <span className="search-icon" aria-hidden>
            ⌕
          </span>
          <input
            className="input search-input"
            type="search"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Buscar por póliza, cliente, placa, agente…"
            aria-label="Buscar pólizas"
          />
        </div>
        <div className="seg" role="tablist" aria-label="Filtrar por vigencia">
          {STATUS_FILTERS.map((f) => (
            <button
              key={f.key}
              type="button"
              role="tab"
              aria-selected={status === f.key}
              className={`seg-btn ${status === f.key ? "active" : ""}`}
              onClick={() => setStatus(f.key)}
            >
              {f.label}
            </button>
          ))}
        </div>
      </div>

      <div className="filter-row">
        <label className="filter-field">
          <span className="filter-label">Ramo</span>
          <select
            className="input select"
            value={typeId}
            onChange={(e) => setTypeId(e.target.value)}
          >
            <option value="">Todos los ramos</option>
            {facets?.types
              .filter((t) => t.count > 0)
              .map((t) => (
                <option key={t.id} value={t.id}>
                  {t.name} ({formatNumber(t.count)})
                </option>
              ))}
          </select>
        </label>

        <label className="filter-field">
          <span className="filter-label">Aseguradora</span>
          <select
            className="input select"
            value={providerId}
            onChange={(e) => setProviderId(e.target.value)}
          >
            <option value="">Todas las aseguradoras</option>
            {facets?.providers
              .filter((p) => p.count > 0)
              .map((p) => (
                <option key={p.id} value={p.id}>
                  {p.name} ({formatNumber(p.count)})
                </option>
              ))}
          </select>
        </label>

        <label className="filter-field">
          <span className="filter-label">Ordenar por</span>
          <select
            className="input select"
            value={sort}
            onChange={(e) => setSort(e.target.value as PolicySort)}
          >
            {SORTS.map((s) => (
              <option key={s.key} value={s.key}>
                {s.label}
              </option>
            ))}
          </select>
        </label>

        {filtered && (
          <button
            type="button"
            className="btn btn-ghost filter-clear"
            onClick={() => {
              setQuery("");
              setStatus("all");
              setTypeId("");
              setProviderId("");
            }}
          >
            Limpiar filtros
          </button>
        )}
      </div>

      {data && !loading && !error && (
        <div className="result-meta" aria-live="polite">
          {data.total === 0
            ? "Sin resultados"
            : `${formatNumber(data.total)} ${
                data.total === 1 ? "póliza" : "pólizas"
              }`}
          {query ? ` para “${query}”` : ""}
        </div>
      )}

      {error ? (
        <div className="state-error" role="alert">
          {error}
        </div>
      ) : loading ? (
        <ListSkeleton />
      ) : data && data.items.length === 0 ? (
        <EmptyState query={query} />
      ) : (
        <>
          <div className="cust-list">
            {data?.items.map((p) => (
              <PolicyRow key={p.id} p={p} />
            ))}
          </div>
          {data && data.pageCount > 1 && (
            <Pager
              page={data.page}
              pageCount={data.pageCount}
              onChange={goToPage}
            />
          )}
        </>
      )}
    </>
  );
}

/** Counts double as filter shortcuts — clicking a cell applies that bucket. */
function StatStrip({
  stats,
  status,
  onPickStatus,
}: {
  stats: PolicyStats | null;
  status: StatusFilter;
  onPickStatus: (s: StatusFilter) => void;
}) {
  if (!stats) {
    return (
      <div className="stat-strip" aria-hidden>
        {Array.from({ length: 6 }).map((_, i) => (
          <div className="stat-cell" key={i}>
            <div className="skeleton" style={{ height: 25, width: "60%" }} />
            <div
              className="skeleton"
              style={{ height: 11, width: "80%", marginTop: 8 }}
            />
          </div>
        ))}
      </div>
    );
  }

  const cells: {
    key: StatusFilter;
    value: number;
    label: string;
    accent?: boolean;
  }[] = [
    { key: "all", value: stats.total, label: "Pólizas", accent: true },
    {
      key: "expiring",
      value: stats.expiring,
      label: `Vencen en ${stats.days} días`,
      accent: true,
    },
    { key: "active", value: stats.active, label: "Vigentes" },
    { key: "expired", value: stats.expired, label: "Vencidas" },
    { key: "undated", value: stats.undated, label: "Sin vigencia" },
  ];

  return (
    <div className="stat-strip">
      {cells.map((c) => (
        <button
          type="button"
          key={c.label}
          className={`stat-cell stat-cell-btn${c.accent ? " accent" : ""}${
            status === c.key ? " selected" : ""
          }`}
          onClick={() => onPickStatus(c.key)}
          aria-pressed={status === c.key}
        >
          <div className="stat-value">{formatNumber(c.value)}</div>
          <div className="stat-label">{c.label}</div>
        </button>
      ))}
      <div className="stat-cell">
        <div className="stat-value">{formatNumber(stats.pending)}</div>
        <div className="stat-label">Sin liquidar</div>
      </div>
    </div>
  );
}

/** Premium in force, split by currency — MXN and USD can't be summed. */
function PremiumStrip({ stats }: { stats: PolicyStats | null }) {
  if (!stats || stats.premiumInForce.length === 0) return null;
  return (
    <div className="premium-strip">
      <span className="premium-caption">Prima neta vigente</span>
      {stats.premiumInForce.map((row) => (
        <span className="premium-chip" key={row.currency}>
          <strong>{formatMoney(row.netPremium, row.currency)}</strong>
          <span className="premium-chip-sub">
            {row.currency} · {formatNumber(row.count)}{" "}
            {row.count === 1 ? "póliza" : "pólizas"}
          </span>
        </span>
      ))}
    </div>
  );
}

function PolicyRow({ p }: { p: PolicyListItem }) {
  const premium = premiumHeadline(p);
  const phrase = expiryPhrase(p.daysToExpiry);
  const showPhrase = p.status === "expiring" || p.status === "active";

  return (
    <Link href={`/polizas/${p.id}`} className="cust-row pol-row">
      <div className="cust-main">
        <div className="cust-name">
          <span className="mono pol-number">{p.policyNumber || "—"}</span>
          {p.policyType?.name && (
            <span className="badge badge-seguros">
              <span className="dot" /> {p.policyType.name}
            </span>
          )}
          <span className={`badge status-${p.status}`}>
            {policyStatusLabel(p.status)}
          </span>
          {!p.liquidated && (
            <span className="badge badge-neutral">Sin liquidar</span>
          )}
        </div>
        <div className="cust-sub">
          <span
            className={
              p.customerName === SIN_NOMBRE ? "cust-name-missing" : undefined
            }
          >
            {p.customerName}
          </span>
          {p.insuranceProvider?.name && (
            <>
              <span className="sep">·</span>
              <span>{p.insuranceProvider.name}</span>
            </>
          )}
          {p.vehicleCount > 0 && (
            <>
              <span className="sep">·</span>
              <span>
                {p.vehicleCount}{" "}
                {p.vehicleCount === 1 ? "vehículo" : "vehículos"}
              </span>
            </>
          )}
        </div>
      </div>
      <div className="pol-side">
        <div className="pol-premium">
          {formatMoney(premium.value, p.currency)}
        </div>
        <div className="pol-dates mono">
          {formatDate(p.policyFrom)} – {formatDate(p.policyTo)}
        </div>
        {showPhrase && phrase && (
          <div className={`pol-phrase ${p.status}`}>{phrase}</div>
        )}
      </div>
    </Link>
  );
}

function Pager({
  page,
  pageCount,
  onChange,
}: {
  page: number;
  pageCount: number;
  onChange: (p: number) => void;
}) {
  return (
    <nav className="pager" aria-label="Paginación">
      <button
        type="button"
        className="btn btn-outline"
        onClick={() => onChange(page - 1)}
        disabled={page <= 1}
      >
        ← Anterior
      </button>
      <span className="pager-info">
        Página <strong>{page}</strong> de {pageCount}
      </span>
      <button
        type="button"
        className="btn btn-outline"
        onClick={() => onChange(page + 1)}
        disabled={page >= pageCount}
      >
        Siguiente →
      </button>
    </nav>
  );
}

function ListSkeleton() {
  return (
    <div className="cust-list" aria-hidden>
      {Array.from({ length: 8 }).map((_, i) => (
        <div className="skeleton skel-row" key={i} />
      ))}
    </div>
  );
}

function EmptyState({ query }: { query: string }) {
  return (
    <div className="state-box">
      <div className="state-glyph" aria-hidden>
        ⌕
      </div>
      <h3>Sin resultados</h3>
      <p>
        {query
          ? `No encontramos pólizas para “${query}”.`
          : "No hay pólizas que coincidan con los filtros."}
      </p>
    </div>
  );
}
