import { SearchResult, ContentLinks, VideoLink } from '../../src/types/source.js';


function decodeFnMeta(url: string): { quality?: string; langs?: string[] } {
    try {
        const m = url.match(/[?&]fn=([^&]+)/);
        if (!m) return {};
        const decoded = Buffer.from(decodeURIComponent(m[1]!), 'base64').toString('utf-8');
        const qm = decoded.match(/\[([^\]]+)\]/);
        const quality = qm ? qm[1]!.trim() : undefined;
        // Tout après " - " jusqu'à la fin (typiquement la langue : FRENCH, MULTI, VOSTFR…)
        const lm = decoded.match(/-\s+([A-Za-z]+(?:\s+[A-Za-z]+)?)$/);
        const langs = lm ? [lm[1]!.trim()] : undefined;
        return { quality, langs };
    } catch {
        return {};
    }
}

function detectType(href: string): 'movie' | 'series' | 'anime' {
    if (/[?&]p=serie\b|telecharger-serie|serie-/i.test(href)) return 'series';
    if (/animes?/i.test(href)) return 'anime';
    return 'movie';
}

function absUrl(url: string, baseUrl: string): string {
    if (url.startsWith('http')) return url;
    const cleanedBase = baseUrl.replace(/\/$/, '');
    return cleanedBase + (url.startsWith('/') ? url : '/' + url);
}

/**
 * Strip suffixes de qualité/langue pour dedup par titre normalisé.
 */
function normalizeTitle(title: string): string {
    return title
        .toLowerCase()
        .normalize('NFD').replace(/[̀-ͯ]/g, '')
        .replace(/\b(web-?dl|web-?rip|blu-?ray|hdtv|hdrip|dvdrip|hdlight|truefrench|french|multi(?:langues?)?|vff|vf|vostfr|x264|x265|hevc)\b/g, '')
        .replace(/\b(720p|1080p|2160p|4k|uhd|3d|sd|hd)\b/g, '')
        .replace(/\(\s*\d{4}\s*\)/g, '')
        .replace(/-\s*saison\s*\d+/gi, '')
        .replace(/[^a-z0-9]/g, '');
}

function deduplicateByTitle<T extends { title: string }>(items: T[]): T[] {
    const seen = new Set<string>();
    return items.filter(it => {
        const k = normalizeTitle(it.title);
        if (!k || seen.has(k)) return false;
        seen.add(k);
        return true;
    });
}

/**
 * News utilise la structure DLE classique avec cover_global / cover_infos_title / mainimg
 * sur la home/listing/recherche. On peut donc partager le parser de listing.
 */
export function parseListingHTML(html: string, baseUrl: string): SearchResult[] {
    const results: SearchResult[] = [];
    const coverRegex = /<div class="cover_global"[^>]*>([\s\S]*?)(?=<div class="cover_global"|$)/g;
    let m: RegExpExecArray | null;
    while ((m = coverRegex.exec(html)) !== null) {
        const block = m[1]!;
        const titleMatch = block.match(/<div class="cover_infos_title"[^>]*>\s*<a href="([^"]+)"[^>]*>\s*([^<]+)/);
        if (!titleMatch) continue;
        const href = absUrl(titleMatch[1]!.trim(), baseUrl);
        const title = titleMatch[2]!.trim();
        const imgMatch = block.match(/<img class="mainimg"[^>]*src="([^"]+)"/);
        const image = imgMatch ? absUrl(imgMatch[1]!, baseUrl) : null;
        let year: string | null = null;
        const yearMatch = title.match(/\(\s*(\d{4})\s*\)/) || href.match(/-(\d{4})-/);
        if (yearMatch) {
            year = yearMatch[1];
        }

        results.push({
            title,
            year,
            image,
            hrefPath: href,
            type: detectType(titleMatch[1]!),
            source: 'ztnews',
        });
    }
    return deduplicateByTitle(results);
}

/**
 * Parse la fiche film/série de news.
 * Structure dans <div class="postinfo">:
 *   <div style="color:#XXX">HOST_NAME</div>
 *   <a href="dl-protect.link/SLUG?fn=...&rl=a2">Télécharger</a>     (film)
 *   <a href="dl-protect.link/SLUG?fn=...&rl=b2">Episode N</a>       (série, plusieurs liens)
 */
export function parseContentHTML(html: string, isSeries: boolean): ContentLinks {
    const links: VideoLink[] = [];

    const postMatch = html.match(/<div class="postinfo">([\s\S]*?)<\/div>\s*<\/center>/);
    if (!postMatch) return { links };
    const post = postMatch[1]!;

    // Découper par hôte : chaque hôte est marqué par <div style="font-weight:bold;color:#XXX">HOST</div>
    const hostSplit = post.split(/<div\s+style="font-weight:bold;color:#[0-9a-fA-F]+">([^<]+)<\/div>/);
    // hostSplit[0] = pre-section, puis alterne (HOST, BLOCK)
    for (let i = 1; i < hostSplit.length; i += 2) {
        const host = hostSplit[i]!.trim();
        const block = hostSplit[i + 1] || '';
        // Tous les <a href="dl-protect.link..."> dans cette section
        const linkRegex = /<a[^>]+href="(https?:\/\/dl-protect\.link\/[0-9a-fA-F]+\?[^"]*?rl=[ab]2[^"]*)"[^>]*>([^<]+)<\/a>/g;
        let lm: RegExpExecArray | null;
        while ((lm = linkRegex.exec(block)) !== null) {
            const url = lm[1]!;
            const label = lm[2]!.trim();
            const epMatch = label.match(/Episode\s*(\d+|FiNAL|Final|final)/i);
            const meta = decodeFnMeta(url);
            
            let quality = meta.quality || 'Inconnu';
            let langs: string[] = [];
            let subs: string[] = [];
            
            const textToScan = `${quality} ${label}`;
            const langMatch = textToScan.match(/\b(MULTI(?:LANGUES?)?|TRUEFRENCH|FRENCH|VOSTFR|VFF|VF)\b/gi);
            if (langMatch) {
                const seenLangs = new Set<string>();
                const seenSubs = new Set<string>();
                langMatch.forEach(l => {
                    const up = l.toUpperCase();
                    if (up.includes('VOSTFR')) { seenLangs.add('VOSTFR'); seenSubs.add('French'); }
                    else if (up.includes('TRUEFRENCH')) seenLangs.add('TrueFrench');
                    else if (up.includes('FRENCH') || up === 'VF' || up === 'VFF') seenLangs.add('French');
                    else if (up.includes('MULTI')) { seenLangs.add('MULTI'); seenSubs.add('Multi'); }
                });
                langs = Array.from(seenLangs);
                subs = Array.from(seenSubs);
                
                quality = quality.replace(/\b(MULTI(?:LANGUES?)?|TRUEFRENCH|FRENCH|VOSTFR|VFF|VF)\b/gi, '').trim();
            }
            
            quality = quality.replace(/[\(\)\[\]\-]+$/g, '').replace(/[\(\)\[\]]/g, '').replace(/\s+/g, ' ').trim();
            if (!quality || quality.toLowerCase() === 'inconnu') quality = 'WEB';

            links.push({
                id: url,
                host: host.toLowerCase(),
                label: isSeries ? `${label} — ${host}` : host,
                episode: epMatch ? epMatch[1] : undefined,
                quality: quality,
                langs: langs,
                subs: subs,
                url: null,
            });
        }
    }

    return { links };
}

/**
 * Extrait les autres versions/qualités du film depuis la section "Qualités également disponibles".
 */
export function parseOtherVersions(html: string, baseUrl: string): { label: string; value: string }[] {
    const out: { label: string; value: string }[] = [];
    const sectionMatch = html.match(/<div class="otherversions"[\s\S]*?<\/div>/);
    if (!sectionMatch) return out;
    const linkRegex = /<a\s+href="([^"]+)"[^>]*>\s*<span class="otherquality">([\s\S]*?)<\/span>\s*<\/a>/g;
    let m: RegExpExecArray | null;
    while ((m = linkRegex.exec(sectionMatch[0])) !== null) {
        const href = absUrl(m[1]!, baseUrl);
        const label = m[2]!.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();
        if (label && !out.find(o => o.value === href)) out.push({ label, value: href });
    }
    return out;
}
