import { SearchResult } from '../types/source.js';
import { CONFIG } from './config.js';

// Cache (CleanTitle+Type => TmdbData)
interface TmdbData {
    year: string | null;
    title: string;
    image: string | null;
}

const tmdbCache = new Map<string, TmdbData | null>();
const MAX_CACHE_SIZE = 500;

function enforceCacheLimit() {
    if (tmdbCache.size > MAX_CACHE_SIZE) {
        let i = 0;
        for (const key of tmdbCache.keys()) {
            tmdbCache.delete(key);
            if (++i > 50) break; // Remove oldest 50
        }
    }
}

export function clearTmdbCache() {
    tmdbCache.clear();
    console.log("[TMDB] Cache réinitialisé.");
}

export function cleanTitle(title: string): string {
    // Décode les entités HTML fréquentes
    let clean = title.replace(/&#039;|&#39;/g, "'")
                     .replace(/&quot;/g, '"')
                     .replace(/&amp;/g, '&')
                     .replace(/&lt;/g, '<')
                     .replace(/&gt;/g, '>');

    clean = clean.replace(/\b(saison|season)\s*\d+.*$/i, '');
    clean = clean.replace(/\b(complete|french|truefrench|vostfr|multi|web-dl|1080p|720p|4k|x265|x264|bluray|bdrip)\b/gi, '');
    clean = clean.replace(/,\s*le film\b/i, '');
    clean = clean.replace(/[-_\[\]\(\):]/g, ' ');
    clean = clean.replace(/\s{2,}/g, ' ');
    return clean.trim();
}

async function fetchTmdbData(title: string, type: string): Promise<TmdbData | null> {
    if (!CONFIG.TMDB_ENABLED || !CONFIG.TMDB_API_KEY) return null;
    
    const clean = cleanTitle(title);
    if (!clean) return null;

    const searchType = (type === 'series' || type === 'serie' || type === 'anime') ? 'tv' : 'movie';
    const cacheKey = `${searchType}:${clean.toLowerCase()}`;

    if (tmdbCache.has(cacheKey)) {
        return tmdbCache.get(cacheKey)!;
    }

    try {
        console.log(`[TMDB] Recherche API: Type "${searchType}", Requête "${clean}" (Original: "${title}")`);
        const url = `https://api.themoviedb.org/3/search/${searchType}?api_key=${CONFIG.TMDB_API_KEY}&query=${encodeURIComponent(clean)}&language=fr-FR&page=1`;
        const res = await fetch(url, { signal: AbortSignal.timeout(3000) });
        if (!res.ok) {
            console.error(`[TMDB] Erreur HTTP ${res.status} pour "${clean}"`);
            return null;
        }
        const data = await res.json();
        let resultData: TmdbData | null = null;
        
        if (data.results && data.results.length > 0) {
            const first = data.results[0];
            const dateStr = searchType === 'tv' ? first.first_air_date : first.release_date;
            const year = (dateStr && typeof dateStr === 'string') ? dateStr.substring(0, 4) : null;
            const tmdbTitle = searchType === 'tv' ? first.name : first.title;
            const image = first.poster_path ? `https://image.tmdb.org/t/p/w300${first.poster_path}` : null;
            
            resultData = { year, title: tmdbTitle, image };
            console.log(`[TMDB] ✅ Trouvé "${clean}" -> ${tmdbTitle} (${year || 'N/A'})`);
        } else {
            console.log(`[TMDB] ❌ Aucun résultat pour "${clean}" en tant que ${searchType}.`);
            // Fallback: search as the opposite type
            const fallbackType = searchType === 'movie' ? 'tv' : 'movie';
            console.log(`[TMDB] 🔄 Fallback: recherche "${clean}" en tant que ${fallbackType}...`);
            const fallbackUrl = `https://api.themoviedb.org/3/search/${fallbackType}?api_key=${CONFIG.TMDB_API_KEY}&query=${encodeURIComponent(clean)}&language=fr-FR&page=1`;
            const fbRes = await fetch(fallbackUrl, { signal: AbortSignal.timeout(3000) });
            if (fbRes.ok) {
                const fbData = await fbRes.json();
                if (fbData.results && fbData.results.length > 0) {
                    const first = fbData.results[0];
                    const dateStr = fallbackType === 'tv' ? first.first_air_date : first.release_date;
                    const year = (dateStr && typeof dateStr === 'string') ? dateStr.substring(0, 4) : null;
                    const tmdbTitle = fallbackType === 'tv' ? first.name : first.title;
                    const image = first.poster_path ? `https://image.tmdb.org/t/p/w300${first.poster_path}` : null;
                    
                    resultData = { year, title: tmdbTitle, image };
                    console.log(`[TMDB] ✅ Trouvé (Fallback) "${clean}" -> ${tmdbTitle} (${year || 'N/A'})`);
                }
            }
        }
        
        enforceCacheLimit();
        tmdbCache.set(cacheKey, resultData);
        return resultData;
    } catch (e) {
        console.error(`[TMDB] ❌ Erreur recherche pour "${clean}":`, (e as Error).message);
        return null;
    }
}

export async function enrichSearchResults(results: SearchResult[]): Promise<SearchResult[]> {
    if (!CONFIG.TMDB_ENABLED || !CONFIG.TMDB_API_KEY) return results;

    const enrichmentPromises = results.map(async (r) => {
        // We now enrich ALWAYS, not just when !r.year, so ZT benefits from it.
        const tmdbData = await fetchTmdbData(r.title, r.type || 'movie');
        if (tmdbData) {
            if (tmdbData.year) r.year = tmdbData.year;
            if (tmdbData.image) r.image = tmdbData.image;
            // Clean up original title by removing the HTML entities if TMDB didn't return a title
            r.title = tmdbData.title || cleanTitle(r.title);
        } else {
            // Still decode HTML entities if TMDB fails
            r.title = cleanTitle(r.title);
        }
        return r;
    });

    await Promise.allSettled(enrichmentPromises);
    return results;
}
