"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 { getStats, listCustomers } from "@/lib/api";
import { useCan } from "@/lib/abilities";
import { formatNumber, SIN_NOMBRE } from "@/lib/labels";
import type {
  BusinessLine,
  CustomerListItem,
  CustomerListResponse,
  CustomerStats,
} from "@/lib/types";

type Filter = "all" | BusinessLine;

const FILTERS: { key: Filter; label: string }[] = [
  { key: "all", label: "Todos" },
  { key: "utility", label: "Servicios" },
  { key: "insurance", label: "Seguros" },
  { key: "both", label: "Ambos" },
];

export default function ClientesPage() {
  return (
    <AppShell>
      <ClientesBrowser />
    </AppShell>
  );
}

function ClientesBrowser() {
  const [stats, setStats] = useState<CustomerStats | null>(null);
  const [query, setQuery] = useState("");
  const [filter, setFilter] = useState<Filter>("all");
  const [page, setPage] = useState(1);

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

  const canCreate = useCan("customer:create");

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

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

  const runSearch = useCallback(
    (q: string, f: Filter, p: number) => {
      setLoading(true);
      setError(null);
      listCustomers({
        query: q || undefined,
        line: f === "all" ? undefined : f,
        page: p,
        pageSize: 25,
      })
        .then((res) => {
          setData(res);
          setLoading(false);
        })
        .catch((e) => {
          setError(
            e?.message ?? "No se pudieron cargar los clientes.",
          );
          setLoading(false);
        });
    },
    [],
  );

  // Debounced search on query/filter change; resets to page 1.
  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => {
      setPage(1);
      runSearch(query, filter, 1);
    }, 280);
    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [query, filter]);

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

  return (
    <>
      <div className="page-head rise">
        <p className="eyebrow">Directorio unificado</p>
        <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
          <h1 className="page-title" style={{ margin: 0 }}>Clientes</h1>
          <span style={{ flex: 1 }} />
          <ContextReports
            entries={[
              { slug: "listado-en-rojo", label: "En rojo" },
              { slug: "pagos-no-efectuados", label: "Sin pagos (agua)" },
            ]}
          />
          {canCreate && (
            <Link href="/clientes/nuevo" className="btn btn-primary">
              + Nuevo cliente
            </Link>
          )}
        </div>
        <StatStrip 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 nombre, ciudad, teléfono…"
            aria-label="Buscar clientes"
          />
        </div>
        <div
          className="seg"
          role="tablist"
          aria-label="Filtrar por línea de negocio"
        >
          {FILTERS.map((f) => (
            <button
              key={f.key}
              type="button"
              role="tab"
              aria-selected={filter === f.key}
              className={`seg-btn ${filter === f.key ? "active" : ""}`}
              onClick={() => setFilter(f.key)}
            >
              {f.label}
            </button>
          ))}
        </div>
      </div>

      {data && !loading && !error && (
        <div className="result-meta" aria-live="polite">
          {data.total === 0
            ? "Sin resultados"
            : `${formatNumber(data.total)} ${
                data.total === 1 ? "cliente" : "clientes"
              }`}
          {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((c) => (
              <CustomerRow key={c.id} c={c} />
            ))}
          </div>
          {data && data.pageCount > 1 && (
            <Pager
              page={data.page}
              pageCount={data.pageCount}
              onChange={goToPage}
            />
          )}
        </>
      )}
    </>
  );
}

function StatStrip({ stats }: { stats: CustomerStats | null }) {
  const cells: {
    value: string;
    label: string;
    accent?: boolean;
  }[] = stats
    ? [
        { value: formatNumber(stats.customers), label: "Clientes", accent: true },
        { value: formatNumber(stats.withUtilities), label: "Con servicios" },
        { value: formatNumber(stats.withInsurance), label: "Con seguros" },
        { value: formatNumber(stats.bothLines), label: "Ambas líneas", accent: true },
        { value: formatNumber(stats.policies), label: "Pólizas" },
        { value: formatNumber(stats.properties), label: "Propiedades" },
      ]
    : [];

  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>
    );
  }

  return (
    <div className="stat-strip">
      {cells.map((c) => (
        <div
          className={`stat-cell${c.accent ? " accent" : ""}`}
          key={c.label}
        >
          <div className="stat-value">{c.value}</div>
          <div className="stat-label">{c.label}</div>
        </div>
      ))}
    </div>
  );
}

function CustomerRow({ c }: { c: CustomerListItem }) {
  const location = [c.city?.replace(/,\s*$/, ""), c.state]
    .filter(Boolean)
    .join(", ");
  const contact = c.phone || c.mobile || c.email;

  return (
    <Link href={`/clientes/${c.id}`} className="cust-row">
      <div className="cust-main">
        <div className="cust-name">
          {!c.status && (
            <span className="inactive-dot" title="Inactivo" aria-hidden />
          )}
          <span className={c.name === SIN_NOMBRE ? "cust-name-missing" : undefined}>
            {c.name}
          </span>
          {c.nameSource && (
            <span
              className="name-source"
              title={`El registro original no tenía nombre. Recuperado de ${c.nameSource}.`}
            >
              nombre recuperado
            </span>
          )}
        </div>
        <div className="cust-sub">
          {location && <span>{location}</span>}
          {location && contact && <span className="sep">·</span>}
          {contact && <span>{contact}</span>}
        </div>
      </div>
      <div className="cust-side">
        {c.hasUtilities && (
          <span className="badge badge-servicios">
            <span className="dot" /> Servicios
            {c.propertyCount > 0 && (
              <span className="badge-count">· {c.propertyCount}</span>
            )}
          </span>
        )}
        {c.hasInsurance && (
          <span className="badge badge-seguros">
            <span className="dot" /> Seguros
            {c.policyCount > 0 && (
              <span className="badge-count">· {c.policyCount}</span>
            )}
          </span>
        )}
      </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 clientes para “${query}”.`
          : "No hay clientes que coincidan con el filtro."}
      </p>
    </div>
  );
}
