/* ============================================================
   Alopecia Digital Twin — app.js
   ============================================================ */

document.addEventListener('DOMContentLoaded', () => {

    // ── Data store
    let allPapers = [];
    let filteredPapers = [];
    let charts = {};
    let currentPage = 1;
    const PAGE_SIZE = 20;

    // ── Tab Nav
    const tabBtns = document.querySelectorAll('.tab-btn');
    const tabContents = document.querySelectorAll('.tab-content');
    tabBtns.forEach(btn => {
        btn.addEventListener('click', () => {
            tabBtns.forEach(b => b.classList.remove('active'));
            tabContents.forEach(c => c.classList.remove('active'));
            btn.classList.add('active');
            document.getElementById(`tab-${btn.dataset.tab}`).classList.add('active');
            // Lazy-render charts when Stats tab opens
            if (btn.dataset.tab === 'stats' && allPapers.length) renderCharts();
        });
    });

    // ── Element refs (Digital Twin)
    const diseaseSelect = document.getElementById('disease-select');
    const modalitySelect = document.getElementById('modality-select');
    const deliverySelect = document.getElementById('delivery-select');
    const synthesizeBtn = document.getElementById('btn-synthesize');
    const visPlaceholder = document.getElementById('vis-placeholder');
    const visActive = document.getElementById('vis-active');
    const mechanismImage = document.getElementById('mechanism-image');
    const activePathway = document.getElementById('active-pathway');
    const mechanismDesc = document.getElementById('mechanism-description');
    const efficacyBar = document.getElementById('efficacy-bar');
    const bioBar = document.getElementById('bio-bar');
    const evidenceBar = document.getElementById('evidence-bar');
    const insightsList = document.getElementById('insights-list');
    const paperCountEl = document.getElementById('paper-count');
    const lastUpdatedEl = document.getElementById('last-updated');
    const relatedCount = document.getElementById('related-count');
    const relatedNum = document.getElementById('related-num');
    const insightFilter = document.getElementById('insight-disease-filter');

    // ── Digital Twin control logic
    diseaseSelect.addEventListener('change', e => {
        const val = e.target.value;
        modalitySelect.disabled = !val;
        if (!val) { modalitySelect.value = ''; deliverySelect.disabled = true; deliverySelect.value = ''; synthesizeBtn.disabled = true; relatedCount.classList.add('hidden'); }
    });
    modalitySelect.addEventListener('change', e => {
        deliverySelect.disabled = !e.target.value;
        if (!e.target.value) { deliverySelect.value = ''; synthesizeBtn.disabled = true; }
    });
    deliverySelect.addEventListener('change', e => { synthesizeBtn.disabled = !e.target.value; });

    // ── Synthesize
    synthesizeBtn.addEventListener('click', () => {
        const disease = diseaseSelect.value;
        const modality = modalitySelect.value;
        const delivery = deliverySelect.value;

        visPlaceholder.classList.add('hidden');
        visActive.classList.remove('hidden');

        const config = getTwinConfig(disease, modality, delivery);

        activePathway.textContent = config.pathway;
        mechanismDesc.innerHTML = `<span class="desc-en">${config.desc}</span><br><span class="desc-ko">${config.descKo}</span>`;

        mechanismImage.style.opacity = '0';
        setTimeout(() => {
            mechanismImage.src = config.image;
            mechanismImage.onload = () => { mechanismImage.style.opacity = '0.85'; };
            mechanismImage.onerror = () => { mechanismImage.style.opacity = '0'; };
        }, 400);

        // Animate bars
        setTimeout(() => {
            efficacyBar.style.width = config.efficacy + '%';
            efficacyBar.textContent = config.efficacy + '%';
            bioBar.style.width = config.bio + '%';
            bioBar.textContent = config.bio + '%';
        }, 600);

        // Count related papers
        const related = allPapers.filter(p =>
            p.disease === disease &&
            (modality === 'Other / Unknown' || p.modality === modality)
        );
        const pct = allPapers.length ? Math.round((related.length / allPapers.length) * 100) : 0;
        evidenceBar.style.width = Math.min(pct * 4, 100) + '%';
        evidenceBar.textContent = related.length + ' papers';
        relatedNum.textContent = related.length;
        relatedCount.classList.remove('hidden');
    });

    function getTwinConfig(disease, modality, delivery) {
        const modalityMap = {
            'Microneedles': { efficacy: 91, bio: 95 },
            'Stem Cells & Exosomes': { efficacy: 88, bio: 82 },
            'Natural Extracts': { efficacy: 72, bio: 68 },
            'Nanoparticles/Nanogels': { efficacy: 85, bio: 88 },
            'Other / Unknown': { efficacy: 78, bio: 75 },
        };
        const stats = modalityMap[modality] || { efficacy: 78, bio: 75 };

        if (disease === 'Androgenetic Alopecia') return {
            pathway: 'Wnt/β-catenin Upregulation (Wnt/β-카테닌 신호 활성화)',
            desc: `Utilizing ${modality} via ${delivery}, the treatment bypasses DHT binding barriers, stimulating Dermal Papilla Cells and driving hair follicles back into the Anagen growth phase.`,
            descKo: `${modality}을(를) ${delivery} 경로로 전달하여 DHT 결합 차단막을 우회합니다. 진피유두세포(Dermal Papilla Cell)를 자극해 모낭을 다시 성장기(Anagen Phase)로 전환시킵니다. Wnt 경로 활성화는 β-카테닌의 핵 내 이동을 촉진하여 모발 생성 관련 유전자 전사를 유도합니다.`,
            image: 'images/wnt_pathway.png',
            ...stats
        };
        if (disease === 'Alopecia Areata') return {
            pathway: 'JAK-STAT Pathway Inhibition (JAK-STAT 경로 억제)',
            desc: `Application of ${modality} (${delivery}) locally suppresses aberrant CD8+ T-cell immune responses, disabling the inflammatory signal loop that attacks the hair bulb.`,
            descKo: `${modality}(${delivery})을(를) 국소 적용하여 비정상적인 CD8+ T세포 면역 반응을 억제합니다. 모낭의 면역 특권(Immune Privilege)이 무너지면서 발생하는 자가면역 공격 신호 루프를 JAK1/2 억제를 통해 차단하고, 모낭 주변 염증을 완화합니다.`,
            image: 'images/jak_stat_pathway.png',
            ...stats
        };
        return {
            pathway: 'Anti-Apoptosis / ROS Scavenging (세포자멸사 억제 / 활성산소 제거)',
            desc: `${modality} delivered through ${delivery} mitigates severe oxidative stress and prevents p53-mediated apoptosis in rapidly dividing matrix cells during toxic exposure.`,
            descKo: `${modality}을(를) ${delivery}로 전달하여 항암 독성으로 인한 극심한 산화 스트레스를 완화합니다. 급속 분열 중인 모기질세포(Matrix Cell)에서 p53 매개 세포자멸사(Apoptosis)를 억제하고, 활성산소종(ROS)을 제거하여 모낭 세포 생존율을 높입니다.`,
            image: 'images/apoptosis_pathway.png',
            ...stats
        };
    }

    // ── Insight filter
    insightFilter.addEventListener('change', () => { updateInsights(currentData); });
    let currentData = null;

    function updateInsights(data) {
        if (!data) return;
        currentData = data;
        const filterVal = insightFilter.value;
        const papers = filterVal ? data.papers.filter(p => p.disease === filterVal) : data.papers;
        const recent = papers.slice(0, 12);

        insightsList.innerHTML = '';
        if (!recent.length) {
            insightsList.innerHTML = '<div class="insight-card empty-state">No papers found.</div>';
            return;
        }
        recent.forEach(paper => {
            const card = document.createElement('div');
            card.className = 'insight-card';
            const abbr = paper.disease.includes('Androgenetic') ? 'AGA Target'
                : paper.disease.includes('Areata') ? 'AA Target' : 'CIA Target';
            card.innerHTML = `
                <div class="insight-disease">${abbr}</div>
                <div class="insight-title" title="${paper.title}">${paper.title}</div>
                <div class="insight-meta">
                    <span class="tag">${paper.modality}</span>
                    <span>${paper.pubYear || 'Recent'}</span>
                </div>`;
            insightsList.appendChild(card);
        });
    }

    // ── Chart rendering
    const CHART_COLORS = ['#6699ff', '#a855f7', '#22d3ee', '#34d399', '#fbbf24', '#f87171', '#818cf8'];
    const chartDefaults = {
        responsive: true, maintainAspectRatio: false,
        plugins: { legend: { labels: { color: '#7b82b0', font: { size: 11 }, boxWidth: 12 } } }
    };

    function renderCharts() {
        if (!currentData?.stats) return;
        const s = currentData.stats;

        renderDoughnut('chart-disease', s.by_disease);
        renderDoughnut('chart-modality', s.by_modality);
        renderBar('chart-trend', s.trend_by_year, 'Papers Published');
        renderDoughnut('chart-aga-modality', s.disease_modality?.['Androgenetic Alopecia'] || {});
        renderDoughnut('chart-aa-modality', s.disease_modality?.['Alopecia Areata'] || {});
    }

    function renderDoughnut(canvasId, dataObj) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return;
        if (charts[canvasId]) charts[canvasId].destroy();
        const labels = Object.keys(dataObj);
        const values = Object.values(dataObj);
        charts[canvasId] = new Chart(canvas, {
            type: 'doughnut',
            data: {
                labels,
                datasets: [{ data: values, backgroundColor: CHART_COLORS, borderColor: 'rgba(255,255,255,0.05)', borderWidth: 1 }]
            },
            options: { ...chartDefaults, cutout: '60%' }
        });
    }

    function renderBar(canvasId, dataObj, label) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return;
        if (charts[canvasId]) charts[canvasId].destroy();
        const labels = Object.keys(dataObj);
        const values = Object.values(dataObj);
        charts[canvasId] = new Chart(canvas, {
            type: 'bar',
            data: {
                labels,
                datasets: [{
                    label,
                    data: values,
                    backgroundColor: 'rgba(102,153,255,0.4)',
                    borderColor: '#6699ff',
                    borderWidth: 1,
                    borderRadius: 6
                }]
            },
            options: {
                ...chartDefaults,
                scales: {
                    x: { ticks: { color: '#7b82b0', font: { size: 11 } }, grid: { color: 'rgba(255,255,255,0.04)' } },
                    y: { ticks: { color: '#7b82b0', font: { size: 11 } }, grid: { color: 'rgba(255,255,255,0.06)' }, beginAtZero: true }
                }
            }
        });
    }

    // ── Paper Library
    const searchInput = document.getElementById('search-input');
    const filterDisease = document.getElementById('filter-disease');
    const filterModality = document.getElementById('filter-modality');
    const filterYear = document.getElementById('filter-year');
    const papersTbody = document.getElementById('papers-tbody');
    const tableCountEl = document.getElementById('table-count');
    const btnPrev = document.getElementById('btn-prev');
    const btnNext = document.getElementById('btn-next');
    const pageInfo = document.getElementById('page-info');
    let sortCol = 'pubYear'; let sortAsc = false;

    function populateYearFilter(papers) {
        const years = [...new Set(papers.map(p => p.pubYear).filter(y => y))].sort((a, b) => b - a);
        years.forEach(y => {
            const opt = document.createElement('option');
            opt.value = y; opt.textContent = y;
            filterYear.appendChild(opt);
        });
    }

    function applyFilters() {
        const q = searchInput.value.toLowerCase();
        const dis = filterDisease.value;
        const mod = filterModality.value;
        const yr = filterYear.value;
        filteredPapers = allPapers.filter(p => {
            if (dis && p.disease !== dis) return false;
            if (mod && p.modality !== mod) return false;
            if (yr && p.pubYear !== yr) return false;
            if (q && !(p.title.toLowerCase().includes(q) || (p.abstract || '').toLowerCase().includes(q))) return false;
            return true;
        });
        filteredPapers.sort((a, b) => {
            const va = a[sortCol] || ''; const vb = b[sortCol] || '';
            return sortAsc ? va.localeCompare(vb) : vb.localeCompare(va);
        });
        currentPage = 1;
        renderTable();
    }

    function makePdfFilename(title) {
        // Windows에서 금지된 문자만 제거. 나머지는 agent1이 저장한 실제 파일명과 동일하게 유지.
        // agent1_fetcher.py: 특수문자 제거 없이 {title}.pdf 그대로 저장
        const illegal = /[\\/:*?"<>|]/g;
        return title.replace(illegal, '').trim() + '.pdf';
    }

    function downloadPdf(url, filename) {
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }

    function renderTable() {
        const total = filteredPapers.length;
        const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
        const start = (currentPage - 1) * PAGE_SIZE;
        const slice = filteredPapers.slice(start, start + PAGE_SIZE);

        tableCountEl.textContent = total;
        pageInfo.textContent = `Page ${currentPage} of ${pages}`;
        btnPrev.disabled = currentPage <= 1;
        btnNext.disabled = currentPage >= pages;

        papersTbody.innerHTML = '';
        if (!slice.length) {
            papersTbody.innerHTML = '<tr><td colspan="5" class="loading-row">No papers match your filter.</td></tr>';
            return;
        }
        slice.forEach(p => {
            const tr = document.createElement('tr');
            const diseaseClass = p.disease.includes('Androgenetic') ? 'disease-aga'
                : p.disease.includes('Areata') ? 'disease-aa' : 'disease-cia';
            const diseaseLabel = p.disease.includes('Androgenetic') ? 'AGA (남성형 탈모)'
                : p.disease.includes('Areata') ? 'AA (원형 탈모)' : 'CIA (항암 탈모)';
            const pdfFilename = makePdfFilename(p.title);
            const pdfUrl = `../papers/${encodeURIComponent(pdfFilename)}`;
            tr.style.cursor = 'pointer';
            tr.title = 'PDF 다운로드 클릭 (Click to download PDF)';
            tr.innerHTML = `
                <td>${p.pubYear || '—'}</td>
                <td>
                    <span class="paper-title" title="${(p.abstract || '').replace(/"/g, '&quot;').substring(0, 300)}">${p.title}</span>
                    <span class="pdf-icon" title="PDF 다운로드">📄</span>
                </td>
                <td><span class="disease-badge ${diseaseClass}">${diseaseLabel}</span></td>
                <td><span class="tag">${p.modality}</span></td>
                <td>${p.mechanism || '—'}</td>`;
            tr.addEventListener('click', () => downloadPdf(pdfUrl, pdfFilename));
            papersTbody.appendChild(tr);
        });
    }

    // Sorting
    document.querySelectorAll('.sortable').forEach(th => {
        th.addEventListener('click', () => {
            const col = th.dataset.col;
            if (sortCol === col) sortAsc = !sortAsc; else { sortCol = col; sortAsc = true; }
            applyFilters();
        });
    });

    // Filters
    [searchInput, filterDisease, filterModality, filterYear].forEach(el => el.addEventListener('input', applyFilters));
    btnPrev.addEventListener('click', () => { if (currentPage > 1) { currentPage--; renderTable(); } });
    btnNext.addEventListener('click', () => {
        const pages = Math.ceil(filteredPapers.length / PAGE_SIZE);
        if (currentPage < pages) { currentPage++; renderTable(); }
    });

    // ── Data Polling
    async function fetchData() {
        try {
            const res = await fetch(`../analysis_results.json?t=${Date.now()}`);
            if (!res.ok) return;
            const data = await res.json();
            if (!data || !data.papers) return;

            allPapers = data.papers;
            filteredPapers = [...allPapers];

            // Header
            paperCountEl.textContent = data.total_papers;
            const updated = data.last_updated ? new Date(data.last_updated).toLocaleString('ko-KR', { month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : '—';
            lastUpdatedEl.textContent = updated;

            // Year filter
            filterYear.innerHTML = '<option value="">All Years</option>';
            populateYearFilter(allPapers);

            // Insights
            updateInsights(data);

            // Paper table
            applyFilters();

            // Charts (only if Stats tab is active)
            if (document.getElementById('tab-stats').classList.contains('active')) renderCharts();

        } catch (err) {
            console.warn('Waiting for analysis_results.json...', err);
        }
    }

    fetchData();
    setInterval(fetchData, 10000);
});
