import { useCallback, useEffect, useRef, useState } from "react";

/**
 * Contador de consultas de la lista de precios.
 *
 * Una sola clave de localStorage compartida por los tres lugares desde donde se
 * consulta (lista de autos, lista de camiones y el widget del home), para que el
 * límite no se pueda esquivar saltando de uno a otro.
 *
 * Es un freno blando: se esquiva en una ventana de incógnito. Es a propósito —
 * un bloqueo real necesitaría cuentas de usuario en el sitio público.
 */

const STORAGE_KEY = "cca_price_list_usage";

type GateConfig = { maxQueries: number; windowHours: number };
type Usage = { count: number; windowStart: number };

const readUsage = (): Usage | null => {
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (typeof parsed?.count !== "number" || typeof parsed?.windowStart !== "number") {
      return null;
    }
    return parsed as Usage;
  } catch {
    // Modo privado o storage bloqueado: se trata como "sin consultas previas".
    return null;
  }
};

const writeUsage = (usage: Usage): void => {
  try {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(usage));
  } catch {
    // Si no se puede escribir, el usuario no queda bloqueado. Preferimos eso
    // antes que romperle la consulta.
  }
};

/** Consultas usadas dentro de la ventana vigente. Si venció, arranca de cero. */
const usedInWindow = (usage: Usage | null, windowHours: number): number => {
  if (!usage) return 0;
  const elapsed = Date.now() - usage.windowStart;
  return elapsed >= windowHours * 3600 * 1000 ? 0 : usage.count;
};

const usePriceListGate = () => {
  const [config, setConfig] = useState<GateConfig | null>(null);
  const [gateOpen, setGateOpen] = useState(false);
  const configRef = useRef<GateConfig | null>(null);

  // La config viene del server para poder cambiarla sin rebuildear.
  useEffect(() => {
    let cancelled = false;

    fetch("/api/price-list-config")
      .then((res) => (res.ok ? res.json() : null))
      .then((data) => {
        if (cancelled || !data) return;
        const next: GateConfig = {
          maxQueries: Number(data.maxQueries),
          windowHours: Number(data.windowHours),
        };
        configRef.current = next;
        setConfig(next);
      })
      .catch(() => {
        // Si la config no carga, no bloqueamos a nadie.
        configRef.current = null;
      });

    return () => {
      cancelled = true;
    };
  }, []);

  /**
   * Registra una consulta. Devuelve true si se puede seguir adelante.
   * Si ya se agotó el cupo devuelve false y abre la pantalla de bloqueo,
   * sin llegar a pegarle a la API.
   */
  const consume = useCallback((): boolean => {
    const cfg = configRef.current;

    // Sin config todavía (o falló): dejamos pasar.
    if (!cfg || typeof window === "undefined") return true;

    const usage = readUsage();
    const used = usedInWindow(usage, cfg.windowHours);

    if (used >= cfg.maxQueries) {
      setGateOpen(true);
      return false;
    }

    writeUsage({
      count: used + 1,
      // La ventana arranca con la primera consulta y no se renueva con cada una.
      windowStart: used === 0 ? Date.now() : (usage as Usage).windowStart,
    });

    return true;
  }, []);

  const closeGate = useCallback(() => setGateOpen(false), []);

  return { config, gateOpen, consume, closeGate };
};

export default usePriceListGate;
