import { ISource, SearchResult, MediaType, SelectionData, ContentLinks } from '../../src/types/source.js';
import { CONFIG } from '../../src/utils/config.js';
import { sourceRegistry } from '../../src/core/registry.js';
import { fetchSearch, fetchTrending, fetchPage } from './api.js';
import { parseSearchResults, parseTrendingResults, parseContentHTML, parseEpisodeLinks, parseOtherVersions } from './parser.js';

function isSeriesIdentifier(identifier: string): boolean {
    return /saison|pack-series|series-(vf|vostfr|terminee)/i.test(identifier);
}

export class FreeTeleAPI implements ISource {
    name = 'freetel';
    displayName = 'Free-Télécharger';
    get baseUrl() {
        return CONFIG.FT_URL?.replace(/\/$/, '');
    }

    async healthCheck(): Promise<boolean> {
        if (!this.baseUrl) {
            console.warn('[FreeTel] ⚠️ FT_URL non définie.');
            return false;
        }
        try {
            const res = await fetch(this.baseUrl, {
                method: 'HEAD',
                headers: { 'User-Agent': 'Mozilla/5.0' },
                signal: AbortSignal.timeout(5000),
            });
            return res.ok;
        } catch {
            return true; // tolérant : le test réel se fait au premier scrape
        }
    }

    async search(query: string, mediaType: MediaType = 'movie'): Promise<SearchResult[]> {
        if (!this.baseUrl) throw new Error('FT_URL non configurée.');
        if (!query || query.length < 3) throw new Error('La recherche nécessite au moins 3 caractères.');
        const html = await fetchSearch(this.baseUrl, query);
        let results = parseSearchResults(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 results;
    }

    async getTrending(mediaType: MediaType): Promise<SearchResult[]> {
        if (!this.baseUrl) return [];
        try {
            const html = await fetchTrending(this.baseUrl);
            let results = parseTrendingResults(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 results.slice(0, 20);
        } catch (e: any) {
            console.error(`[FreeTel] Erreur trending ${mediaType}:`, e.message);
            return [];
        }
    }

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

    async getContentLinks(identifier: string): Promise<ContentLinks> {
        if (!this.baseUrl) throw new Error('FT_URL non configurée.');
        const url = identifier.startsWith('http') ? identifier : `${this.baseUrl}/${identifier.replace(/^\//, '')}`;
        const html = await fetchPage(url);
        return parseContentHTML(html, isSeriesIdentifier(identifier));
    }

    async getSelection(identifier: string, type?: string, seasonValue?: string | number): Promise<SelectionData> {
        if (!this.baseUrl) throw new Error('FT_URL non configurée.');
        // Si seasonValue est fournie (l'UI a cliqué sur une autre qualité), on switch de fiche
        const targetIdentifier = seasonValue ? String(seasonValue) : identifier;
        const url = targetIdentifier.startsWith('http') ? targetIdentifier : `${this.baseUrl}/${targetIdentifier.replace(/^\//, '')}`;
        const html = await fetchPage(url);
        const isSeries = isSeriesIdentifier(targetIdentifier);
        const content = parseContentHTML(html, isSeries);

        // Pour les films, exposer les autres qualités comme "seasons" (l'UI les affichera en dropdown)
        let seasons: { label: string; value: string }[] = [];
        if (!isSeries) {
            seasons = parseOtherVersions(html, this.baseUrl);
            // Ajouter la version courante comme première entrée (sélectionnée par défaut)
            const currentQuality = content.links[0]?.quality;
            if (currentQuality && currentQuality !== 'Inconnu') {
                seasons.unshift({ label: currentQuality, value: targetIdentifier });
            }
        }

        return {
            links: content.links,
            seasons,
            isSeries,
        };
    }

    async resolveLink(linkId: string): Promise<string | null> {
        let hostUrl: string | null = null;

        // Cas série : page intermédiaire liens.free-telecharger.cam/SLUG-episode_N
        if (linkId.includes('liens.free-telecharger.')) {
            try {
                const html = await fetchPage(linkId);
                const hosts = parseEpisodeLinks(html);
                if (hosts.length === 0) {
                    console.warn(`[FreeTel] Aucun hôte trouvé sur ${linkId}`);
                    return null;
                }
                const preferred = hosts.find(h => /1fichier/i.test(h.host))
                    || hosts.find(h => /turbobit/i.test(h.host))
                    || hosts[0];
                hostUrl = preferred ? preferred.url : null;
            } catch (e: any) {
                console.error(`[FreeTel] Erreur resolveLink:`, e.message);
                return null;
            }
        } else if (linkId.startsWith('http')) {
            // Cas film : linkId est déjà l'URL hôte (1fichier, Turbobit, …)
            hostUrl = linkId;
        }

        return hostUrl;
    }
}

sourceRegistry.register(new FreeTeleAPI());
