/**
 * downloader.js — YouTube Player
 * ניהול הורדות סרטונים, תור הורדות, קישורים ידניים ופלייליסטים
 */

let downloadPollInterval = null;
// שומר את המידע המקומי על המשימות
let localJobsInfo = {}; 

// ─── חילוץ מזהה לתמונה ────────────────────────────────────────

function extractIdForThumb(str) {
    if (!str) return '';
    if (str.startsWith('http')) {
        const match = str.match(/[?&]v=([^&]+)/);
        if (match) return match[1];
        const shortMatch = str.match(/youtu\.be\/([^?]+)/);
        if (shortMatch) return shortMatch[1];
        return ''; 
    }
    return str;
}

// ─── פעולות בסיס (התחלה, ביטול, ניקוי) ─────────────────────────

async function startVideoDownload(videoId, categoryName, channelTitle) {
    categoryName = decodeURIComponent(categoryName);
    channelTitle = decodeURIComponent(channelTitle);

    const isAlreadyDownloading = Object.values(localJobsInfo).some(
        job => job.videoId === videoId && ['queued', 'starting', 'downloading'].includes(job.status)
    );
    
    if (isAlreadyDownloading) {
        showToast('הסרטון כבר נמצא בתהליך הורדה או ממתין בתור', 'info');
        toggleDownloadsManager(true);
        return;
    }

    try {
        showToast('נוסף לתור ההורדות', 'info');
        updateVideoCardUI(videoId, 'queued', 0);

        const el = document.querySelector(`[data-vid="${videoId}"]`);
        const title = el ? el.getAttribute('data-title') : 'סרטון מ-YouTube';

        const response = await fetch('/api/download/start', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ videoId, category: categoryName, channel: channelTitle, isPlaylist: false })
        });

        const data = await response.json();
        
        if (data.success && data.jobId) {
            localJobsInfo[data.jobId] = {
                jobId: data.jobId,
                videoId: videoId,
                title: title,
                category: categoryName,
                channel: channelTitle,
                status: 'queued',
                progress: 0,
                speed: '',
                phase: 'starting',
                isPlaylist: false
            };
            
            ensurePolling();
            renderDownloadsManager();
            updateBadge();
        } else {
            throw new Error(data.error || 'שגיאה בהכנסה לתור ההורדות');
        }
    } catch (err) {
        showToast(`שגיאה: ${err.message}`, 'error');
        updateVideoCardUI(videoId, 'error', 0);
        setTimeout(() => hideVideoCardUI(videoId), 3000);
    }
}

async function submitCustomDownload() {
    const inputEl = document.getElementById('customDownloadUrl');
    
    if (!inputEl) return;
    
    const url = inputEl.value.trim();
    if (!url) {
        showToast('נא להזין קישור תקין', 'error');
        return;
    }

    // זיהוי אוטומטי של פלייליסט (בודק אם יש 'list=' בתוך הקישור)
    const isPlaylist = /[?&]list=/.test(url);
    
    try {
        showToast('מוסיף לתור...', 'info');
        
        const categoryName = 'הורדות שונות';
        const channelTitle = 'קישורים ידניים';
        
        const response = await fetch('/api/download/start', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                videoId: url, 
                category: categoryName, 
                channel: channelTitle,
                isPlaylist: isPlaylist
            })
        });

        const data = await response.json();
        
        if (data.success && data.jobId) {
            inputEl.value = ''; 

            localJobsInfo[data.jobId] = {
                jobId: data.jobId,
                videoId: url,
                title: isPlaylist ? 'פלייליסט מצורף ידנית' : 'סרטון מצורף ידנית',
                category: categoryName,
                channel: channelTitle,
                status: 'queued',
                progress: 0,
                speed: '',
                phase: 'starting',
                isPlaylist: isPlaylist
            };
            
            ensurePolling();
            renderDownloadsManager();
            updateBadge();
            showToast(isPlaylist ? 'הפלייליסט נוסף לתור' : 'הסרטון נוסף לתור', 'success');
        } else {
            throw new Error(data.error || 'שגיאה בהכנסה לתור');
        }
    } catch (err) {
        showToast(`שגיאה: ${err.message}`, 'error');
    }
}

async function cancelDownload(jobId) {
    try {
        await fetch('/api/download/cancel', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ jobId })
        });
        
        if (localJobsInfo[jobId]) {
            localJobsInfo[jobId].status = 'canceled';
            updateVideoCardUI(localJobsInfo[jobId].videoId, 'canceled', localJobsInfo[jobId].progress);
            setTimeout(() => hideVideoCardUI(localJobsInfo[jobId].videoId), 3000);
        }
        
        renderDownloadsManager();
        updateBadge();
    } catch (err) {
        console.error('Error canceling job:', err);
    }
}

async function clearCompletedDownloads() {
    const jobsToRemove = Object.keys(localJobsInfo).filter(
        jobId => ['done', 'error', 'canceled', 'netfree_blocked'].includes(localJobsInfo[jobId].status)
    );

    for (const jobId of jobsToRemove) {
        try {
            await fetch('/api/download/clear', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ jobId })
            });
            hideVideoCardUI(localJobsInfo[jobId].videoId);
            delete localJobsInfo[jobId];
        } catch(e) { console.error('Error clearing:', e); }
    }

    renderDownloadsManager();
    updateBadge();
}

// ─── מנגנון דגימה (Polling) מהשרת ─────────────────────────────

function ensurePolling() {
    if (downloadPollInterval) return;
    downloadPollInterval = setInterval(pollDownloads, 1000);
}

async function pollDownloads() {
    if (Object.keys(localJobsInfo).length === 0) {
        clearInterval(downloadPollInterval);
        downloadPollInterval = null;
        updateBadge();
        return;
    }

    try {
        const res = await fetch('/api/download/status');
        const statuses = await res.json();
        
        let hasChanges = false;

        for (const [jobId, jobInfo] of Object.entries(statuses)) {
            if (!localJobsInfo[jobId]) {
                localJobsInfo[jobId] = {
                    jobId: jobId,
                    videoId: jobInfo.video_id,
                    title: jobInfo.title || (jobInfo.is_playlist ? 'פלייליסט...' : 'סרטון בהורדה...'), 
                    category: jobInfo.category,
                    channel: jobInfo.channel,
                    status: jobInfo.status,
                    progress: jobInfo.progress,
                    speed: jobInfo.speed || '',
                    phase: jobInfo.phase || 'starting',
                    isPlaylist: jobInfo.is_playlist
                };
                hasChanges = true;
            }

            const localJob = localJobsInfo[jobId];
            
            let jobChanged = false;

            if (jobInfo.title && localJob.title !== jobInfo.title) {
                localJob.title = jobInfo.title;
                jobChanged = true;
            }
            
            if (jobInfo.channel && localJob.channel !== jobInfo.channel) {
                localJob.channel = jobInfo.channel;
                jobChanged = true;
            }

            if (localJob.status !== jobInfo.status || localJob.progress !== jobInfo.progress || localJob.phase !== jobInfo.phase) {
                localJob.status = jobInfo.status;
                localJob.progress = jobInfo.progress;
                localJob.speed = jobInfo.speed || '';
                localJob.phase = jobInfo.phase || 'starting';
                jobChanged = true;

                updateVideoCardUI(localJob.videoId, localJob.status, localJob.progress);

                if (jobInfo.status === 'done') {
                    if (!jobInfo.is_playlist) {
                        showToast('ההורדה הסתיימה בהצלחה ✓', 'success');
                    }
                    setTimeout(() => hideVideoCardUI(localJob.videoId), 3000);
                } else if (jobInfo.status === 'error') {
                    showToast('שגיאה בהורדת הסרטון/הפלייליסט', 'error');
                    setTimeout(() => hideVideoCardUI(localJob.videoId), 4000);
                } else if (jobInfo.status === 'netfree_blocked') {
                    showToast('הסרטון חסום בנטפרי', 'error');
                    setTimeout(() => hideVideoCardUI(localJob.videoId), 5000);
                }
            }

            if (jobChanged) hasChanges = true;
        }

        for (const jobId of Object.keys(localJobsInfo)) {
            if (!statuses[jobId]) {
                delete localJobsInfo[jobId];
                hasChanges = true;
            }
        }

        if (hasChanges) {
            renderDownloadsManager();
            updateBadge();
        }

    } catch (err) {
        console.error('Error polling downloads:', err);
    }
}

// ─── ניהול ממשק המשתמש (UI) ───────────────────────────────────

function toggleDownloadsManager(forceOpen = false) {
    const modal = document.getElementById('downloadsModal');
    if (!modal) return;
    
    if (forceOpen) {
        modal.classList.remove('hidden');
    } else {
        modal.classList.toggle('hidden');
    }
    
    if (!modal.classList.contains('hidden')) {
        document.getElementById('settingsPanel')?.classList.add('hidden');
        document.getElementById('notificationDropdown')?.classList.add('hidden');
        renderDownloadsManager();
        
        const inputEl = document.getElementById('customDownloadUrl');
        if (inputEl) inputEl.focus();
    }
}

function updateBadge() {
    const badge = document.getElementById('downloadsBadge');
    if (!badge) return;

    const activeCount = Object.values(localJobsInfo).filter(
        job => ['queued', 'starting', 'downloading'].includes(job.status)
    ).length;

    if (activeCount > 0) {
        badge.textContent = activeCount;
        badge.style.display = 'flex';
        document.getElementById('downloadsNavBtn').classList.add('animate-pulse');
    } else {
        badge.style.display = 'none';
        document.getElementById('downloadsNavBtn').classList.remove('animate-pulse');
    }
}

function getLogText(job) {
    const { status, phase, isPlaylist } = job;
    const iconClass = "text-[11px] ml-1.5 opacity-80";
    
    if (status === 'queued') return `<i class="fas fa-hourglass-half ${iconClass}"></i> ממתין בתור...`;
    if (status === 'starting') return `<i class="fas fa-link ${iconClass}"></i> מתחבר לשרת...`;
    if (status === 'downloading') {
        if (isPlaylist) return `<i class="fas fa-list ${iconClass}"></i> שולף נתוני פלייליסט...`;
        if (phase === 'video') return `<i class="fas fa-video ${iconClass}"></i> מוריד ערוץ וידאו...`;
        if (phase === 'audio') return `<i class="fas fa-music ${iconClass}"></i> מוריד ערוץ שמע...`;
        if (phase === 'merge') return `<i class="fas fa-layer-group ${iconClass}"></i> ממזג וידאו ושמע...`;
        return `<i class="fas fa-search ${iconClass}"></i> אוסף נתונים...`;
    }
    if (status === 'done') {
        return isPlaylist 
            ? `<i class="fas fa-list-check ${iconClass}"></i> חולץ והתווסף לתור!` 
            : `<i class="fas fa-check-circle ${iconClass}"></i> הושלם בהצלחה!`;
    }
    if (status === 'error') return `<i class="fas fa-exclamation-triangle ${iconClass}"></i> ההורדה נכשלה.`;
    if (status === 'canceled') return `<i class="fas fa-ban ${iconClass}"></i> ההורדה בוטלה.`;
    if (status === 'netfree_blocked') return `<i class="fas fa-shield-alt ${iconClass}"></i> חסום ע"י נטפרי`;
    return 'ממתין...';
}

function renderDownloadsManager() {
    const listContainer = document.getElementById('downloadsManagerList');
    const emptyState = document.getElementById('downloadsEmptyState');
    const subtitle = document.getElementById('downloadsManagerSubtitle');
    if (!listContainer || !emptyState || !subtitle) return;

    const jobs = Object.values(localJobsInfo);
    
    jobs.sort((a, b) => {
        const activeA = ['queued', 'starting', 'downloading'].includes(a.status) ? -1 : 1;
        const activeB = ['queued', 'starting', 'downloading'].includes(b.status) ? -1 : 1;
        return activeA - activeB;
    });

    if (jobs.length === 0) {
        emptyState.style.display = 'block';
        subtitle.textContent = 'אין הורדות פעילות';
        
        Array.from(listContainer.children).forEach(child => {
            if (child.id !== 'downloadsEmptyState') child.remove();
        });
        return;
    }

    emptyState.style.display = 'none';
    const activeCount = jobs.filter(j => ['queued', 'starting', 'downloading'].includes(j.status)).length;
    subtitle.textContent = activeCount > 0 ? `${activeCount} הורדות מתוכננות/פעילות` : 'כל ההורדות הסתיימו';

    Array.from(listContainer.children).forEach(child => {
        if (child.id !== 'downloadsEmptyState') child.remove();
    });

    jobs.forEach(job => {
        const extractedId = extractIdForThumb(job.videoId);
        const thumbUrl = extractedId ? `https://img.youtube.com/vi/${extractedId}/mqdefault.jpg` : '';
        const logHtml = getLogText(job);
        const isDone = job.status === 'done';
        const isErr = job.status === 'error';
        const isCanc = job.status === 'canceled';
        const isNetfree = job.status === 'netfree_blocked';
        const isQueued = job.status === 'queued';
        const isActive = ['starting', 'downloading'].includes(job.status);
        const isPendingOrActive = isQueued || isActive;
        
        let barColor = 'bg-violet-500';
        let logColor = 'text-violet-600';
        let bgOpacity = 'bg-white hover:bg-gray-50/50';
        let opacity = 'opacity-100';
        let borderClass = 'border-gray-100 hover:border-violet-200';

        if (isDone) { 
            barColor = 'bg-emerald-500'; logColor = 'text-emerald-600'; 
            bgOpacity = 'bg-emerald-50/30'; borderClass = 'border-emerald-100'; 
        } else if (isErr) { 
            barColor = 'bg-red-500'; logColor = 'text-red-600'; 
            bgOpacity = 'bg-red-50/30'; borderClass = 'border-red-100'; 
        } else if (isNetfree) { 
            barColor = 'bg-orange-500'; logColor = 'text-orange-600'; 
            bgOpacity = 'bg-orange-50/40'; borderClass = 'border-orange-100'; 
        } else if (isCanc) { 
            barColor = 'bg-gray-400'; logColor = 'text-gray-500'; 
            bgOpacity = 'bg-gray-50'; opacity = 'opacity-70'; borderClass = 'border-gray-200'; 
        } else if (isQueued) { 
            barColor = 'bg-blue-400'; logColor = 'text-blue-600'; 
            bgOpacity = 'bg-blue-50/20 hover:bg-blue-50/40'; borderClass = 'border-gray-100 hover:border-blue-200'; 
        }

        const card = document.createElement('div');
        card.className = `flex-shrink-0 p-3.5 ${bgOpacity} ${opacity} border ${borderClass} rounded-2xl shadow-sm hover:shadow flex gap-4 items-center transition-all duration-300 relative overflow-hidden group`;

        card.innerHTML = `
            <div class="relative w-28 h-16 flex-shrink-0 bg-gray-100 rounded-xl overflow-hidden border border-gray-200/60 shadow-inner flex items-center justify-center">
                <i class="fas ${job.isPlaylist ? 'fa-layer-group text-violet-300' : 'fa-video text-gray-300'} text-2xl absolute z-0"></i>
                <img src="${thumbUrl}" class="w-full h-full object-cover relative z-10 transition-opacity duration-300" onerror="this.style.opacity='0'">
                ${isDone ? '<div class="absolute inset-0 bg-emerald-500/20 flex items-center justify-center z-20 backdrop-blur-[1px]"><i class="fas fa-check text-emerald-600 text-xl drop-shadow-md"></i></div>' : ''}
            </div>
            
            <div class="flex-1 min-w-0 flex flex-col justify-center py-0.5">
                <h4 class="text-[14px] font-bold text-gray-800 truncate leading-tight flex items-center gap-1.5 mb-0.5">
                    ${job.isPlaylist ? '<i class="fas fa-list text-violet-500 text-[10px] bg-violet-100 px-1.5 py-1 rounded-md"></i>' : ''}
                    ${job.title}
                </h4>
                <p class="text-[11px] text-gray-500 truncate">${job.channel} <span class="mx-1 text-gray-300">•</span> ${job.category}</p>
                
                <div class="mt-2.5 flex justify-between items-end mb-1.5">
                    <div class="text-[11px] font-semibold ${logColor} flex items-center tracking-wide">
                        ${logHtml}
                    </div>
                    <div class="flex items-center gap-2">
                        ${isActive && job.speed ? `<span class="text-gray-400 font-mono text-[10px] bg-white border border-gray-100 px-1.5 py-0.5 rounded shadow-sm" dir="ltr">${job.speed}</span>` : ''}
                        <span class="font-bold font-mono text-[12px] ${logColor}">${isActive ? job.progress.toFixed(1) + '%' : ''}</span>
                    </div>
                </div>
                
                <div class="w-full bg-gray-200/70 h-2 rounded-full overflow-hidden shadow-inner">
                    <div class="${barColor} h-full rounded-full transition-all duration-300 relative" style="width: ${isActive || isDone ? job.progress : (isQueued ? 100 : 0)}%">
                         ${isActive ? '<div class="absolute top-0 bottom-0 left-0 right-0 bg-white/25 animate-pulse"></div>' : ''}
                         ${isQueued ? '<div class="absolute top-0 bottom-0 left-0 right-0 bg-blue-100/40 animate-pulse"></div>' : ''}
                    </div>
                </div>
            </div>

            ${isPendingOrActive ? `
                <div class="flex-shrink-0 flex items-center justify-center pl-1">
                    <button onclick="cancelDownload('${job.jobId}')" title="בטל הורדה" 
                            class="w-9 h-9 rounded-xl flex items-center justify-center text-gray-400 hover:text-red-600 bg-white border border-transparent hover:bg-red-50 hover:border-red-100 hover:shadow-sm transition-all outline-none">
                        <i class="fas fa-times text-sm"></i>
                    </button>
                </div>
            ` : ''}
        `;
        listContainer.appendChild(card);
    });
}

function updateVideoCardUI(videoId, status, progress) {
    const container = document.getElementById(`dl-progress-${videoId}`);
    if (!container) return; 

    container.classList.remove('hidden');
    container.style.display = 'flex';

    const bar = container.querySelector('.dl-bar');
    const pctText = container.querySelector('.dl-pct');

    if (bar && pctText) {
        bar.style.width = status === 'queued' ? '100%' : `${progress}%`;
        pctText.textContent = status === 'queued' ? 'ממתין' : `${Math.floor(progress)}%`;

        if (status === 'done') {
            bar.style.backgroundColor = '#10b981';
            pctText.style.color = '#059669'; 
        } else if (status === 'error') {
            bar.style.backgroundColor = '#ef4444'; 
            pctText.style.color = '#dc2626'; 
            pctText.textContent = 'שגיאה';
        } else if (status === 'netfree_blocked') {
            bar.style.backgroundColor = '#f97316'; 
            pctText.style.color = '#ea580c'; 
            pctText.textContent = 'חסום';
        } else if (status === 'canceled') {
            bar.style.backgroundColor = '#9ca3af'; 
            pctText.style.color = '#6b7280'; 
            pctText.textContent = 'בוטל';
        } else if (status === 'queued') {
            bar.style.backgroundColor = '#60a5fa'; 
            pctText.style.color = '#3b82f6'; 
            pctText.style.fontSize = '8px'; 
        } else {
            bar.style.backgroundColor = '#8b5cf6'; 
            pctText.style.color = '#7c3aed'; 
            pctText.style.fontSize = '9px'; 
        }
    }
}

function hideVideoCardUI(videoId) {
    const container = document.getElementById(`dl-progress-${videoId}`);
    if (container) {
        container.classList.add('hidden');
        container.style.display = '';
        
        const bar = container.querySelector('.dl-bar');
        const pctText = container.querySelector('.dl-pct');
        if (bar) bar.style.width = '0%';
        if (pctText) pctText.textContent = '0%';
        if (bar) bar.style.backgroundColor = '#8b5cf6';
        if (pctText) pctText.style.color = '#7c3aed';
        if (pctText) pctText.style.fontSize = '9px';
    }
}

async function initDownloadsRecovery() {
    try {
        const res = await fetch('/api/download/status');
        const statuses = await res.json();
        
        let hasActive = false;
        for (const [jobId, info] of Object.entries(statuses)) {
            localJobsInfo[jobId] = {
                jobId: jobId,
                videoId: info.video_id,
                title: info.title || (info.is_playlist ? 'פלייליסט בהורדה...' : 'סרטון בהורדה...'), 
                category: info.category,
                channel: info.channel,
                status: info.status,
                progress: info.progress,
                speed: info.speed || '',
                phase: info.phase || 'starting',
                isPlaylist: info.is_playlist || false
            };

            const el = document.querySelector(`[data-vid="${info.video_id}"]`);
            if (el && (!info.title || info.title.includes('בהורדה'))) {
                localJobsInfo[jobId].title = el.getAttribute('data-title');
            }

            if (['queued', 'starting', 'downloading'].includes(info.status)) {
                hasActive = true;
            }
        }

        if (hasActive) {
            ensurePolling();
        }
        
        updateBadge();
        
    } catch (e) {
        console.error('Failed to recover downloads on load:', e);
    }
}

document.addEventListener('DOMContentLoaded', initDownloadsRecovery);