import { ISource, SearchResult, MediaType, ContentLinks, SelectionData } from '../../src/types/source.js';
import { CONFIG } from '../../src/utils/config.js';
import { sourceRegistry } from '../../src/core/registry.js';
import { fetchSearchResults, fetchTrendingMovies, fetchTrendingSeries, fetchContentPage, fetchResolvedLink, fetchRecent } from './api.js';
import { parseSearchHTML, parseContentHTML, extractLinkFromZtProtect } from './parser.js';

/**
 * Normalise un titre pour la comparaison (minuscules, sans accents, sans ponctuation).
 */
function normalizeTitle(title: string): string {
    return title
        .toLowerCase()
        .normalize('NFD')
        .replace(/[\u0300-\u036f]/g, '')
        .replace(/-\s*saison\s*\d+/gi, '')
        .replace(/\(\s*\d{4}\s*\)/g, '')
        .replace(/[^a-z0-9]/g, '');
}

/**
 * Déduplique les résultats par titre normalisé, en gardant la première occurrence.
 */
function deduplicateByTitle(results: SearchResult[]): SearchResult[] {
    const seen = new Set<string>();
    return results.filter(r => {
        const key = normalizeTitle(r.title);
        if (seen.has(key)) return false;
        seen.add(key);
        return true;
    });
}

export class ZoneTelechargementAPI implements ISource {
    name = 'zt';
    displayName = 'Zone-Téléchargement';
    get baseUrl() {
        return CONFIG.ZT_URL?.replace(/\/$/, '');
    }

    async healthCheck(): Promise<boolean> {
        if (!this.baseUrl) {
            console.warn('[ZT] ⚠️ ZT_URL non définie.');
            return false;
        }
        return true;
    }

    async search(query: string, mediaType: MediaType = 'movie'): Promise<SearchResult[]> {
        if (!this.baseUrl) throw new Error('ZT_URL non configurée.');
        if (!query || query.length < 4) throw new Error('La recherche nécessite au moins 4 caractères.');

        const html = await fetchSearchResults(this.baseUrl, query);
        if (html.includes('Aucun résultat')) return [];

        let results = parseSearchHTML(html, this.baseUrl);

        if (mediaType === 'movie') {
            results = results.filter(r => r.type === 'movie' || r.type === 'anime');
        } else {
            results = results.filter(r => r.type === 'series' || r.type === 'anime');
        }

        return deduplicateByTitle(results);
    }

    async getTrending(mediaType: MediaType): Promise<SearchResult[]> {
        if (!this.baseUrl) return [];
        try {
            const html = mediaType === 'movie'
                ? await fetchTrendingMovies(this.baseUrl)
                : await fetchTrendingSeries(this.baseUrl);
            const results = parseSearchHTML(html, this.baseUrl).slice(0, 40);
            return deduplicateByTitle(results).slice(0, 20);
        } catch (e: any) {
            console.error(`[ZT] ❌ Erreur trending ${mediaType}:`, e.message);
            return [];
        }
    }

    async getRecent(): Promise<SearchResult[]> {
        if (!this.baseUrl) return [];
        try {
            const html = await fetchRecent(this.baseUrl);
            const results = parseSearchHTML(html, this.baseUrl).slice(0, 40);
            return deduplicateByTitle(results).slice(0, 20);
        } catch (e: any) {
            console.error(`[ZT] ❌ Erreur getRecent:`, e.message);
            return [];
        }
    }

    async getContentLinks(pageUrl: string): Promise<ContentLinks> {
        if (!this.baseUrl) throw new Error('ZT_URL non configurée.');
        const fullUrl = pageUrl.startsWith('http') ? pageUrl : (this.baseUrl + (pageUrl.startsWith('/') ? '' : '/') + pageUrl);
        const html = await fetchContentPage(fullUrl);
        return parseContentHTML(html);
    }


    async getSelection(identifier: string, type?: string, seasonValue?: string | number): Promise<SelectionData> {
        const targetUrl = seasonValue ? String(seasonValue) : identifier;
        const content = await this.getContentLinks(targetUrl);

        const isSeries = targetUrl.includes('/telecharger-serie/') || targetUrl.includes('/serie-') || (content.relatedSeasons?.length || 0) > 0;
        
        let currentSeasonLabel = "Saison (Actuelle)";
        if (content.releaseNames && content.releaseNames.length > 0) {
            const sm = content.releaseNames[0].match(/Saison\s*\d+/i);
            if (sm) currentSeasonLabel = sm[0];
        }
        
        const formattedSeasons = (content.relatedSeasons || []).map(s => ({
            label: s.label,
            value: s.href
        }));
        
        if (isSeries) {
            formattedSeasons.push({ label: currentSeasonLabel, value: targetUrl });
            formattedSeasons.sort((a, b) => {
                const numA = parseInt(a.label.replace(/\D/g, '')) || 0;
                const numB = parseInt(b.label.replace(/\D/g, '')) || 0;
                return numA - numB;
            });
        }

        const allLinks = [...content.links];
        if (content.relatedQualities && content.relatedQualities.length > 0) {
            console.log(`[ZT] Fetching ${content.relatedQualities.length} other qualities concurrently...`);
            const qualityPromises = content.relatedQualities.map(async (q) => {
                try {
                    const qContent = await this.getContentLinks(q.href);
                    return qContent.links;
                } catch (e) {
                    console.error(`[ZT] Error fetching quality page ${q.href}:`, e);
                    return [];
                }
            });
            const otherQualitiesLinks = await Promise.all(qualityPromises);
            otherQualitiesLinks.forEach(links => allLinks.push(...links));
        }

        return { links: allLinks, seasons: formattedSeasons, isSeries };
    }

    async resolveLink(linkId: string): Promise<string | null> {
        try {
            console.log(`[ZT] 🔓 Résolution du lien : ${linkId}`);
            const html = await fetchResolvedLink(linkId);
            const resolved = extractLinkFromZtProtect(html);
            if (!resolved) {
                console.warn(`[ZT] ⚠️ Impossible d'extraire le lien résolu du HTML de ZTProtect pour ${linkId}`);
            }
            return resolved;
        } catch (e: any) {
            console.error(`[ZT] ❌ Erreur resolveLink pour ${linkId}:`, e.message);
            return null;
        }
    }
}

// ── Auto-registration ──
sourceRegistry.register(new ZoneTelechargementAPI());
