'use strict';

/* ── Single URL Extraction ── */
const singleUrl = document.getElementById('single-url');
const singleBtn = document.getElementById('single-btn');
const singleBtnText = document.getElementById('single-btn-text');
const singleResult = document.getElementById('single-result');
const singleResultInner = document.getElementById('single-result-inner');

async function extractSingle() {
    const url = singleUrl.value.trim();
    if (!url) { singleUrl.focus(); return; }

    // Loading state
    singleBtn.disabled = true;
    singleBtnText.textContent = 'Extracting…';
    singleResult.classList.remove('hidden');
    singleResultInner.innerHTML = `
        <div class="result-loading">
            <div class="spinner"></div>
            <span>Visiting page and looking for the main product image…</span>
        </div>`;

    try {
        const resp = await fetch('extract_single.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ url })
        });
        const data = await resp.json();

        if (data.image_url) {
            const levelLabels = {
                1: 'og:image (best)',
                2: 'twitter:image',
                3: 'zoom image attribute',
                4: 'large image attribute',
                5: 'data-src attribute',
                6: 'srcset (largest)',
                7: 'CSS selector fallback',
            };
            const levelLabel = levelLabels[data.fallback_level] ?? `level ${data.fallback_level}`;

            singleResultInner.innerHTML = `
                <div class="result-success">
                    <div class="result-label">✓ Image URL Found</div>
                    <div class="result-url-wrap">
                        <div class="result-url" id="extracted-url">${escHtml(data.image_url)}</div>
                        <button class="btn btn-sm btn-secondary" onclick="copyUrl(this, '${escHtml(data.image_url).replace(/'/g,"\\'")}')">Copy</button>
                        <a href="${escHtml(data.image_url)}" target="_blank" class="btn btn-sm btn-secondary">Open ↗</a>
                    </div>
                    <div class="result-meta">
                        <span class="result-chip">Source: ${escHtml(levelLabel)}</span>
                        <span class="result-chip">From: ${escHtml(new URL(url).hostname)}</span>
                    </div>
                    <div class="result-image-preview">
                        <img src="${escHtml(data.image_url)}" alt="Product image preview"
                             onerror="this.parentElement.innerHTML='<p style=\\'color:var(--gray-400);font-size:.82rem\\'>Preview not available (image may require authentication)</p>'">
                    </div>
                </div>`;
        } else {
            singleResultInner.innerHTML = `
                <div class="result-error">
                    <div class="result-label">✗ No Image Found</div>
                    <p>${escHtml(data.error ?? 'Could not extract an image from this page.')}</p>
                    <p style="margin-top:8px;font-size:.82rem;color:#9ca3af">This can happen with pages protected by Cloudflare, login-gated pages, or sites that load images via JavaScript.</p>
                </div>`;
        }
    } catch (err) {
        singleResultInner.innerHTML = `
            <div class="result-error">
                <div class="result-label">✗ Request Failed</div>
                <p>${escHtml(err.message)}</p>
            </div>`;
    } finally {
        singleBtn.disabled = false;
        singleBtnText.textContent = 'Extract Image URL';
    }
}

function copyUrl(btn, url) {
    navigator.clipboard.writeText(url).then(() => {
        btn.textContent = 'Copied!';
        setTimeout(() => { btn.textContent = 'Copy'; }, 2000);
    });
}

singleBtn.addEventListener('click', extractSingle);
singleUrl.addEventListener('keydown', e => { if (e.key === 'Enter') extractSingle(); });



/* ── Drop zone ── */
const dropZone   = document.getElementById('drop-zone');
const fileInput  = document.getElementById('file-input');
const filePreview = document.getElementById('file-preview');
const submitBtn  = document.getElementById('submit-btn');
const uploadHint = document.querySelector('.upload-hint');

function formatBytes(bytes) {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
    return (bytes / 1048576).toFixed(1) + ' MB';
}

function showFilePreview(file) {
    filePreview.innerHTML = `
        <span class="file-icon">📊</span>
        <div>
            <div class="file-name">${escHtml(file.name)}</div>
            <div class="file-size">${formatBytes(file.size)}</div>
        </div>
    `;
    filePreview.classList.remove('hidden');
    submitBtn.disabled = false;
    uploadHint.textContent = '';
}

fileInput.addEventListener('change', () => {
    if (fileInput.files.length > 0) showFilePreview(fileInput.files[0]);
});

['dragenter', 'dragover'].forEach(ev => {
    dropZone.addEventListener(ev, e => { e.preventDefault(); dropZone.classList.add('drag-over'); });
});
['dragleave', 'drop'].forEach(ev => {
    dropZone.addEventListener(ev, e => { e.preventDefault(); dropZone.classList.remove('drag-over'); });
});
dropZone.addEventListener('drop', e => {
    const file = e.dataTransfer?.files[0];
    if (!file) return;
    fileInput.files = e.dataTransfer.files;
    showFilePreview(file);
});

/* ── Form submit (AJAX) ── */
const uploadForm = document.getElementById('upload-form');
const progressSection = document.getElementById('progress-section');

uploadForm.addEventListener('submit', async e => {
    e.preventDefault();
    submitBtn.disabled = true;
    submitBtn.textContent = '⏳ Uploading...';

    try {
        const formData = new FormData(uploadForm);
        const resp = await fetch('upload.php', { method: 'POST', body: formData });
        const data = await resp.json();

        if (data.error) {
            alert('Error: ' + data.error);
            submitBtn.disabled = false;
            submitBtn.innerHTML = '<span class="btn-icon">🚀</span> Start Extraction';
            return;
        }

        // Show progress UI
        uploadForm.closest('.card').classList.add('hidden');
        progressSection.classList.remove('hidden');
        document.getElementById('progress-job-id').textContent = '#' + data.job_id;
        startPolling(data.token, data.total);

    } catch (err) {
        alert('Network error: ' + err.message);
        submitBtn.disabled = false;
        submitBtn.innerHTML = '<span class="btn-icon">🚀</span> Start Extraction';
    }
});

/* ── Progress polling ── */
let pollInterval = null;
let pollStartTime = null;

function startPolling(token, total) {
    pollStartTime = Date.now();
    document.getElementById('stat-total').textContent = total;

    const stopBtn     = document.getElementById('stop-btn');
    const downloadBtn = document.getElementById('download-btn');
    const statusEl    = document.getElementById('progress-status');

    stopBtn.addEventListener('click', () => stopJob(token));

    pollInterval = setInterval(async () => {
        try {
            const resp = await fetch(`api.php?action=process&token=${encodeURIComponent(token)}`);
            const data = await resp.json();
            if (data.error) return;

            const { processed_rows, success_rows, failed_rows, total_rows, status, filename } = data;
            const pct = total_rows > 0 ? Math.round(processed_rows / total_rows * 100) : 0;

            document.getElementById('stat-success').textContent = success_rows;
            document.getElementById('stat-failed').textContent  = failed_rows;
            document.getElementById('stat-pct').textContent     = pct + '%';
            document.getElementById('progress-bar').style.width = pct + '%';

            // ETA
            if (processed_rows > 0) {
                const elapsed = (Date.now() - pollStartTime) / 1000;
                const rate    = processed_rows / elapsed;
                const remaining = (total_rows - processed_rows) / rate;
                document.getElementById('stat-eta').textContent = formatTime(remaining);
            }

            const labels = { pending: 'Waiting to start…', running: `Processing… (${processed_rows}/${total_rows})`, done: 'Complete!', failed: 'Job failed.', stopped: 'Job stopped.' };
            statusEl.textContent = labels[status] ?? status;

            if (status === 'done') {
                clearInterval(pollInterval);
                downloadBtn.classList.remove('hidden');
                downloadBtn.href = `download.php?token=${encodeURIComponent(token)}`;
                downloadBtn.onclick = () => { downloadBtn.href = `download.php?token=${encodeURIComponent(token)}`; };
                stopBtn.classList.add('hidden');
                document.getElementById('progress-bar').style.width = '100%';
                fetchLogs(token);
            } else if (['failed', 'stopped'].includes(status)) {
                clearInterval(pollInterval);
                stopBtn.classList.add('hidden');
                fetchLogs(token);
            } else {
                fetchLogs(token);
            }
        } catch (err) { /* ignore transient errors */ }
    }, 1500);
}

async function fetchLogs(token) {
    try {
        const resp = await fetch(`api.php?action=logs&token=${encodeURIComponent(token)}`);
        const data = await resp.json();
        if (!data.logs) return;
        const el = document.getElementById('log-output');
        el.innerHTML = data.logs.map(log => {
            const cls = 'log-' + (log.level || 'info');
            return `<span class="${cls}">[${log.timestamp}] [${log.level.toUpperCase()}] ${escHtml(log.message)}</span>`;
        }).join('\n');
        el.scrollTop = el.scrollHeight;
    } catch (_) {}
}

async function stopJob(token) {
    if (!confirm('Stop this job?')) return;
    clearInterval(pollInterval);
    try {
        await fetch('api.php?action=stop', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ token })
        });
    } catch (_) {}
    document.getElementById('progress-status').textContent = 'Job stopped.';
    document.getElementById('stop-btn').classList.add('hidden');
}

function formatTime(seconds) {
    if (!isFinite(seconds) || seconds < 0) return '—';
    if (seconds < 60) return Math.round(seconds) + 's';
    const m = Math.floor(seconds / 60);
    const s = Math.round(seconds % 60);
    return `${m}m ${s}s`;
}

function escHtml(str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

/* ── Resume watching a job from history ── */
window.resumeJob = function(token) {
    uploadForm.closest('.card').classList.add('hidden');
    progressSection.classList.remove('hidden');
    document.getElementById('progress-job-id').textContent = '#?';
    startPolling(token, 0);
    // Fetch total from first progress call — handled by polling
};

/* ── Download button wire-up ── */
const downloadBtn = document.getElementById('download-btn');
if (downloadBtn) {
    downloadBtn.addEventListener('click', function() {
        window.location.href = this.href;
    });
}
