// Enriquecimiento TMDB para items Xtream: matchea por TÍTULO y trae artwork,
// sinopsis, rating, géneros y tmdbId. El VIDEO sigue siendo del Xtream.
import { searchMedia } from "./tmdb";
import type { MediaItem } from "./types";

const JUNK = /\b(4k|uhd|hd|fhd|sd|hevc|h265|h264|x265|x264|web[- ]?dl|webrip|bluray|bdrip|hdrip|dvdrip|remux|dual|latino|lat|castellano|espanol|español|ingles|english|sub|subs|subtitulad[oa]s?|vose|vos|vo|multi|audio|extended|remasterizada|remastered)\b/gi;

export function cleanTitle(raw: string): string {
  let t = raw || "";
  t = t.replace(/\([^)]*\)/g, " ").replace(/\[[^\]]*\]/g, " ").replace(/\{[^}]*\}/g, " ");
  t = t.replace(/^\s*\d{1,3}[\s.\-)]+/, " ");
  t = t.replace(/\bS\d{1,2}\s?E\d{1,3}\b/gi, " ");
  t = t.replace(/\b(temporada|season|cap(?:itulo)?|ep(?:isodio)?|t)\s?\d{1,3}\b/gi, " ");
  t = t.replace(/\b(19|20)\d{2}\b/g, " ").replace(JUNK, " ");
  t = t.replace(/[-_:.|•·–—]+/g, " ").replace(/\s+/g, " ").trim();
  return t || (raw || "").trim();
}

// Normaliza para comparar títulos (sin acentos, signos ni espacios extra).
function norm(s: string): string {
  return (s || "").toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "");
}

const cache = new Map<string, MediaItem | null>();

function yearOf(r: { year?: string; releaseDate?: string | null }): number {
  return Number(String(r.year || r.releaseDate || "").slice(0, 4)) || 0;
}

// Busca el tmdbId correcto para un item Xtream usando TÍTULO + AÑO. Devuelve
// solo el match (para backdrop/logo/cast); NUNCA cambia el título del servidor.
async function findMatch(item: MediaItem): Promise<MediaItem | null> {
  const clean = cleanTitle(item.title);
  const key = `${item.mediaType}:${clean.toLowerCase()}:${(item.year || "").slice(0, 4)}`;
  const cached = cache.get(key);
  if (cached !== undefined) return cached;
  const target = norm(clean);
  let match: MediaItem | null = null;
  if (target.length >= 2) {
    const results = await searchMedia(clean).catch(() => []);
    const same = results.filter((r) => r.mediaType === item.mediaType && norm(r.title));
    const pool = same.length ? same : results.filter((r) => norm(r.title));
    const yr = Number((item.year || "").slice(0, 4)) || 0;
    const titleOk = (r: MediaItem) => { const t = norm(r.title); return t === target || t.startsWith(target) || target.startsWith(t) || (target.length >= 5 && (t.includes(target) || target.includes(t))); };
    const yrOk = (r: MediaItem) => yr && Math.abs(yearOf(r) - yr) <= 1;
    match =
      // 1) título coincide Y el año coincide → lo más confiable
      (yr ? pool.find((r) => titleOk(r) && yrOk(r)) : undefined) ??
      // 2) TMDB devuelve títulos traducidos (ej. "Red Notice"→"Alerta roja"): el
      //    primer resultado relevante (top 4) cuyo AÑO coincide es el correcto.
      (yr ? pool.slice(0, 4).find((r) => yrOk(r)) : undefined) ??
      // 3) título EXACTO
      pool.find((r) => norm(r.title) === target) ??
      // 4) título aproximado
      pool.find((r) => titleOk(r)) ??
      null;
  }
  cache.set(key, match);
  return match;
}

// Enriquece un item Xtream: CONSERVA título/póster/sinopsis del servidor (siempre
// correctos) y añade de TMDB el fondo (backdrop), géneros y el tmdbId (para logo).
export async function tmdbEnrich(item: MediaItem): Promise<MediaItem> {
  if (!item.xtream) return item;
  const match = await findMatch(item);
  if (!match) return item;
  return {
    ...item,
    tmdbId: match.id,
    backdrop: match.backdrop || item.backdrop,
    image: item.image || match.image,
    overview: item.overview || match.overview,
    rating: item.rating || match.rating,
    genres: match.genres ?? item.genres,
    genreIds: match.genreIds ?? item.genreIds
  };
}

/** Detalle COMPLETO: datos del servidor (título/póster/sinopsis) + fondo/cast/temporadas de TMDB. */
export async function enrichFull(item: MediaItem): Promise<MediaItem> {
  const match = await findMatch(item);
  if (!match) return item;
  const { getDetails } = await import("./tmdb");
  const full = await getDetails({ ...item, id: match.id }).catch(() => null);
  if (!full) return { ...item, tmdbId: match.id, backdrop: match.backdrop || item.backdrop };
  // full = datos TMDB del match (backdrop, cast, géneros, temporadas). Pero el
  // TÍTULO, PÓSTER y SINOPSIS se quedan los del SERVIDOR (correctos).
  return {
    ...full,
    id: item.id,
    mediaType: item.mediaType,
    xtream: item.xtream,
    tmdbId: match.id,
    title: item.title,
    image: item.image || full.image,
    overview: item.overview || full.overview,
    year: item.year || full.year
  };
}
