import { Icon } from "@iconify/react";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import styled from "styled-components";
import {
  getHojaDeRuta,
  getClientesSinCobrador,
  asignarCobradorACliente,
} from "../../api/cobros.service";
import { getAccessToken } from "../../api/api.config";
import { getCobradoresActivos } from "../../api/vendedores-cobradores.service";
import { getGestiones } from "../../api/cobranzas.service";
import { getCobGestionTipoChip, getCobGestionResultadoChip } from "../_standards/enums/estados";

// ─── Helpers ────────────────────────────────────────────────────────────────

const fmtGs = (v) =>
  `Gs. ${Number(v || 0).toLocaleString("es-PY", { maximumFractionDigits: 0 })}`;

// ─── Estado filter definitions ────────────────────────────────────────────────

const ESTADOS = [
  { key: "todos",       label: "Todos",          icon: "lucide:list",          color: null },
  { key: "vencido",     label: "Vencidos",        icon: "lucide:alert-circle",  color: "#f87171" },
  { key: "al_dia",      label: "Al día",          icon: "lucide:check-circle",  color: "#4ade80" },
  { key: "proximos",    label: "Próx. 7d",        icon: "lucide:clock",         color: "#fbbf24", dias: 7 },
  { key: "proximos15",  label: "Próx. 15d",       icon: "lucide:clock",         color: "#fbbf24", dias: 15 },
  { key: "proximos30",  label: "Próx. 30d",       icon: "lucide:clock",         color: "#fb923c", dias: 30 },
  { key: "con_promesa", label: "Con promesa",     icon: "lucide:handshake",     color: "#a78bfa" },
  { key: "sin_deuda",   label: "Sin deuda",       icon: "lucide:badge-check",   color: "#94a3b8" },
];

// ─── Styled ──────────────────────────────────────────────────────────────────

const Container = styled.div`
  display: flex;
  flex-direction: column;
  height: calc(100vh - 160px);
  background: ${({ theme }) => theme.bg1};
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid ${({ theme }) => theme.color2};
`;

const TopBar = styled.div`
  display: flex;
  align-items: flex-end;
  gap: 12px;
  padding: 14px 18px;
  background: ${({ theme }) => theme.bg2};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  flex-wrap: wrap;
`;

/* ── Cobrador searchable ── */
const CobradorWrapper = styled.div`
  position: relative;
  min-width: 240px;

  label {
    display: block;
    font-size: 10px;
    font-weight: 700;
    color: ${({ theme }) => theme.textSecondary};
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 4px;
  }
`;

const CobradorInput = styled.input`
  width: 100%;
  height: 34px;
  padding: 0 32px 0 10px;
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 6px;
  font-size: 13px;
  color: ${({ theme }) => theme.color1};
  background: ${({ theme }) => theme.bg3};
  outline: none;
  box-sizing: border-box;
  cursor: pointer;

  &:focus {
    border-color: ${({ theme }) => theme.primary};
  }

  &::placeholder {
    color: ${({ theme }) => theme.textSecondary};
  }
`;

const CobradorCaret = styled.span`
  position: absolute;
  right: 9px;
  bottom: 9px;
  color: ${({ theme }) => theme.textSecondary};
  pointer-events: none;
`;

const CobradorDropdown = styled.ul`
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 200;
  background: ${({ theme }) => theme.bg2};
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  max-height: 220px;
  overflow-y: auto;
  margin: 0;
  padding: 4px 0;
  list-style: none;
`;

const CobradorOption = styled.li`
  padding: 8px 12px;
  font-size: 13px;
  color: ${({ $active, theme }) => $active ? theme.primary : theme.color1};
  background: ${({ $active, theme }) => $active ? `${theme.primary}18` : "transparent"};
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;

  &:hover {
    background: ${({ theme }) => theme.bg3};
  }
`;

const CobradorEmpty = styled.li`
  padding: 10px 12px;
  font-size: 12px;
  color: ${({ theme }) => theme.textSecondary};
  text-align: center;
`;

const PdfButton = styled.button`
  display: flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 16px;
  background: ${({ theme }) => theme.primary};
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  margin-left: auto;
  align-self: flex-end;

  &:hover { opacity: 0.88; }
  &:disabled { opacity: 0.35; cursor: not-allowed; }
`;

/* ── Stats strip ── */
const StatsStrip = styled.div`
  display: flex;
  gap: 1px;
  background: ${({ theme }) => theme.color2};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
`;

const StatCard = styled.div`
  flex: 1;
  padding: 10px 14px;
  background: ${({ theme }) => theme.bg2};
  display: flex;
  flex-direction: column;
  gap: 2px;
`;

const StatLabel = styled.div`
  font-size: 10px;
  font-weight: 700;
  color: ${({ theme }) => theme.textSecondary};
  text-transform: uppercase;
  letter-spacing: 0.04em;
`;

const StatValue = styled.div`
  font-size: 18px;
  font-weight: 700;
  color: ${({ $color, theme }) => $color || theme.color1};
  line-height: 1;
`;

const StatSub = styled.div`
  font-size: 10.5px;
  color: ${({ theme }) => theme.textSecondary};
`;

/* ── Filter chips ── */
const FiltersBar = styled.div`
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  background: ${({ theme }) => theme.bg1};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  flex-wrap: wrap;
`;

const FilterChip = styled.button`
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 11px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.12s;
  border: 1.5px solid ${({ $active, $color, theme }) =>
    $active ? ($color || theme.primary) : theme.color2};
  background: ${({ $active, $color, theme }) =>
    $active ? ($color ? `${$color}22` : `${theme.primary}22`) : "transparent"};
  color: ${({ $active, $color, theme }) =>
    $active ? ($color || theme.primary) : theme.textSecondary};

  &:hover {
    border-color: ${({ $color, theme }) => $color || theme.primary};
    color: ${({ $color, theme }) => $color || theme.primary};
    background: ${({ $color, theme }) => $color ? `${$color}18` : `${theme.primary}18`};
  }
`;

const ChipCount = styled.span`
  background: ${({ $active, $color, theme }) =>
    $active ? ($color || theme.primary) : theme.color2};
  color: ${({ $active }) => $active ? "#fff" : "inherit"};
  border-radius: 10px;
  padding: 0 6px;
  font-size: 10px;
  min-width: 16px;
  text-align: center;
`;

/* ── Table area ── */
const ScrollArea = styled.div`
  flex: 1;
  overflow-y: auto;
  padding: 0;
`;

const SectionHeader = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px 8px;
  font-size: 11px;
  font-weight: 700;
  color: ${({ theme }) => theme.textSecondary};
  text-transform: uppercase;
  letter-spacing: 0.06em;
  position: sticky;
  top: 0;
  background: ${({ theme }) => theme.bg1};
  z-index: 10;
  border-bottom: 1px solid ${({ theme }) => theme.color2};
`;

const CountBadge = styled.span`
  background: ${({ theme }) => theme.color2};
  border-radius: 10px;
  padding: 1px 8px;
  font-size: 11px;
  color: ${({ theme }) => theme.textSecondary};
`;

const Table = styled.table`
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
`;

const Th = styled.th`
  text-align: left;
  font-size: 10px;
  font-weight: 700;
  color: ${({ theme }) => theme.textSecondary};
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 8px 10px;
  background: ${({ theme }) => theme.bg2};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  white-space: nowrap;
  position: sticky;
  top: 40px;
  z-index: 9;
`;

const Tr = styled.tr`
  &:hover td {
    background: ${({ theme }) => theme.bg2}bb;
  }
`;

const Td = styled.td`
  padding: 8px 10px;
  border-bottom: 1px solid ${({ theme }) => theme.color2}44;
  vertical-align: top;
  color: ${({ theme }) => theme.color1};
`;

const TdMuted = styled(Td)`
  color: ${({ theme }) => theme.textSecondary};
  font-size: 11.5px;
`;

const TdSaldo = styled(Td)`
  color: ${(p) => (p.$vencido ? "#f87171" : p.$cero ? "#94a3b8" : "#4ade80")};
  font-weight: 600;
  text-align: right;
  white-space: nowrap;
`;

const UrgBadge = styled.span`
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 700;
  background: ${(p) => p.$bg};
  color: ${(p) => p.$color};
  white-space: nowrap;
`;

const PromesaBox = styled.div`
  display: flex;
  flex-direction: column;
  gap: 2px;
`;

const PromesaChip = styled.span`
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 10px;
  font-size: 10.5px;
  font-weight: 600;
  background: #7c3aed22;
  color: #a78bfa;
  white-space: nowrap;
`;

const PromesaMonto = styled.div`
  font-size: 10.5px;
  color: ${({ theme }) => theme.textSecondary};
`;

const PromesaNota = styled.div`
  font-size: 10px;
  color: ${({ theme }) => theme.textSecondary};
  font-style: italic;
`;

const ProductosList = styled.div`
  font-size: 10.5px;
  color: ${({ theme }) => theme.textSecondary};
  margin-top: 2px;
`;

const EmptyState = styled.div`
  text-align: center;
  padding: 40px;
  color: ${({ theme }) => theme.textSecondary};
  font-size: 13px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
`;

/* ── Sin cobrador ── */
const SinCobradorHeader = styled.div`
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px 10px;
  margin-top: 16px;
  background: ${({ theme }) => theme.bg2};
  border-top: 2px solid ${({ theme }) => theme.color2};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  flex-wrap: wrap;
`;

const SinCobradorTitle = styled.div`
  font-size: 11px;
  font-weight: 700;
  color: ${({ theme }) => theme.textSecondary};
  text-transform: uppercase;
  letter-spacing: 0.06em;
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
`;

const SearchInput = styled.input`
  height: 30px;
  padding: 0 10px 0 30px;
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 6px;
  font-size: 12.5px;
  color: ${({ theme }) => theme.color1};
  background: ${({ theme }) => theme.bg3};
  outline: none;
  width: 220px;
  box-sizing: border-box;

  &:focus {
    border-color: ${({ theme }) => theme.primary};
  }
  &::placeholder {
    color: ${({ theme }) => theme.textSecondary};
  }
`;

const SearchWrap = styled.div`
  position: relative;
  display: flex;
  align-items: center;

  svg {
    position: absolute;
    left: 8px;
    color: ${({ theme }) => theme.textSecondary};
    pointer-events: none;
  }
`;

const AsignarRow = styled.div`
  display: flex;
  gap: 6px;
  align-items: center;
`;

const AsignarSelect = styled.select`
  font-size: 12px;
  padding: 3px 8px;
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 5px;
  background: ${({ theme }) => theme.bg3};
  color: ${({ theme }) => theme.color1};
  cursor: pointer;
  &:focus { outline: none; border-color: ${({ theme }) => theme.primary}; }
`;

const AsignarBtn = styled.button`
  font-size: 12px;
  padding: 3px 10px;
  border: 1px solid ${({ theme }) => theme.primary};
  border-radius: 5px;
  background: ${({ theme }) => theme.primary}22;
  color: ${({ theme }) => theme.primary};
  cursor: pointer;
  font-weight: 600;
  white-space: nowrap;
  &:hover { background: ${({ theme }) => theme.primary}44; }
  &:disabled { opacity: 0.5; cursor: not-allowed; }
`;

// ─── PDF Modal ───────────────────────────────────────────────────────────────

const PdfModalOverlay = styled.div`
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
`;

const PdfModalBox = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 900px;
  height: 90vh;
  background: ${({ theme }) => theme.bg2};
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5);
`;

const PdfModalHeader = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: ${({ theme }) => theme.bg3};
  border-bottom: 1px solid ${({ theme }) => theme.border || "rgba(255,255,255,0.08)"};
  font-size: 13px;
  font-weight: 600;
  color: ${({ theme }) => theme.color1};
  flex-shrink: 0;
`;

const PdfModalActions = styled.div`
  display: flex;
  gap: 8px;
  align-items: center;
`;

const PdfModalBtn = styled.button`
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 5px;
  border: 1px solid ${({ theme }) => theme.primary};
  background: ${({ theme }) => theme.primary}22;
  color: ${({ theme }) => theme.primary};
  cursor: pointer;
  font-weight: 600;
  text-decoration: none;
  &:hover { background: ${({ theme }) => theme.primary}44; }
`;

const PdfModalCloseBtn = styled.button`
  display: flex;
  align-items: center;
  padding: 4px 6px;
  border-radius: 5px;
  border: 1px solid transparent;
  background: transparent;
  color: ${({ theme }) => theme.textSecondary || theme.color2};
  cursor: pointer;
  &:hover { background: rgba(255,255,255,0.08); }
`;

const PdfFrame = styled.iframe`
  flex: 1;
  width: 100%;
  border: none;
`;

// ─── Searchable Cobrador Select ───────────────────────────────────────────────

function CobradorSelector({ cobradores, value, onChange, loading }) {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const ref = useRef(null);
  const inputRef = useRef(null);

  const selected = cobradores.find((c) => c.id === value);
  const filtered = cobradores.filter((c) =>
    c.nombre?.toLowerCase().includes(search.toLowerCase())
  );

  useEffect(() => {
    const handler = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const handleOpen = () => {
    setOpen(true);
    setSearch("");
    setTimeout(() => inputRef.current?.focus(), 50);
  };

  const handleSelect = (cobrador) => {
    onChange(cobrador.id);
    setOpen(false);
    setSearch("");
  };

  const handleClear = (e) => {
    e.stopPropagation();
    onChange("");
    setOpen(false);
  };

  return (
    <CobradorWrapper ref={ref}>
      <label>Cobrador</label>
      {open ? (
        <>
          <CobradorInput
            ref={inputRef}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Buscar cobrador..."
          />
          <CobradorCaret>
            <Icon icon="lucide:search" width={13} />
          </CobradorCaret>
          <CobradorDropdown>
            {filtered.length === 0 ? (
              <CobradorEmpty>Sin resultados</CobradorEmpty>
            ) : (
              filtered.map((c) => (
                <CobradorOption
                  key={c.id}
                  $active={c.id === value}
                  onMouseDown={() => handleSelect(c)}
                >
                  <Icon icon="lucide:user" width={13} />
                  {c.nombre}
                </CobradorOption>
              ))
            )}
          </CobradorDropdown>
        </>
      ) : (
        <>
          <CobradorInput
            readOnly
            value={selected?.nombre || ""}
            placeholder={loading ? "Cargando..." : "— Seleccionar cobrador —"}
            onClick={handleOpen}
            style={{ cursor: "pointer" }}
          />
          <CobradorCaret onClick={value ? handleClear : handleOpen} style={{ cursor: "pointer", pointerEvents: "all" }}>
            <Icon icon={value ? "lucide:x" : "lucide:chevron-down"} width={14} />
          </CobradorCaret>
        </>
      )}
    </CobradorWrapper>
  );
}

// ─── Sin cobrador row ─────────────────────────────────────────────────────────

function SinCobradorRow({ cliente, cobradores, onAsignar }) {
  const [sel, setSel] = useState("");
  const [loading, setLoading] = useState(false);

  const handleAsignar = async () => {
    if (!sel) { toast.warning("Seleccione un cobrador"); return; }
    setLoading(true);
    try {
      await onAsignar(cliente.cliente_id, sel);
      toast.success("Cobrador asignado correctamente");
    } catch {
      toast.error("Error al asignar cobrador");
    } finally {
      setLoading(false);
    }
  };

  return (
    <Tr>
      <Td style={{ fontWeight: 600 }}>{cliente.razon_social}</Td>
      <TdMuted>{cliente.nro_documento}</TdMuted>
      <TdMuted>{cliente.direccion || "—"}</TdMuted>
      <TdMuted>{cliente.celular || "—"}</TdMuted>
      <TdSaldo $vencido={cliente.saldo_pendiente > 0} $cero={cliente.saldo_pendiente === 0}>
        {fmtGs(cliente.saldo_pendiente)}
      </TdSaldo>
      <Td>
        <AsignarRow>
          <AsignarSelect value={sel} onChange={(e) => setSel(e.target.value)}>
            <option value="">— Seleccionar —</option>
            {cobradores.map((c) => (
              <option key={c.id} value={c.id}>{c.nombre}</option>
            ))}
          </AsignarSelect>
          <AsignarBtn onClick={handleAsignar} disabled={loading}>
            {loading ? "..." : "Asignar"}
          </AsignarBtn>
        </AsignarRow>
      </Td>
    </Tr>
  );
}

// ─── Urgencia helper ──────────────────────────────────────────────────────────

function UrgenciaBadge({ cuotasVencidas, diasVencido, proximaCuota }) {
  if (cuotasVencidas > 0) {
    const critica = diasVencido > 30;
    return (
      <UrgBadge $bg={critica ? "#f8717122" : "#fbbf2422"} $color={critica ? "#f87171" : "#fbbf24"}>
        <Icon icon="lucide:alert-circle" width={10} />
        {diasVencido}d vencido
      </UrgBadge>
    );
  }
  if (proximaCuota) {
    const dias = Math.ceil((new Date(proximaCuota) - new Date()) / 86400000);
    if (dias <= 7) return (
      <UrgBadge $bg="#fbbf2422" $color="#fbbf24">
        <Icon icon="lucide:clock" width={10} />
        vence en {dias}d
      </UrgBadge>
    );
  }
  return (
    <UrgBadge $bg="#4ade8022" $color="#4ade80">
      <Icon icon="lucide:check-circle" width={10} />
      Al día
    </UrgBadge>
  );
}

// ─── Main ─────────────────────────────────────────────────────────────────────

export function HojaRutaTab() {
  const [cobradorId, setCobradorId] = useState("");
  const [estadoKey, setEstadoKey] = useState("todos");
  const [busquedaSinCobrador, setBusquedaSinCobrador] = useState("");
  const [pdfUrl, setPdfUrl] = useState(null);
  const [pdfLoading, setPdfLoading] = useState(false);
  const queryClient = useQueryClient();

  const estadoObj = ESTADOS.find((e) => e.key === estadoKey) || ESTADOS[0];
  const apiEstado = estadoObj.key.startsWith("proximos") ? "proximos" : estadoObj.key;
  const diasProximos = estadoObj.dias;

  const { data: cobradoresRaw = [], isLoading: loadingCobradores } = useQuery({
    queryKey: ["cobradores-activos"],
    queryFn: getCobradoresActivos,
  });
  const cobradoresList = Array.isArray(cobradoresRaw) ? cobradoresRaw : cobradoresRaw?.data || [];

  const { data: clientes = [], isLoading: loadingClientes } = useQuery({
    queryKey: ["hoja-de-ruta", cobradorId, apiEstado, diasProximos],
    queryFn: () => getHojaDeRuta(cobradorId, { estado: apiEstado, dias_proximos: diasProximos }),
    enabled: !!cobradorId,
  });

  const { data: sinCobradorRaw = [], isLoading: loadingSinCobrador } = useQuery({
    queryKey: ["clientes-sin-cobrador"],
    queryFn: getClientesSinCobrador,
  });
  const sinCobradorList = Array.isArray(sinCobradorRaw) ? sinCobradorRaw : sinCobradorRaw?.data || [];

  // Últimas gestiones del cobrador (para mostrar 3 por cliente)
  const { data: gestionesCobrador = [] } = useQuery({
    queryKey: ["hoja-ruta-gestiones", cobradorId],
    queryFn: () => getGestiones({ cobradorId }),
    enabled: !!cobradorId,
  });
  const gestionesByCliente = (Array.isArray(gestionesCobrador) ? gestionesCobrador : [])
    .reduce((acc, g) => {
      const k = g.cliente_id;
      if (!acc[k]) acc[k] = [];
      if (acc[k].length < 3) acc[k].push(g);
      return acc;
    }, {});

  const sinCobradorFiltrado = busquedaSinCobrador.trim().length >= 1
    ? sinCobradorList.filter((c) =>
        c.razon_social?.toLowerCase().includes(busquedaSinCobrador.toLowerCase()) ||
        c.nro_documento?.includes(busquedaSinCobrador)
      )
    : sinCobradorList;

  // Pre-fetch counts for all filters (using "todos" data)
  const { data: todosClientes = [] } = useQuery({
    queryKey: ["hoja-de-ruta", cobradorId, "todos", undefined],
    queryFn: () => getHojaDeRuta(cobradorId, { estado: "todos" }),
    enabled: !!cobradorId,
  });

  const counts = {
    todos:       todosClientes.length,
    vencido:     todosClientes.filter((c) => c.cuotas_vencidas > 0).length,
    al_dia:      todosClientes.filter((c) => c.cuotas_vencidas === 0 && c.saldo_pendiente > 0).length,
    proximos:    todosClientes.filter((c) => { if (!c.proxima_cuota_fecha) return false; const d = Math.ceil((new Date(c.proxima_cuota_fecha) - new Date()) / 86400000); return d >= 0 && d <= 7; }).length,
    proximos15:  todosClientes.filter((c) => { if (!c.proxima_cuota_fecha) return false; const d = Math.ceil((new Date(c.proxima_cuota_fecha) - new Date()) / 86400000); return d >= 0 && d <= 15; }).length,
    proximos30:  todosClientes.filter((c) => { if (!c.proxima_cuota_fecha) return false; const d = Math.ceil((new Date(c.proxima_cuota_fecha) - new Date()) / 86400000); return d >= 0 && d <= 30; }).length,
    con_promesa: todosClientes.filter((c) => c.promesa != null).length,
    sin_deuda:   todosClientes.filter((c) => c.saldo_pendiente === 0).length,
  };

  const totalSaldo = todosClientes.reduce((s, c) => s + (c.saldo_pendiente || 0), 0);
  const totalVencido = todosClientes.filter((c) => c.cuotas_vencidas > 0).reduce((s, c) => s + (c.saldo_pendiente || 0), 0);

  const handleAsignar = useCallback(async (clienteId, newCobradorId) => {
    await asignarCobradorACliente(clienteId, newCobradorId);
    queryClient.invalidateQueries({ queryKey: ["clientes-sin-cobrador"] });
    queryClient.invalidateQueries({ queryKey: ["hoja-de-ruta"] });
  }, [queryClient]);

  const handleGenerarPdf = async () => {
    if (!cobradorId) { toast.warning("Seleccione un cobrador primero"); return; }
    setPdfLoading(true);
    try {
      const token = getAccessToken() || "";
      const baseUrl = import.meta.env.VITE_API_BASE_URL || "http://localhost:3000/api/v1";
      const url = `${baseUrl}/cobros/hoja-de-ruta/pdf?cobrador_id=${cobradorId}`;
      const r = await fetch(url, { headers: { Authorization: `Bearer ${token}`, "x-app-key": import.meta.env.VITE_APP_KEY || "" } });
      if (!r.ok) throw new Error();
      const blob = await r.blob();
      if (pdfUrl) URL.revokeObjectURL(pdfUrl);
      setPdfUrl(URL.createObjectURL(blob));
    } catch {
      toast.error("Error al generar PDF");
    } finally {
      setPdfLoading(false);
    }
  };

  const handleClosePdf = () => {
    if (pdfUrl) URL.revokeObjectURL(pdfUrl);
    setPdfUrl(null);
  };

  return (
    <Container>
      {/* ── Top bar ── */}
      <TopBar>
        <CobradorSelector
          cobradores={cobradoresList}
          value={cobradorId}
          onChange={setCobradorId}
          loading={loadingCobradores}
        />
        <PdfButton onClick={handleGenerarPdf} disabled={!cobradorId || pdfLoading}>
          <Icon icon="mdi:printer" width={15} />
          {pdfLoading ? "Generando..." : "Generar PDF"}
        </PdfButton>
      </TopBar>

      {/* ── Stats strip (solo si hay cobrador) ── */}
      {cobradorId && todosClientes.length > 0 && (
        <StatsStrip>
          <StatCard>
            <StatLabel>Total clientes</StatLabel>
            <StatValue>{todosClientes.length}</StatValue>
          </StatCard>
          <StatCard>
            <StatLabel>Saldo total</StatLabel>
            <StatValue style={{ fontSize: 14 }}>{fmtGs(totalSaldo)}</StatValue>
          </StatCard>
          <StatCard>
            <StatLabel>Vencido</StatLabel>
            <StatValue $color="#f87171">{counts.vencido}</StatValue>
            <StatSub>{fmtGs(totalVencido)}</StatSub>
          </StatCard>
          <StatCard>
            <StatLabel>Con promesa</StatLabel>
            <StatValue $color="#a78bfa">{counts.con_promesa}</StatValue>
          </StatCard>
          <StatCard>
            <StatLabel>Sin cobrador asig.</StatLabel>
            <StatValue $color="#fbbf24">{sinCobradorList.length}</StatValue>
          </StatCard>
        </StatsStrip>
      )}

      {/* ── Filter chips ── */}
      {cobradorId && (
        <FiltersBar>
          {ESTADOS.map((e) => (
            <FilterChip
              key={e.key}
              $active={estadoKey === e.key}
              $color={e.color}
              onClick={() => setEstadoKey(e.key)}
            >
              <Icon icon={e.icon} width={12} />
              {e.label}
              <ChipCount $active={estadoKey === e.key} $color={e.color}>
                {counts[e.key] ?? 0}
              </ChipCount>
            </FilterChip>
          ))}
        </FiltersBar>
      )}

      <ScrollArea>
        {/* ── Clientes asignados ── */}
        <SectionHeader>
          Clientes asignados
          {estadoObj.key !== "todos" && ` — ${estadoObj.label}`}
          <CountBadge>{clientes.length}</CountBadge>
        </SectionHeader>

        {!cobradorId ? (
          <EmptyState>
            <Icon icon="lucide:user-search" width={32} style={{ opacity: 0.3 }} />
            Seleccione un cobrador para ver su hoja de ruta
          </EmptyState>
        ) : loadingClientes ? (
          <EmptyState>
            <Icon icon="lucide:loader" width={24} style={{ opacity: 0.4 }} />
            Cargando...
          </EmptyState>
        ) : clientes.length === 0 ? (
          <EmptyState>
            <Icon icon="lucide:inbox" width={28} style={{ opacity: 0.3 }} />
            No hay clientes para este filtro
          </EmptyState>
        ) : (
          <Table>
            <thead>
              <tr>
                <Th>Estado</Th>
                <Th>Cliente</Th>
                <Th>CI/RUC</Th>
                <Th>Dirección / Referencia</Th>
                <Th>Celular</Th>
                <Th>Día cobro</Th>
                <Th style={{ textAlign: "right" }}>Saldo</Th>
                <Th>Promesa de pago</Th>
                <Th>Últimas gestiones</Th>
              </tr>
            </thead>
            <tbody>
              {clientes.map((c) => (
                <Tr key={c.cliente_id}>
                  <Td style={{ whiteSpace: "nowrap" }}>
                    <UrgenciaBadge
                      cuotasVencidas={c.cuotas_vencidas}
                      diasVencido={c.dias_vencido_max}
                      proximaCuota={c.proxima_cuota_fecha}
                    />
                  </Td>
                  <Td>
                    <div style={{ fontWeight: 600 }}>{c.razon_social}</div>
                    {c.productos?.length > 0 && (
                      <ProductosList>
                        {c.productos.map((p) => p.descripcion).join(" · ")}
                      </ProductosList>
                    )}
                  </Td>
                  <TdMuted>{c.nro_documento}</TdMuted>
                  <Td>
                    <div style={{ fontSize: 12 }}>{c.direccion || "—"}</div>
                    {c.referencia_domicilio && (
                      <div style={{ fontSize: 10.5, opacity: 0.65, marginTop: 2 }}>
                        <Icon icon="lucide:milestone" width={10} /> {c.referencia_domicilio}
                      </div>
                    )}
                  </Td>
                  <TdMuted>{c.celular || c.telefono || "—"}</TdMuted>
                  <TdMuted>{c.dia_cobro || "—"}</TdMuted>
                  <TdSaldo $vencido={c.cuotas_vencidas > 0} $cero={c.saldo_pendiente === 0}>
                    {fmtGs(c.saldo_pendiente)}
                  </TdSaldo>
                  <Td>
                    {c.promesa ? (
                      <PromesaBox>
                        <PromesaChip>
                          <Icon icon="lucide:handshake" width={10} />
                          {c.promesa.fecha}
                        </PromesaChip>
                        <PromesaMonto>{fmtGs(c.promesa.monto)}</PromesaMonto>
                        {c.promesa.notas && (
                          <PromesaNota>"{c.promesa.notas}"</PromesaNota>
                        )}
                      </PromesaBox>
                    ) : (
                      <TdMuted as="span">—</TdMuted>
                    )}
                  </Td>
                  <Td>
                    {(() => {
                      const list = gestionesByCliente[c.cliente_id] || [];
                      if (list.length === 0) return <TdMuted as="span">—</TdMuted>;
                      return (
                        <GestionesBox>
                          {list.map((g) => {
                            const tipo = getCobGestionTipoChip(g.tipo_gestion);
                            const res = getCobGestionResultadoChip(g.resultado);
                            const f = new Date(g.fecha).toLocaleDateString("es-PY", { day: "2-digit", month: "2-digit" });
                            return (
                              <GestionLine key={g.id} title={g.observacion || ""}>
                                <Icon icon={tipo.icon || "lucide:clipboard"} width={10} />
                                <span>{f}</span>
                                <GestionResultado>{res.label}</GestionResultado>
                              </GestionLine>
                            );
                          })}
                        </GestionesBox>
                      );
                    })()}
                  </Td>
                </Tr>
              ))}
            </tbody>
          </Table>
        )}

        {/* ── Sin cobrador — siempre visible ── */}
        <SinCobradorHeader>
          <SinCobradorTitle>
            <Icon icon="lucide:user-x" width={13} />
            Sin cobrador asignado
            <CountBadge>{sinCobradorList.length}</CountBadge>
            {busquedaSinCobrador && (
              <CountBadge style={{ background: "transparent", color: "inherit" }}>
                (mostrando {sinCobradorFiltrado.length})
              </CountBadge>
            )}
          </SinCobradorTitle>

          <SearchWrap>
            <Icon icon="lucide:search" width={13} />
            <SearchInput
              value={busquedaSinCobrador}
              onChange={(e) => setBusquedaSinCobrador(e.target.value)}
              placeholder="Buscar por nombre o CI..."
            />
          </SearchWrap>
        </SinCobradorHeader>

        {loadingSinCobrador ? (
          <EmptyState>Cargando...</EmptyState>
        ) : sinCobradorList.length === 0 ? (
          <EmptyState>
            <Icon icon="lucide:check-circle-2" width={24} style={{ opacity: 0.4 }} />
            Todos los clientes tienen cobrador asignado
          </EmptyState>
        ) : sinCobradorFiltrado.length === 0 ? (
          <EmptyState>Sin resultados para "{busquedaSinCobrador}"</EmptyState>
        ) : (
          <Table>
            <thead>
              <tr>
                <Th>Cliente</Th>
                <Th>CI/RUC</Th>
                <Th>Dirección</Th>
                <Th>Celular</Th>
                <Th style={{ textAlign: "right" }}>Saldo</Th>
                <Th>Asignar cobrador</Th>
              </tr>
            </thead>
            <tbody>
              {sinCobradorFiltrado.map((c) => (
                <SinCobradorRow
                  key={c.cliente_id}
                  cliente={c}
                  cobradores={cobradoresList}
                  onAsignar={handleAsignar}
                />
              ))}
            </tbody>
          </Table>
        )}
      </ScrollArea>

      {pdfUrl && (
        <PdfModalOverlay onClick={handleClosePdf}>
          <PdfModalBox onClick={(e) => e.stopPropagation()}>
            <PdfModalHeader>
              <span>Hoja de Ruta — Vista previa</span>
              <PdfModalActions>
                <PdfModalBtn as="a" href={pdfUrl} download="hoja-de-ruta.pdf">
                  <Icon icon="lucide:download" width={14} /> Descargar
                </PdfModalBtn>
                <PdfModalCloseBtn onClick={handleClosePdf}>
                  <Icon icon="lucide:x" width={14} />
                </PdfModalCloseBtn>
              </PdfModalActions>
            </PdfModalHeader>
            <PdfFrame src={pdfUrl} title="Hoja de Ruta PDF" />
          </PdfModalBox>
        </PdfModalOverlay>
      )}

    </Container>
  );
}

const GestionesBox = styled.div`
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
`;
const GestionLine = styled.div`
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: #475569;
`;
const GestionResultado = styled.span`
  font-size: 10.5px;
  opacity: 0.7;
`;
