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 { parseListingHTML, parseContentHTML, parseOtherVersions } from './parser.js';

function isSeriesIdentifier(identifier: string): boolean {
    return /[?&]p=serie\b|telecharger-serie/i.test(identifier);
}

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, '');
}

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 ZtTeamAPI implements ISource {
    name = 'ztnews';
    displayName = 'Zone-Téléchargement (Team)';
    get baseUrl() {
        return CONFIG.ZTTEAM_URL?.replace(/\/$/, '');
    }

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

    async search(query: string, mediaType: MediaType = 'movie'): Promise<SearchResult[]> {
        if (!this.baseUrl) throw new Error('ZTTEAM_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 = parseListingHTML(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 = await fetchTrending(this.baseUrl, mediaType === 'series' ? 'series' : 'films');
            const results = parseListingHTML(html, this.baseUrl);
            return deduplicateByTitle(results).slice(0, 20);
        } catch (e: any) {
            console.error(`[ztnews] Erreur trending ${mediaType}:`, e.message);
            return [];
        }
    }

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

    async getContentLinks(identifier: string): Promise<ContentLinks> {
        if (!this.baseUrl) throw new Error('ZTTEAM_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('ZTTEAM_URL non configurée.');
        const targetIdentifier = seasonValue ? String(seasonValue) : identifier;
        const isSeries = isSeriesIdentifier(targetIdentifier);
        const url = targetIdentifier.startsWith('http') ? targetIdentifier : `${this.baseUrl}/${targetIdentifier.replace(/^\//, '')}`;
        const html = await fetchPage(url);
        const content = parseContentHTML(html, isSeries);

        const allLinks = [...content.links];
        let seasons: { label: string; value: string }[] = [];
        
        if (!isSeries) {
            const otherVersions = parseOtherVersions(html, this.baseUrl);
            if (otherVersions.length > 0) {
                console.log(`[ztnews] Fetching ${otherVersions.length} other qualities concurrently...`);
                const qualityPromises = otherVersions.map(async (q) => {
                    try {
                        const qHtml = await fetchPage(q.value);
                        const qContent = parseContentHTML(qHtml, isSeries);
                        return qContent.links;
                    } catch (e) {
                        console.error(`[ztnews] Error fetching quality page ${q.value}:`, e);
                        return [];
                    }
                });
                const otherQualitiesLinks = await Promise.all(qualityPromises);
                otherQualitiesLinks.forEach(links => allLinks.push(...links));
            }
        }

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

    async resolveLink(linkId: string): Promise<string | null> {
        console.log(`[ztTeam] 🔗 Renvoi du lien dl-protect brut (résolution via navigateur ou JDownloader requise) : ${linkId}`);
        return linkId || null;
    }
}

sourceRegistry.register(new ZtTeamAPI());
