/**
 * recoSearch.js
 *
 * BUT: Optionnel.
 * - Si tu veux que le frontend fasse une "suggestion/recherche" via Rico,
 *   FAIS-LE via le core-api (BFF), pas direct vers Rico.
 *
 * IMPORTANT:
 * - Si tu n'importes pas ce fichier, rien ne change dans ton UI.
 * - Ton search bar actuelle filtre déjà localement (0 call réseau).
 */

function apiPrefix() {
  const raw =
    (import.meta?.env?.VITE_API_BASE_URL || "")
      .toString()
      .replace(/\/+$/, "");
  if (raw) return raw + "/api";
  try {
    if (typeof window !== "undefined") {
      const host = window.location.hostname || "";
      if (host.startsWith("www.")) {
        return `https://${host.replace(/^www\./, "")}/api`;
      }
    }
  } catch {}
  return "/api";
}

const DEFAULT_PATHS = [
  "/suggestions",       // FAST: Meilisearch autocomplete (cities, posts, profiles) - PRIMARY
  "/unified-search",    // Fallback: Unified search (posts + profiles + places)
  "/search",            // Fallback: Posts only
  "/reco/search",
  "/reco/suggest",
  "/recommendations/search",
];

const searchCache = new Map();

function cacheGet(query) {
  const key = query.toLowerCase().trim();
  const hit = searchCache.get(key);
  if (!hit) return null;
  if (hit.expiresAt <= Date.now()) {
    searchCache.delete(key);
    return null;
  }
  return hit.value;
}

function cacheSet(query, value, ttlMs) {
  const key = query.toLowerCase().trim();
  if (!key) return;
  searchCache.set(key, { value, expiresAt: Date.now() + ttlMs });
}

/**
 * Normalise un item venant du core-api.
 * On reste permissif: Rico / core-api peut renvoyer plusieurs shapes.
 */
function normalizeOne(r) {
  if (!r || typeof r !== "object") return null;

  const title =
    (r.title ?? r.name ?? r.label ?? r.display_name ?? r.disp ?? r.text ?? "")
      .toString()
      .trim();

  // coords possibles (support multiple formats)
  const lat = typeof r.lat === "number" ? r.lat : (typeof r.latitude === "number" ? r.latitude : null);
  const lon = typeof r.lon === "number" ? r.lon : (typeof r.lng === "number" ? r.lng : null);

  const coords =
    Array.isArray(r.coords) && r.coords.length === 2
      ? r.coords
      : (lat != null && lon != null ? [lon, lat] : null);

  const type = (r.type ?? r.kind ?? r.entity ?? "").toString().toLowerCase().trim();
  const hasPostSignal =
    !!(r.category ||
       r.sub_category ||
       r.subCategory ||
       r.author ||
       r.snippet ||
       r.body ||
       r.content ||
       r.url ||
       r.cluster_key ||
       r.clusterKey ||
       r.template ||
       r.source);
  const kind =
    type ||
    (hasPostSignal ? "post" : coords ? "place" : "item");
  const tags =
    Array.isArray(r.event_tags)
      ? r.event_tags
      : Array.isArray(r.tags)
      ? r.tags
      : [];

  const postID =
    typeof r.post_id === "number" && r.post_id > 0
      ? r.post_id
      : typeof r.postId === "number" && r.postId > 0
      ? r.postId
      : null;

  return {
    id: (postID ?? r.id ?? r._id ?? r.key ?? title).toString(),
    type: kind,
    kind: kind,  // Keep both for compatibility
    title,
    subtitle: (r.subtitle ?? r.sub ?? r.extra ?? r.category ?? "").toString(),
    coords,
    lat,
    lon,
    tags,
    post_id: postID,
    raw: r,
  };
}

/**
 * Tente une recherche sur une liste de paths (au cas où le endpoint exact diffère).
 * Retourne [] sur 404/erreur.
 */
async function tryFetchAnyPath(q, { signal, limit } = {}) {
  const query = (q || "").toString().trim();
  const isEmptyQuery = query === "";
  const maxResults = limit && limit > 0 ? limit : 12;
  const cached = cacheGet(query);
  if (cached) return cached;

  // Permet override runtime si tu veux:
  // window.__SW_RECO_SEARCH_PATH = "/api/reco/search"
  const override =
    typeof window !== "undefined" && window.__SW_RECO_SEARCH_PATH
      ? String(window.__SW_RECO_SEARCH_PATH)
      : "";

  const prefix = apiPrefix();
  const basePaths = isEmptyQuery ? ["/suggestions"] : DEFAULT_PATHS;
  const paths = override ? [override, ...basePaths] : basePaths;
  const posts = [];
  const locations = [];
  const profiles = [];
  const seen = new Set();
  const seenPostIDs = new Set();
  const minLocationResults = Math.min(2, maxResults);
  const locationKinds = new Set([
    "place", "city", "region", "province", "state",
    "country", "area", "district", "poi", "venue", "location",
  ]);
  for (const p of paths) {
    try {
      const base = p.startsWith("http") ? p : `${prefix}${p}`;
      const url = `${base}?q=${encodeURIComponent(query)}`;
      const res = await fetch(url, { credentials: "include", signal });

      if (res.status === 404) {
        continue; // Try next path
      }
      if (!res.ok) {
        return []; // Avoid spam errors
      }
      const data = await res.json().catch(() => null);

      const arr = Array.isArray(data)
        ? data
        : Array.isArray(data?.items)
        ? data.items
        : Array.isArray(data?.results)
        ? data.results
        : [];

      if (arr.length === 0) {
        continue; // Try next path
      }

      const normalized = arr.map(normalizeOne).filter(Boolean);
      if (normalized.length === 0) {
        continue; // Try next path
      }

      for (const it of normalized) {
        const rawPostID =
          typeof it.post_id === "number" && it.post_id > 0
            ? it.post_id
            : typeof it.raw?.post_id === "number" && it.raw.post_id > 0
            ? it.raw.post_id
            : typeof it.raw?.postId === "number" && it.raw.postId > 0
            ? it.raw.postId
            : null;
        if (rawPostID && seenPostIDs.has(rawPostID)) continue;
        if (seen.has(it.id)) continue;
        seen.add(it.id);
        if (rawPostID) seenPostIDs.add(rawPostID);
        const kind = (it.kind || "").toLowerCase();
        if (locationKinds.has(kind)) {
          locations.push(it);
        } else if (kind === "profile") {
          profiles.push(it);
        } else {
          posts.push(it);
        }
      }

      const totalCollected = posts.length + locations.length + profiles.length;
      if (totalCollected >= maxResults && locations.length >= minLocationResults) {
        break; // Collected enough results
      }
    } catch (e) {
      // Abort => stop network calls
      if (e && (e.name === "AbortError" || e.code === 20)) {
        return [];
      }
      // Other errors => try next path
      continue;
    }
  }

  const totalCollected = posts.length + locations.length + profiles.length;
  if (totalCollected === 0) {
    return [];
  }
  const locationSlots = Math.min(minLocationResults, locations.length);
  const initialResults = [
    ...locations.slice(0, locationSlots),
    ...posts,
    ...locations.slice(locationSlots),
    ...profiles,
  ];
  const resultSlice = initialResults.slice(0, maxResults);
  cacheSet(query, resultSlice, 30 * 1000);
  return resultSlice;
}

/**
 * recoSearch(query): renvoie une liste normalisée.
 * - "safe" : retourne [] si rien marche.
 */
export async function recoSearch(query, opts = {}) {
  return tryFetchAnyPath(query, opts);
}
