// Cliente del backend FastAPI de Leads (puerto 8001).
const BASE_URL = "http://localhost:8001";

// ── Cache en memoria (frontend) con TTL 15 min y "stale-while-revalidate" ──
// Guarda la respuesta de cada GET (por path+params). Al volver a pedir:
//   - si hay dato vigente (< 15 min) -> lo devuelve al instante, SIN fetch.
//   - si venció -> devuelve el viejo al instante Y refresca en 2º plano.
// Así, al cambiar de apartado y volver, NO se recarga; y a los 15 min se
// actualiza solo sin mostrar loader. Los POST invalidan el cache.
const TTL = 15 * 60 * 1000;                 // 15 minutos
const _cache = new Map();                   // key -> { ts, data }
const _enVuelo = new Map();                 // key -> Promise (evita fetch duplicado)

function _key(path, params) {
  return path + "?" + new URLSearchParams(params).toString();
}

async function _fetch(path, params) {
  const qs = new URLSearchParams(params).toString();
  const r = await fetch(`${BASE_URL}${path}${qs ? "?" + qs : ""}`);
  if (!r.ok) throw new Error(`Error ${r.status} en ${path}`);
  return r.json();
}

// GET con cache. Devuelve SIEMPRE una promesa que resuelve rápido si hay cache.
function get(path, params = {}) {
  const key = _key(path, params);
  const hit = _cache.get(key);
  const now = Date.now();

  if (hit) {
    // Hay algo cacheado -> devolverlo YA.
    if (now - hit.ts >= TTL && !_enVuelo.has(key)) {
      // Venció: refrescar en 2º plano (no bloquea, no muestra loader).
      const p = _fetch(path, params)
        .then((data) => { _cache.set(key, { ts: Date.now(), data }); return data; })
        .finally(() => _enVuelo.delete(key));
      _enVuelo.set(key, p);
    }
    return Promise.resolve(hit.data);
  }

  // No hay cache: si ya hay una petición en vuelo para esta key, reusarla.
  if (_enVuelo.has(key)) return _enVuelo.get(key);

  const p = _fetch(path, params)
    .then((data) => { _cache.set(key, { ts: Date.now(), data }); return data; })
    .finally(() => _enVuelo.delete(key));
  _enVuelo.set(key, p);
  return p;
}

// Invalida entradas del cache cuyo path empiece con alguno de los prefijos dados.
function invalidar(...prefijos) {
  for (const k of _cache.keys()) {
    if (prefijos.some((p) => k.startsWith(p))) _cache.delete(k);
  }
}

// POST helper: hace el POST y luego invalida los caches afectados.
async function post(path, body, invalidarPrefijos = []) {
  const r = await fetch(`${BASE_URL}${path}`, {
    method: "POST", headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  if (!r.ok) throw new Error(`Error al guardar en ${path}`);
  const data = await r.json();
  if (invalidarPrefijos.length) invalidar(...invalidarPrefijos);
  return data;
}

export const api = {
  leadsFiltros: () => get("/api/leads/filtros"),
  leads: (ano = "TODOS", mes = "TODOS", dia = "TODOS", programa = "TODOS", sede = "TODOS") =>
    get("/api/leads", { ano, mes, dia, programa, sede }),
  otrosGeneral: (ano = "TODOS", mes = "TODOS", dia = "TODOS") =>
    get("/api/otros-general", { ano, mes, dia }),
  vendedores: (ano = "TODOS", mes = "TODOS", dia = "TODOS") =>
    get("/api/vendedores", { ano, mes, dia }),
  roas: (ano = "TODOS", mes = "TODOS", dia = "TODOS") =>
    get("/api/roas", { ano, mes, dia }),
  conjuntosSinSede: () => get("/api/conjuntos-sin-sede"),
  guardarConjuntoSede: (cambios) =>
    post("/api/conjuntos-sin-sede/guardar", { cambios }, ["/api/conjuntos-sin-sede", "/api/roas"]),
  borrarConjuntoSede: (conjunto) =>
    post("/api/conjuntos-sin-sede/borrar", { conjunto }, ["/api/conjuntos-sin-sede", "/api/roas"]),
  ultimaActualizacion: () => get("/api/ultima-actualizacion"),
  // Actualiza TODO manualmente (como si pasaran los 15 min), pero EN SEGUNDO
  // PLANO: NO se toca el cache del cliente mientras el backend trabaja, así el
  // usuario sigue viendo los datos viejos sin pantallas de carga durante los
  // ~29s. Recien cuando el backend responde OK se limpia el cache del cliente,
  // para que a partir de ahi todo muestre los datos nuevos de inmediato.
  refrescarTodo: async () => {
    const r = await fetch(`${BASE_URL}/api/cache/refresh`, { method: "POST" });
    if (!r.ok) throw new Error("Error al actualizar");
    await r.json();               // espera a que el backend TERMINE de rehacer todo
    _cache.clear();               // solo AHORA se invalida el cache del cliente
    // Trae la hora de actualizacion FRESCA (sin cache) y la deja cacheada, para
    // que el sidebar muestre la hora del refresco manual recien hecho.
    const hr = await _fetch("/api/ultima-actualizacion", {});
    _cache.set(_key("/api/ultima-actualizacion", {}), { ts: Date.now(), data: hr });
    return hr;                     // { hora: "..." }
  },
  conjuntosSinPauta: () => get("/api/conjuntos-sin-pauta"),
  usoPauta: (pauta, excluir) => get("/api/pauta/uso", { pauta, excluir: excluir || "" }),
  leyendaAnuncios: () => get("/api/leyenda-anuncios"),
  programasDisponibles: () => get("/api/programas-disponibles"),
  programasOcultos: () => get("/api/programas-ocultos"),
  encenderProgramas: (num_indices) =>
    post("/api/programas-ocultos/encender", { num_indices },
         ["/api/programas-ocultos", "/api/programas-disponibles", "/api/leads"]),
  guardarLeyenda: (cambios) =>
    post("/api/leyenda-anuncios/guardar", { cambios }, ["/api/leyenda-anuncios", "/api/roas"]),
  guardarPauta: (num_indice, pauta, conjunto, contar) =>
    post("/api/curso/guardar-pauta", { num_indice, pauta, conjunto, contar },
         ["/api/leads", "/api/conjuntos-sin-pauta", "/api/roas"]),
  alertas: () => get("/api/leads/alertas"),
  // Leyenda (campanias de Supabase). Al agregar/borrar, invalida TODOS los
  // apartados que dependen de las leyendas para que el cambio se vea al instante.
  campanias: () => get("/api/campanias"),
  agregarCampania: (datos) =>
    post("/api/campanias/agregar", datos,
         ["/api/campanias", "/api/leads", "/api/vendedores", "/api/roas", "/api/otros-general"]),
  editarCampania: (id, datos) =>
    post("/api/campanias/editar", { id, ...datos },
         ["/api/campanias", "/api/leads", "/api/vendedores", "/api/roas", "/api/otros-general"]),
  borrarCampania: (id) =>
    post("/api/campanias/borrar", { id },
         ["/api/campanias", "/api/leads", "/api/vendedores", "/api/roas", "/api/otros-general"]),
};
