"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,
  getPropertyFacets,
  getPropertyStats,
  listProperties,
} from "@/lib/api";
import {
  expiryPhrase,
  formatDate,
  formatNumber,
  serviceKindGlyph,
  serviceKindLabel,
  SIN_NOMBRE,
  trustStatusLabel,
} from "@/lib/labels";
import type {
  PropertyFacets,
  PropertyListItem,
  PropertyListResponse,
  PropertySort,
  PropertyStats,
  ServiceKind,
} from "@/lib/types";

/**
 * The buckets staff actually work from. Trust (fideicomiso) renewals are the
 * recurring deadline in this line of business, so they get first-class filters
 * next to the "nothing enrolled yet" bucket that flags incomplete records.
 */
type Focus = "all" | "trust" | "expiring" | "expired" | "no_services";

const FOCUS_FILTERS: { key: Focus; label: string }[] = [
  { key: "all", label: "Todas" },
  { key: "expiring", label: "Fideicomiso por vencer" },
  { key: "expired", label: "Fideicomiso vencido" },
  { key: "trust", label: "Con fideicomiso" },
  { key: "no_services", label: "Sin servicios" },
];

const SORTS: { key: PropertySort; label: string }[] = [
  { key: "customer", label: "Cliente (A–Z)" },
  { key: "address", label: "Dirección (A–Z)" },
  { key: "services_desc", label: "Más servicios" },
  {
    key: "trust_due_asc",
    label: "Vencimiento de fideicomiso (solo con fideicomiso)",
  },
  {
    key: "trust_due_desc",
    label: "Vencimiento más lejano (solo con fideicomiso)",
  },
];

/** Focus bucket → the query the API understands. */
function focusQuery(focus: Focus) {
  switch (focus) {
    case "trust":
      return { trust: "with" as const };
    case "expiring":
      return { trust: "expiring" as const };
    case "expired":
      return { trust: "expired" as const };
    case "no_services":
      return { hasServices: false };
    default:
      return {};
  }
}

export default function ServiciosPage() {
  return (
    <AppShell>
      <ServiciosBrowser />
    </AppShell>
  );
}

function ServiciosBrowser() {
  const canCreate = useCan("property:create");
  const [stats, setStats] = useState<PropertyStats | null>(null);
  const [facets, setFacets] = useState<PropertyFacets | null>(null);

  const [query, setQuery] = useState("");
  const [focus, setFocus] = useState<Focus>("all");
  const [serviceKind, setServiceKind] = useState<ServiceKind | "">("");
  const [municipality, setMunicipality] = useState("");
  const [bank, setBank] = useState("");
  const [sort, setSort] = useState<PropertySort>("customer");

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

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

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

  const runSearch = useCallback(
    (p: number) => {
      setLoading(true);
      setError(null);
      listProperties({
        query: query || undefined,
        serviceKind: serviceKind || undefined,
        municipality: municipality || undefined,
        bank: bank || undefined,
        sort,
        days: EXPIRY_WINDOW_DAYS,
        page: p,
        pageSize: 25,
        ...focusQuery(focus),
      })
        .then((res) => {
          setData(res);
          setLoading(false);
        })
        .catch((e) => {
          setError(e?.message ?? "No se pudieron cargar las propiedades.");
          setLoading(false);
        });
    },
    [query, focus, serviceKind, municipality, bank, 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]);

  /** Picking a renewal bucket also switches the sort to due-date order —
   *  a list of renewals sorted by customer name isn't a worklist. */
  function pickFocus(f: Focus) {
    setFocus(f);
    if (f === "expiring" || f === "expired") setSort("trust_due_asc");
    else if (sort === "trust_due_asc" || sort === "trust_due_desc")
      setSort("customer");
  }

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

  const filtered =
    query !== "" ||
    focus !== "all" ||
    serviceKind !== "" ||
    municipality !== "" ||
    bank !== "";

  return (
    <>
      <div className="page-head rise">
        <p className="eyebrow">Administración de servicios</p>
        <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
          <h1 className="page-title" style={{ margin: 0 }}>Propiedades</h1>
          <span style={{ flex: 1 }} />
          <ContextReports
            entries={[
              { slug: "faltantes", label: "Faltantes agua", params: { serviceKind: "WATER" } },
              { slug: "faltantes", label: "Faltantes luz", params: { serviceKind: "ELECTRICITY" } },
              { slug: "faltantes", label: "Faltantes tel.", params: { serviceKind: "PHONE" } },
            ]}
          />
          {canCreate && (
            <Link href="/servicios/nuevo" className="btn btn-primary">+ Nueva propiedad</Link>
          )}
        </div>
        <StatStrip stats={stats} focus={focus} onPickFocus={pickFocus} />
        <ServiceMixStrip
          stats={stats}
          serviceKind={serviceKind}
          onPickKind={(k) => setServiceKind(k === serviceKind ? "" : k)}
        />
      </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 dirección, cliente, cuenta, medidor, fideicomiso…"
            aria-label="Buscar propiedades"
          />
        </div>
        <div className="seg" role="tablist" aria-label="Filtrar propiedades">
          {FOCUS_FILTERS.map((f) => (
            <button
              key={f.key}
              type="button"
              role="tab"
              aria-selected={focus === f.key}
              className={`seg-btn ${focus === f.key ? "active" : ""}`}
              onClick={() => pickFocus(f.key)}
            >
              {f.label}
            </button>
          ))}
        </div>
      </div>

      <div className="filter-row">
        <label className="filter-field">
          <span className="filter-label">Servicio</span>
          <select
            className="input select"
            value={serviceKind}
            onChange={(e) => setServiceKind(e.target.value as ServiceKind | "")}
          >
            <option value="">Todos los servicios</option>
            {facets?.kinds.map((k) => (
              <option key={k.kind} value={k.kind}>
                {serviceKindLabel(k.kind)} ({formatNumber(k.count)})
              </option>
            ))}
          </select>
        </label>

        <label className="filter-field">
          <span className="filter-label">Municipio</span>
          <select
            className="input select"
            value={municipality}
            onChange={(e) => setMunicipality(e.target.value)}
          >
            <option value="">Todos los municipios</option>
            {facets?.municipalities.map((m) => (
              <option key={m.name} value={m.name}>
                {m.name} ({formatNumber(m.count)})
              </option>
            ))}
          </select>
        </label>

        <label className="filter-field">
          <span className="filter-label">Banco (fideicomiso)</span>
          <select
            className="input select"
            value={bank}
            onChange={(e) => setBank(e.target.value)}
          >
            <option value="">Todos los bancos</option>
            {facets?.banks.map((b) => (
              <option key={b.name} value={b.name}>
                {b.name} ({formatNumber(b.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 PropertySort)}
          >
            {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("");
              setFocus("all");
              setServiceKind("");
              setMunicipality("");
              setBank("");
              setSort("customer");
            }}
          >
            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 ? "propiedad" : "propiedades"
              }`}
          {query ? ` para “${query}”` : ""}
          {(sort === "trust_due_asc" || sort === "trust_due_desc") &&
            " · solo propiedades con fideicomiso"}
        </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) => (
              <PropertyRow 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,
  focus,
  onPickFocus,
}: {
  stats: PropertyStats | null;
  focus: Focus;
  onPickFocus: (f: Focus) => 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: Focus;
    value: number;
    label: string;
    accent?: boolean;
  }[] = [
    { key: "all", value: stats.properties, label: "Propiedades", accent: true },
    {
      key: "expiring",
      value: stats.trustExpiring,
      label: `Fideicomisos en ${stats.days} días`,
      accent: true,
    },
    { key: "expired", value: stats.trustExpired, label: "Fideicomisos vencidos" },
    { key: "trust", value: stats.trusts, label: "Con fideicomiso" },
    { key: "no_services", value: stats.withoutServices, label: "Sin servicios" },
  ];

  return (
    <div className="stat-strip">
      {cells.map((c) => (
        <button
          type="button"
          key={c.label}
          className={`stat-cell stat-cell-btn${c.accent ? " accent" : ""}${
            focus === c.key ? " selected" : ""
          }`}
          onClick={() => onPickFocus(c.key)}
          aria-pressed={focus === 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.services)}</div>
        <div className="stat-label">Servicios · {formatNumber(stats.owners)} clientes</div>
      </div>
    </div>
  );
}

/** The monthly workload, per service type — also the fastest kind filter. */
function ServiceMixStrip({
  stats,
  serviceKind,
  onPickKind,
}: {
  stats: PropertyStats | null;
  serviceKind: ServiceKind | "";
  onPickKind: (k: ServiceKind) => void;
}) {
  if (!stats || stats.byKind.length === 0) return null;
  return (
    <div className="mix-strip">
      <span className="premium-caption">Servicios administrados</span>
      {stats.byKind.map((k) => (
        <button
          type="button"
          key={k.kind}
          className={`mix-chip${serviceKind === k.kind ? " selected" : ""}`}
          onClick={() => onPickKind(k.kind)}
          aria-pressed={serviceKind === k.kind}
        >
          <span className="mix-glyph" aria-hidden>
            {serviceKindGlyph(k.kind)}
          </span>
          <span className="mix-body">
            <strong>{formatNumber(k.count)}</strong>
            <span className="mix-label">{serviceKindLabel(k.kind)}</span>
          </span>
          {k.active < k.count && (
            <span className="mix-inactive">
              {formatNumber(k.count - k.active)} inactivos
            </span>
          )}
        </button>
      ))}
    </div>
  );
}

function PropertyRow({ p }: { p: PropertyListItem }) {
  const addr = [p.addressLine1, p.addressLine2].filter(Boolean).join(", ");
  const location = [p.customerCity?.replace(/,\s*$/, ""), p.customerState]
    .filter(Boolean)
    .join(", ");
  const phrase = p.trust ? expiryPhrase(p.trust.daysToDue) : null;

  return (
    <Link href={`/servicios/${p.id}`} className="cust-row prop-row">
      <div className="cust-main">
        <div className="cust-name">
          <span>{addr || "Propiedad sin dirección"}</span>
          {p.municipality && (
            <span className="badge badge-servicios">
              <span className="dot" /> {p.municipality}
            </span>
          )}
          {p.trust && (
            <span className={`badge status-${p.trust.status}`}>
              Fideicomiso · {trustStatusLabel(p.trust.status)}
            </span>
          )}
          {p.serviceCount === 0 && (
            <span className="badge badge-neutral">Sin servicios</span>
          )}
        </div>
        <div className="cust-sub">
          <span
            className={
              p.customerName === SIN_NOMBRE ? "cust-name-missing" : undefined
            }
          >
            {p.customerName}
          </span>
          {location && (
            <>
              <span className="sep">·</span>
              <span>{location}</span>
            </>
          )}
          {p.zone && (
            <>
              <span className="sep">·</span>
              <span>Zona {p.zone}</span>
            </>
          )}
          {p.phones.length > 0 && (
            <>
              <span className="sep">·</span>
              <span className="mono">{p.phones[0]}</span>
            </>
          )}
        </div>
      </div>
      <div className="prop-side">
        <div className="svc-chips">
          {p.services.map((s) => (
            <span
              key={s.id}
              className={`svc-chip${s.active ? "" : " inactive"}`}
              title={`${serviceKindLabel(s.kind)}${s.active ? "" : " (inactivo)"}`}
            >
              <span aria-hidden>{serviceKindGlyph(s.kind)}</span>
              <span className="sr-only">{serviceKindLabel(s.kind)}</span>
            </span>
          ))}
          {p.services.length === 0 && <span className="muted">—</span>}
        </div>
        {p.trust?.dueDate2 && (
          <>
            <div className="pol-dates mono">
              Vence {formatDate(p.trust.dueDate2)}
            </div>
            {phrase && (
              <div className={`pol-phrase ${p.trust.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 propiedades para “${query}”.`
          : "No hay propiedades que coincidan con los filtros."}
      </p>
    </div>
  );
}
