import * as Charts from "./dashboard/globals.js";
const standardPrograms = ['SARI', 'ILI', 'LBM', 'AFI', 'NDS'];
const programCode = (window.PROGRAM_CODE || '').trim().toUpperCase();

let map;

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

    if (!standardPrograms.includes(programCode)) return;

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

        document.querySelectorAll(".report-period")
            .forEach(el => {
                el.textContent =
                    `Week ${startWeek} of ${startYear} to Week ${endWeek} of ${endYear}`;
            });

        fetch(
            `/api/dashboard/program?surveillance_id=${window.SURVEILLANCE_ID}` +
            `&start_year=${startYear}&start_week=${startWeek}` +
            `&end_year=${endYear}&end_week=${endWeek}`
        )
            .then(res => res.json())
            .then(programCode === 'AFI'
                ? renderAFIDashboard
                : renderDashboard
            )
            .catch(err => console.error("Dashboard API error:", err));

    });

});

function renderTrend(valueId, changeId, current, previous, suffix = '') {

    const valueEl = document.getElementById(valueId);
    const changeEl = document.getElementById(changeId);

    if (!valueEl || !changeEl) return;

    valueEl.textContent = current + suffix;

    if (!previous) {
        changeEl.innerHTML = "— No previous data";
        changeEl.className = "text-muted";
        return;
    }

    const diff = current - previous;
    const percent = ((diff / previous) * 100).toFixed(1);

    if (diff > 0) {
        changeEl.innerHTML = `↑ +${percent}% from previous week`;
        changeEl.className = "text-success";
    }
    else if (diff < 0) {
        changeEl.innerHTML = `↓ ${percent}% from previous week`;
        changeEl.className = "text-danger";
    }
    else {
        changeEl.innerHTML = "— No significant change";
        changeEl.className = "text-muted";
    }
}

function renderSummary(summary = {}) {

    const mappings = [
        ['totalCases', 'casesChange', summary.cases],
        ['influenzaRate', 'influenzaChange', summary.influenza_rate, '%'],
        ['covidRate', 'covidChange', summary.covid_rate, '%'],
        ['hospitalRate', 'hospitalChange', summary.hospital_rate, '%'],
        ['icuRate', 'icuChange', summary.icu_rate, '%'],
        ['positivityRate', 'positivityChange', summary.positivity_rate, '%']
    ];

    mappings.forEach(([valueId, changeId, data = {}, suffix = '']) => {
        renderTrend(
            valueId,
            changeId,
            data.current || 0,
            data.previous || 0,
            suffix
        );
    });
}
function renderDashboard(data = {}) {

    renderProgramTrend(data.trend || []);
    renderSummary(data.summary);
    renderProvinceHeatmap(data.province_distribution || []);

    Charts.buildDistributionChart(
        'pathogenChart',
        'doughnut',
        (data.pathogen_distribution || [])
            .sort((a, b) => b.total - a.total),
        'pathogen',
        'total',
        Charts.getSubtypeColor

    );

    Charts.buildDistributionChart(
        'ageChart',
        'doughnut',
        data.age_distribution || [],
        'age_group'
    );

    Charts.buildDistributionChart(
        'sexChart',
        'bar',
        data.sex_distribution || [],
        'patient_sex'
    );

    Charts.buildDistributionChart(
        'subtypeChart',
        'bar',
        data.subtype_distribution || [],
        'subtype',
        'total',
        Charts.getSubtypeColor
    );

    Charts.buildDistributionChart(
        'sentinelChart',
        'pie',
        data.sentinel_sites || [],
        'name'
    );


}
function renderAFIDashboard(data = {}) {

    const trend = data.afi_trend || {};
    const positivity = data.afi_case_trend || {};

    renderAFITrend(
        data.afi_case_trend.section_1,
        'afiSection1Trend',
        Chart.COLORS,
        'trend'
    );

    renderAFITrend(
        data.afi_case_trend.section_2,
        'afiSection2Trend',
        Chart.COLORS,
        'trend'
    );

    renderAFITrend(
        data.afi_case_trend.section_3,
        'afiSection3Trend',
        Chart.COLORS,
        'trend'
    );

    // DOUGHNUTS
    renderAFITrend(
        data.afi_case_trend.section_1,
        'afiPcrChart',
        Chart.COLORS,
        'donut'
    );

    renderAFITrend(
        data.afi_case_trend.section_2,
        'afiMultiplexChart',
        Chart.COLORS,
        'donut'
    );

    renderAFITrend(
        data.afi_case_trend.section_3,
        'afiElisaChart',
        Chart.COLORS,
        'donut'
    );


    renderSummary(data.summary);
    renderProvinceHeatmap(data.province_distribution);
    renderDemographics(data);
    renderPathogenChart(data.pathogen_distribution || []);
    renderSentinel(data.sentinel_sites || []);
    renderSubtypeChart(data.subtype_distribution || []);
}
function normalizeProvince(name, validSet) {

    if (!name || !validSet) return null;

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

    const raw = name.trim();

    const provinceMap = {
        "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 (provinceMap[key] && validSet.has(provinceMap[key])) {
        return provinceMap[key];
    }

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

    return match || null;
}
window.normalizeProvince = normalizeProvince;

function renderProvinceHeatmap(rows = []) {

    window.latestProvinceData = rows;

    if (map) {
        map.remove();
    }

    map = L.map('provinceMap')
        .setView([12.7, 104.9], 7);
    window.map = map;
    L.tileLayer(
        'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        {
            attribution: '&copy; OpenStreetMap contributors'
        }
    ).addTo(map);

    addProvinceLegend();

    fetch('/geo/cambodia_provinces.geojson')
        .then(r => r.json())
        .then(geo => {

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

            window.validProvinces = validProvinces;

            const totals = {};

            rows.forEach(r => {

                const province = normalizeProvince(
                    r.patient_province,
                    validProvinces
                );

                if (!province) return;

                totals[province] ??= {
                    total: 0,
                    positive: 0
                };

                totals[province].total += Number(r.total || 0);
                totals[province].positive += Number(r.positive || 0);

            });

            const getColor = value => {

                if (value > 50) return "#b91c1c";
                if (value >= 10) return "#ef4444";
                if (value > 0) return "#fecaca";

                return "#f3f4f600";
            };

            window.provinceLayer = L.geoJSON(geo, {

                style: feature => {

                    const province =
                        feature.properties.ADM1_EN;

                    const value =
                        totals[province]?.total || 0;

                    return {
                        color: "#444",
                        weight: 1.5,
                        fillColor: getColor(value),
                        fillOpacity: 0.8
                    };
                },

                onEachFeature: (feature, layer) => {

                    const province =
                        feature.properties.ADM1_EN;

                    const total =
                        totals[province]?.total || 0;

                    const positive =
                        totals[province]?.positive || 0;

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

                    layer.bindTooltip(`
                        ${province}<br>
                        Total: ${total}<br>
                        Positivity: ${percent}%
                    `);

                }

            }).addTo(map);

        });

}
function addProvinceLegend() {

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

    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;
                ">
                    Cases
                </div>

                <div style="
                    display:flex;
                    align-items:center;
                    margin-bottom:4px;
                ">
                    <span style="
                        width:12px;
                        height:12px;
                        background:#b91c1c;
                        display:inline-block;
                        margin-right:6px;
                    "></span>
                    > 50
                </div>

                <div style="
                    display:flex;
                    align-items:center;
                    margin-bottom:4px;
                ">
                    <span style="
                        width:12px;
                        height:12px;
                        background:#ef4444;
                        display:inline-block;
                        margin-right:6px;
                    "></span>
                    10 – 50
                </div>

                <div style="
                    display:flex;
                    align-items:center;
                    margin-bottom:4px;
                ">
                    <span style="
                        width:12px;
                        height:12px;
                        background:#fecaca;
                        display:inline-block;
                        margin-right:6px;
                    "></span>
                    1 – 9
                </div>

                <div style="
                    display:flex;
                    align-items:center;
                ">
                    <span style="
                        width:12px;
                        height:12px;
                        background:#f3f4f6;
                        display:inline-block;
                        margin-right:6px;
                    "></span>
                    0
                </div>

            </div>
        `;

        return div;
    };

    legend.addTo(map);
}
function renderProgramTrend(rows = []) {

    if (!rows.length) {

        Charts.buildMixedTrendChart(
            'trendChart',
            [],
            [],
            []
        );

        return;
    }

    /*
    |--------------------------------------------------------------------------
    | YEARLY VIEW
    |--------------------------------------------------------------------------
    */

    const years = [...new Set(
        rows.map(r => Number(r.year))
    )];

    const totalYears =
        Math.max(...years) - Math.min(...years);

    const useYearlyView =
        totalYears >= 5;

    /*
    |--------------------------------------------------------------------------
    | LABELS
    |--------------------------------------------------------------------------
    */

    let labels;

    if (useYearlyView) {

        labels = [...new Set(
            rows.map(r => String(r.year))
        )].sort();

    } else {

        labels = [...new Set(
            rows.map(r =>
                `${r.year}-W${r.period}`
            )
        )].sort((a, b) => {

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

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

            if (yearA !== yearB) {
                return yearA - yearB;
            }

            return weekA - weekB;

        });

    }

    /*
    |--------------------------------------------------------------------------
    | TOTAL SAMPLES
    |--------------------------------------------------------------------------
    */

    const samples = labels.map(label => {

        if (useYearlyView) {

            return rows
                .filter(r =>
                    String(r.year) === label
                )
                .reduce(
                    (sum, r) =>
                        sum + Number(r.total_samples || 0),
                    0
                );

        }

        const row = rows.find(r =>
            `${r.year}-W${r.period}` === label
        );

        return row?.total_samples || 0;

    });

    /*
    |--------------------------------------------------------------------------
    | LINES
    |--------------------------------------------------------------------------
    */

    const lines = [

        {
            label: 'Influenza %',

            data: labels.map(label => {

                if (useYearlyView) {

                    const filtered = rows.filter(r =>
                        String(r.year) === label
                    );

                    const total =
                        filtered.reduce(
                            (sum, r) =>
                                sum + Number(r.influenza_rate || 0),
                            0
                        );

                    return filtered.length
                        ? total / filtered.length
                        : 0;
                }

                const row = rows.find(r =>
                    `${r.year}-W${r.period}` === label
                );

                return row?.influenza_rate || 0;

            }),

            color: '#ef4444'
        },

        {
            label: 'SARS-CoV-2 %',

            data: labels.map(label => {

                if (useYearlyView) {

                    const filtered = rows.filter(r =>
                        String(r.year) === label
                    );

                    const total =
                        filtered.reduce(
                            (sum, r) =>
                                sum + Number(r.covid_rate || 0),
                            0
                        );

                    return filtered.length
                        ? total / filtered.length
                        : 0;
                }

                const row = rows.find(r =>
                    `${r.year}-W${r.period}` === label
                );

                return row?.covid_rate || 0;

            }),

            color: '#10b981'
        }

    ];

    /*
    |--------------------------------------------------------------------------
    | NDS EXTRA LINES
    |--------------------------------------------------------------------------
    */

    if (programCode === 'NDS') {

        lines.push(

            {
                label: 'EV %',

                data: labels.map(label => {

                    if (useYearlyView) {

                        const filtered = rows.filter(r =>
                            String(r.year) === label
                        );

                        const total =
                            filtered.reduce(
                                (sum, r) =>
                                    sum + Number(r.ev_rate || 0),
                                0
                            );

                        return filtered.length
                            ? total / filtered.length
                            : 0;
                    }

                    const row = rows.find(r =>
                        `${r.year}-W${r.period}` === label
                    );

                    return row?.ev_rate || 0;

                }),

                color: '#f59e0b'
            },

            {
                label: 'Mpox %',

                data: labels.map(label => {

                    if (useYearlyView) {

                        const filtered = rows.filter(r =>
                            String(r.year) === label
                        );

                        const total =
                            filtered.reduce(
                                (sum, r) =>
                                    sum + Number(r.mpox_rate || 0),
                                0
                            );

                        return filtered.length
                            ? total / filtered.length
                            : 0;
                    }

                    const row = rows.find(r =>
                        `${r.year}-W${r.period}` === label
                    );

                    return row?.mpox_rate || 0;

                }),

                color: '#8b5cf6'
            }

        );

    }

    Charts.buildMixedTrendChart(
        'trendChart',
        labels,
        samples,
        lines
    );

}

function renderAFITrend(
    data = {},
    canvasId,
    COLORS,
    type = 'trend'
) {

    /*
    |--------------------------------------------------------------------------
    | DATA
    |--------------------------------------------------------------------------
    */

    const rows =
        data.rows || [];

    const totals =
        data.totals || [];

    /*
    |--------------------------------------------------------------------------
    | EMPTY
    |--------------------------------------------------------------------------
    */

    if (!totals.length) {

        if (type === 'donut') {

            Charts.buildDistributionChart(
                canvasId,
                'doughnut',
                [],
                'pathogen',
                'total'
            );

        } else {

            Charts.buildMixedTrendChart(
                canvasId,
                [],
                [],
                []
            );

        }

        return;
    }

    /*
    |--------------------------------------------------------------------------
    | LABELS
    |--------------------------------------------------------------------------
    */

    const labels = [...new Set(

        totals.map(r =>

            `${r.year}-W${r.period}`

        )

    )].sort((a, b) => {

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

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

        if (yearA !== yearB) {
            return yearA - yearB;
        }

        return weekA - weekB;

    });

    /*
    |--------------------------------------------------------------------------
    | TOTAL CASES (BLUE BARS)
    |--------------------------------------------------------------------------
    */

    const totalCases = labels.map(label => {

        const row = totals.find(r =>

            `${r.year}-W${r.period}`
            === label

        );

        return Number(
            row?.total_cases || 0
        );

    });

    /*
    |--------------------------------------------------------------------------
    | DONUT
    |--------------------------------------------------------------------------
    */

    if (type === 'donut') {

        const grouped = {};

        rows.forEach(r => {

            const pathogen =
                r.pathogen || 'Unknown';

            grouped[pathogen] ??= 0;

            grouped[pathogen] +=
                Number(r.total_positive || 0);

        });

        const donutRows =

            Object.entries(grouped)

                .map(([pathogen, total]) => ({
                    pathogen,
                    total
                }));

        Charts.buildDistributionChart(
            canvasId,
            'doughnut',
            donutRows,
            'pathogen',
            'total'
        );

        /*
        |--------------------------------------------------------------------------
        | DONUT CENTER TOTAL
        |--------------------------------------------------------------------------
        |
        | MUST MATCH SUM OF BLUE BARS
        |
        */

        const donutTotal = rows.reduce(
            (sum, row) => sum + Number(row.total_positive || 0),
            0
        );

        if (Charts.charts[canvasId]) {

            Charts.charts[canvasId].$afiTotalCases =
                donutTotal;

            Charts.charts[canvasId].update();

        }

        return;
    }

    /*
    |--------------------------------------------------------------------------
    | PATHOGENS
    |--------------------------------------------------------------------------
    */

    const pathogens = [

        ...new Set(
            rows.map(r => r.pathogen)
        )

    ];

    /*
    |--------------------------------------------------------------------------
    | LINES
    |--------------------------------------------------------------------------
    */

    const lines = pathogens.map(
        (pathogen, i) => ({

            label: `${pathogen} %`,

            data: labels.map(label => {

                const row = rows.find(r =>

                    `${r.year}-W${r.period}`
                    === label

                    && r.pathogen === pathogen

                );

                return Number(
                    row?.positivity_rate || 0
                );

            }),

            color:
                Charts.COLORS[
                i % Charts.COLORS.length
                ]

        })
    );

    /*
    |--------------------------------------------------------------------------
    | BUILD
    |--------------------------------------------------------------------------
    */

    Charts.buildMixedTrendChart(
        canvasId,
        labels,
        totalCases,
        lines
    );

}


function renderPathogenChart(rows = []) {
    Charts.buildDistributionChart(
        'pathogenChart',
        'doughnut',
        rows,
        'pathogen'
    );
}
function renderSentinel(rows = []) {
    Charts.buildDistributionChart(
        'sentinelChart',
        'pie',
        rows,
        'name'
    );
}
function renderSubtypeChart(rows = []) {

    rows.forEach(row => {
        if (row.subtype === 'B/VIC') {
            row.subtype = 'B/Vic';
        }
    });

    Charts.buildDistributionChart(
        'subtypeChart',
        'bar',
        rows,
        'subtype',
        'total',
        Charts.getSubtypeColor
    );
}
function renderDemographics(data = {}) {

    Charts.buildDistributionChart(
        'ageChart',
        'doughnut',
        data.age_distribution || [],
        'age_group'
    );

    Charts.buildDistributionChart(
        'sexChart',
        'bar',
        data.sex_distribution || [],
        'patient_sex'
    );
}