let trendChart;
let map;

/*
|--------------------------------------------------------------------------
| Load Summary Cards
|--------------------------------------------------------------------------
*/

function loadSummary() {
    fetch('/api/dashboard/summary')
        .then(res => res.json())
        .then(data => {

            let html = '';
            const alerts = [];

            data.forEach(item => {

                let trendColor = 'text-secondary';

                if (item.percent_change > 0) trendColor = 'text-danger';
                if (item.percent_change < 0) trendColor = 'text-success';

                html += `
                    <div class="col-md-2 mb-3">
                        <div class="card shadow-sm h-100">
                            <div class="card-body">

                                <div class="d-flex justify-content-between">

                                    <div>
                                        <h6 class="fw-bold">${item.code}</h6>
                                        <h3 class="mb-1">${item.current_total}</h3>
                                        <small class="text-muted">Last 7 days</small>
                                    </div>

                                    <div class="text-end">

                                        <div class="${trendColor} fw-bold">
                                            ${item.percent_change > 0 ? '▲' : item.percent_change < 0 ? '▼' : '–'}
                                            ${Math.abs(item.percent_change)}%
                                        </div>

                                        <small class="text-muted">
                                            ${item.previous_total ?? 0} last week
                                        </small>

                                    </div>

                                </div>

                            </div>
                        </div>
                    </div>
                `;

                window._summaryData = data;
                updateAlerts();

            });

            document.getElementById('summary_cards').innerHTML = html;

            renderAlerts(alerts);

        });
}

/*
|--------------------------------------------------------------------------
| Load Trend Chart
|--------------------------------------------------------------------------
*/

function loadTrend(periodType, startYear, startWeek, endYear, endWeek) {

    fetch(`/api/dashboard/trend?period_type=${periodType}&start_year=${startYear}&start_week=${startWeek}&end_year=${endYear}&end_week=${endWeek}`)
        .then(res => res.json())
        .then(data => {

            if (trendChart) trendChart.destroy();

            const labelsSet = new Set();

            Object.values(data).forEach(program => {
                program.forEach(row => {
                    labelsSet.add(`${row.year}-${row.period}`);
                });
            });

            const labels = Array.from(labelsSet).sort((a, b) => {

                const [yearA, weekA] = a.split('-').map(Number);
                const [yearB, weekB] = b.split('-').map(Number);

                if (yearA !== yearB) return yearA - yearB;
                return weekA - weekB;

            });

            const colors = {
                SARI: '#2563eb',
                ILI: '#10b981',
                LBM: '#9333ea'
            };

            const datasets = [];

            const allowedPrograms = ['SARI', 'ILI', 'LBM'];

            Object.keys(data).forEach(code => {

                if (!allowedPrograms.includes(code)) return;

                const values = labels.map(label => {
                    const found = data[code].find(row => `${row.year}-${row.period}` === label);
                    return found ? found.total : 0;
                });

                datasets.push({
                    label: code,
                    data: values,
                    borderColor: colors[code],
                    backgroundColor: colors[code],
                    borderWidth: 3,
                    pointRadius: 4,
                    fill: false,
                    tension: 0.3
                });

            });

            const displayLabels = labels.map(l => {
                const [year, week] = l.split('-');
                return `W${String(week).padStart(2, '0')}`;
            });

            trendChart = new Chart(document.getElementById('trendChart'), {
                type: 'line',
                data: {
                    labels: displayLabels,
                    datasets: datasets
                },
                options: {
                    responsive: true,
                    plugins: {
                        legend: { position: 'bottom' }
                    },
                    interaction: {
                        mode: 'index',
                        intersect: false
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            ticks: { stepSize: 1 }
                        },
                        x: { grid: { display: false } }
                    }
                }
            });

        });
}
function updateAlerts() {

    if (!window._summaryData || !window._provinceData) return;

    const raw = buildAlerts(window._summaryData, window._provinceData);
    const finalAlerts = processAlerts(raw);

    renderAlerts(finalAlerts);
}
function generateAlerts(data) {

    const alerts = [];

    // -------------------------
    // 1. Program-level alerts
    // -------------------------
    const summary = data.summary || {};

    const programs = [
        { key: 'influenza_rate', label: 'Influenza' },
        { key: 'covid_rate', label: 'COVID-19' },
        { key: 'positivity_rate', label: 'Overall positivity' }
    ];

    programs.forEach(p => {
        const current = summary[p.key]?.current || 0;
        const previous = summary[p.key]?.previous || 0;

        const diff = previous ? ((current - previous) / previous) * 100 : 0;

        if (current >= 15) {
            alerts.push(`🔴 High ${p.label} (${current}%)`);
        } else if (current >= 10) {
            alerts.push(`🟠 Moderate ${p.label} (${current}%)`);
        }

        if (diff >= 10) {
            alerts.push(`🟡 Increasing ${p.label} (+${diff.toFixed(1)}%)`);
        }
    });

    // -------------------------
    // 2. Province-level alerts
    // -------------------------
    const provinces = data.province_distribution || [];

    const top = [...provinces]
        .sort((a, b) => b.total - a.total)
        .slice(0, 3);

    top.forEach(p => {

        const percent = p.total
            ? ((p.positive / p.total) * 100)
            : 0;

        if (percent >= 15) {
            alerts.push(`🔴 High positivity in ${p.patient_province} (${percent.toFixed(1)}%)`);
        } else if (percent >= 10) {
            alerts.push(`🟠 Moderate positivity in ${p.patient_province}`);
        }

        if (p.total >= 50) {
            alerts.push(`🟡 High case volume in ${p.patient_province} (${p.total})`);
        }
    });

    // -------------------------
    // fallback
    // -------------------------
    if (!alerts.length) {
        alerts.push("🟢 No unusual activity detected");
    }

    return alerts;
}
function createAlert(type, message, priority) {
    return { type, message, priority };
}

function buildAlerts(summaryData, provinceData) {

    const alerts = [];

    // -------------------------
    // 1. Program alerts
    // -------------------------
    summaryData.forEach(item => {

        // 🔴 High activity
        if (item.current_total >= 80) {
            alerts.push(createAlert(
                'high',
                `High ${item.code} activity (${item.current_total} cases)`,
                1
            ));
        }

        // 🟠 Moderate
        else if (item.current_total >= 40) {
            alerts.push(createAlert(
                'moderate',
                `${item.code} activity elevated (${item.current_total})`,
                2
            ));
        }

        // 🟡 Increasing trend
        if (item.percent_change >= 10) {
            alerts.push(createAlert(
                'trend',
                `Increasing ${item.code} (+${item.percent_change}%)`,
                3
            ));
        }

    });

    // -------------------------
    // 2. Province alerts
    // -------------------------
    const top = [...provinceData]
        .sort((a, b) => b.total - a.total)
        .slice(0, 5);

    top.forEach(p => {

        const percent = p.total
            ? ((p.positive / p.total) * 100)
            : 0;

        // 🔴 High positivity
        if (percent >= 15) {
            alerts.push(createAlert(
                'high',
                `High positivity in ${p.patient_province} (${percent.toFixed(1)}%)`,
                1
            ));
        }

        // 🟠 Moderate positivity
        else if (percent >= 10) {
            alerts.push(createAlert(
                'moderate',
                `Moderate positivity in ${p.patient_province}`,
                2
            ));
        }

        // 🟡 High volume
        if (p.total >= 50) {
            alerts.push(createAlert(
                'volume',
                `High case volume in ${p.patient_province} (${p.total})`,
                3
            ));
        }

    });

    return alerts;
}
function processAlerts(alerts) {

    const seen = new Set();

    const unique = alerts.filter(a => {
        if (seen.has(a.message)) return false;
        seen.add(a.message);
        return true;
    });

    // sort by priority
    unique.sort((a, b) => a.priority - b.priority);

    // limit to top 5
    return unique.slice(0, 5);
}
function renderAlerts(alerts) {

    const container = document.getElementById('alertsList');
    if (!container) return;

    if (!alerts.length) {
        container.innerHTML = `
            <li class="list-group-item text-success">
                🟢 No unusual activity detected
            </li>
        `;
        return;
    }

    const colorMap = {
        high: 'text-danger',
        moderate: 'text-warning',
        trend: 'text-primary',
        volume: 'text-secondary'
    };

    container.innerHTML = alerts.map(a => `
        <li class="list-group-item ${colorMap[a.type] || ''}">
            ${a.type === 'high' ? '🔴' :
            a.type === 'moderate' ? '🟠' :
                a.type === 'trend' ? '🟡' :
                    '🔵'}
            ${a.message}
        </li>
    `).join('');
}


/*
|--------------------------------------------------------------------------
| Province Map Helpers
|--------------------------------------------------------------------------
*/
function getPositivityColor(p) {
    if (p > 20) return "#b91c1c";
    if (p > 10) return "#ef4444";
    if (p > 5) return "#f59e0b";
    if (p > 0) return "#84cc16";
    return "#9ca3af";
}
function normalizeProvince(name, validSet) {
    if (!name || !validSet) return null;

    const clean = str =>
        str.toLowerCase().replace(/\s+/g, '');

    const raw = name.trim();

    const map = {
        "kepville": "Kep",
        "sihanoukville": "Preah Sihanouk",
        "sihanoukvillecity": "Preah Sihanouk",
        "krongpailin": "Pailin",
        "mondulkiri": "Mondulkiri",
        "odormeanchey": "Oddar Meanchey",
        "tbongkhmom": "Tboung Khmum",
        "tboungkhmum": "Tboung Khmum",
        "rattanakiri": "Ratanak Kiri"
    };

    const key = clean(raw);

    if (map[key] && validSet.has(map[key])) {
        return map[key];
    }

    const match = [...validSet].find(p => clean(p) === key);

    return match || null;
}
function getRadius(total) {
    if (!total) return 0;
    const r = Math.sqrt(total);
    return Math.max(4, Math.min(r * 2, 22));
}
function addPositivityLegend() {

    const legend = L.control({ position: "bottomleft" });

    legend.onAdd = function () {

        const div = L.DomUtil.create("div", "map-legend");

        div.innerHTML = `
            <div style="background:white;padding:10px 12px;border-radius:6px;
                        box-shadow:0 2px 6px rgba(0,0,0,0.2);font-size:12px;">
                <div style="font-weight:600;margin-bottom:6px;">Positivity</div>

                <div><span style="border:3px solid #b91c1c;width:12px;height:12px;display:inline-block;margin-right:6px;"></span>> 20%</div>
                <div><span style="border:3px solid #ef4444;width:12px;height:12px;display:inline-block;margin-right:6px;"></span>10–20%</div>
                <div><span style="border:3px solid #f59e0b;width:12px;height:12px;display:inline-block;margin-right:6px;"></span>5–10%</div>
                <div><span style="border:3px solid #84cc16;width:12px;height:12px;display:inline-block;margin-right:6px;"></span>0–5%</div>
                <div><span style="border:3px solid #9ca3af;width:12px;height:12px;display:inline-block;margin-right:6px;"></span>0%</div>
            </div>
        `;

        return div;
    };

    legend.addTo(map);
}
/*
|--------------------------------------------------------------------------
| Province Map
|--------------------------------------------------------------------------
*/

function loadProvinceMap(startYear, startWeek, endYear, endWeek) {

    if (map) map.remove();

    map = L.map('provinceMap').setView([12.7, 104.9], 7);
    addPositivityLegend();

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© OpenStreetMap'
    }).addTo(map);

    Promise.all([
        fetch('/geo/cambodia_provinces.geojson').then(r => r.json()),
        fetch(`/api/dashboard/province-circles?start_year=${startYear}&start_week=${startWeek}&end_year=${endYear}&end_week=${endWeek}`).then(r => r.json())
    ])
        .then(([geojson, data]) => {
            window._provinceData = data;
            updateAlerts();

            const validProvinces = new Set(
                geojson.features.map(f => f.properties.ADM1_EN)
            );

            L.geoJSON(geojson, {
                style: {
                    fillOpacity: 0,
                    color: '#ccc',
                    weight: 1,
                    interactive: false
                },

                onEachFeature: function (feature, layer) {

                    const province = feature.properties.ADM1_EN;
                    const center = layer.getBounds().getCenter();

                    const rows = data.filter(d => {
                        if (![1, 2, 3].includes(d.surveillance_id)) return false;

                        const name = normalizeProvince(d.patient_province, validProvinces);
                        return name === province;
                    });

                    const offsets = { 1: -0.15, 2: 0, 3: 0.15 };

                    const colors = {
                        1: '#2563eb',
                        2: '#10b981',
                        3: '#9333ea'
                    };

                    rows.forEach(row => {

                        const percent = row.total
                            ? ((row.positive / row.total) * 100).toFixed(1)
                            : 0;

                        const offset = offsets[row.surveillance_id] ?? 0;

                        const lat = center.lat;
                        const lng = center.lng + offset;

                        const programName =
                            row.surveillance_id === 1 ? 'SARI' :
                                row.surveillance_id === 2 ? 'ILI' : 'LBM';

                        L.circleMarker([lat, lng], {
                            radius: getRadius(row.total),
                            fillColor: colors[row.surveillance_id],
                            color: getPositivityColor(percent),
                            weight: 2,
                            fillOpacity: 0.9
                        })
                            .bindTooltip(`
                        <strong>${province}</strong><br>
                        ${programName}<br>
                        Cases: ${row.total}<br>
                        Positivity: ${percent}%
                    `)
                            .addTo(map);

                    });

                }

            }).addTo(map);

        });

}


/*
|--------------------------------------------------------------------------
| Initialize Dashboard
|--------------------------------------------------------------------------
*/

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

    loadSummary();

    new DashboardFilter((startYear, startWeek, endYear, endWeek) => {

        loadTrend('week', startYear, startWeek, endYear, endWeek);
        loadProvinceMap(startYear, startWeek, endYear, endWeek);

    });

});