Chart.register({
    id: 'noDataText',
    afterDraw(chart) {

        const datasets = chart.data.datasets || [];

        const hasData = datasets.some(ds =>
            (ds.data || []).some(v => Number(v) > 0)
        );

        chart.$noData = !hasData;

        if (hasData) return;

        const { ctx, width, height } = chart;

        ctx.save();
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.font = '14px sans-serif';
        ctx.fillStyle = '#9ca3af';

        ctx.fillText('No data available', width / 2, height / 2);

        ctx.restore();
    }
});
Chart.register({
    id: 'centerText',
    afterDraw(chart) {

        if (chart.config.type !== 'doughnut') return;
        if (chart.$noData) return;

        const { ctx, chartArea } = chart;

        const data = chart.data.datasets[0].data;
        const total =
            chart.$totalTested ||
            chart.$afiTotalCases ||
            data.reduce((a, b) => a + b, 0);

        if (!chartArea) return;

        const centerX = (chartArea.left + chartArea.right) / 2;
        const centerY = (chartArea.top + chartArea.bottom) / 2;

        ctx.save();

        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        ctx.font = 'bold 18px sans-serif';
        ctx.fillStyle = '#111827';
        ctx.fillText(total, centerX, centerY - 8);

        ctx.font = '12px sans-serif';
        ctx.fillStyle = '#6b7280';
        ctx.fillText('Total Positive cases', centerX, centerY + 12);

        ctx.restore();
    }
});
Chart.register(ChartDataLabels);
Chart.defaults.devicePixelRatio = 2;
export const charts = {};


function buildStackedChart(canvasId, labels, data) {
    const ctx = document.getElementById(canvasId);

    if (!ctx) return;

    if (charts[canvasId]) {
        charts[canvasId].destroy();
    }

    charts[canvasId] = new Chart(ctx, {

        type: "bar",

        data: {
            labels: labels,
            datasets: data.map(ds => ({
                ...ds,
                borderWidth: 1,
                barPercentage: 0.9,
                categoryPercentage: 0.8,
                maxBarThickness: 60
            }))
        },

        plugins: [ChartDataLabels],
        options: {
            responsive: true,
            maintainAspectRatio: false,

            layout: {
                padding: {
                    top: 20,
                    bottom: 30
                }
            },


            plugins: {
                legend: {
                    position: 'bottom',
                    align: 'center',

                    labels: {
                        padding: 20,
                        boxWidth: 10,
                        boxHeight: 10,
                        usePointStyle: true,
                        pointStyle: 'circle'
                    }
                },
                // datalabels: {
                //     color: "#000",
                //     anchor: "end",
                //     align: "top",
                //     clamp: true,
                //     clip: false,
                //     font: {
                //         weight: "bold",
                //         size: 10
                //     },
                //     formatter: function (value) {
                //         return value > 0 ? value : null;
                //     }
                // }
                datalabels: {
                    display: false
                }
            },

            scales: {
                x: {
                    stacked: true
                },
                y: {
                    stacked: true,
                    beginAtZero: true
                }
            }
        }
    });
}
export function buildChart(id, type, labels, data) {

    const ctx = document.getElementById(id);
    if (!ctx) return;

    Chart.getChart(id)?.destroy();

    const hasData = data && data.some(v => Number(v) > 0);

    if (!hasData) {
        labels = [];
        data = [];
    }
    const isHorizontal = id === 'sexChart' || id === 'influenzaSubtypeDistribution';
    const isAgeChart = id === 'ageChart';
    const isSentinelChart = id === 'sentinelChart';
    const options = {
        responsive: true,
        maintainAspectRatio: false,

        layout: {
            padding: 30
        },


        indexAxis: isHorizontal ? 'y' : 'x',
        plugins: {

            legend: {
                position: isAgeChart || isSentinelChart ? 'left' : 'bottom',
                align: 'center',
                display: (ctx) => {
                    const chart = ctx.chart;

                    if (!(chart.config.type === 'pie' || chart.config.type === 'doughnut')) {
                        return false;
                    }

                    return !chart.$noData;
                },
                labels: {
                    padding: 14,
                    boxWidth: 10,
                    boxHeight: 10,
                    usePointStyle: true,
                    pointStyle: 'circle',
                    font: {
                        size: 11
                    }
                }
            },
            datalabels: {
                color: "#282626",
                offset: 6,
                clip: false,
                display: (ctx) => {
                    const chart = ctx.chart;
                    if (chart.$noData) return false;
                    if (chart.config.type === 'bar') return true;
                    return !chart.$noData;
                },
                anchor: (ctx) => {
                    const type = ctx.chart.config.type;

                    if (type === 'doughnut' || type === 'pie') {
                        return 'center';
                    }

                    return 'end';
                },

                align: (ctx) => {
                    const type = ctx.chart.config.type;
                    if (type === 'doughnut' || type === 'pie') {
                        return 'center';
                    }
                    if (type === 'bar') {
                        return ctx.chart.options.indexAxis === 'y' ? 'right' : 'end';
                    }
                    return 'center';
                },
                font: {
                    size: 10,
                    weight: '600'
                },

                formatter: (value, ctx) => {
                    if (ctx.chart.$noData) return '';

                    const data = ctx.chart.data.datasets[0].data;
                    const total =
                        ctx.chart.$totalTested ||
                        data.reduce((a, b) => a + b, 0);

                    if (!total) return '';

                    return ((value / total) * 100).toFixed(1) + '%';
                }
            }
        }
    };
    if (type === 'bar') {
        options.scales = {
            x: {
                beginAtZero: true,
                grid: {
                    display: false
                }
            },
            y: {
                grid: {
                    color: '#f3f4f6'
                }
            }
        };
    }
    if (type === 'doughnut') {
        options.cutout = '70%';
        options.maintainAspectRatio = false;
        options.elements = {
            arc: {
                borderWidth: (ctx) => ctx.chart.$noData ? 0 : 1
            }

        };
    }

    charts[id] = new Chart(ctx, {

        type: type,
        data: {
            labels: labels,
            datasets: [{
                data: data,
                borderWidth: 2,
                tension: 0.3,
                barPercentage: 0.8,
                categoryPercentage: 0.6,
                maxBarThickness: 50
            }]
        },
        options: options
    });
    charts[id].$totalTested = 0;
}
export function buildMixedTrendChart(canvasId, labels, samples, lines) {

    const ctx = document.getElementById(canvasId);
    if (!ctx) return;

    if (charts[canvasId]) charts[canvasId].destroy();

    const datasets = [];

    lines.forEach(line => {
        datasets.push({
            type: 'line',
            label: line.label,
            data: line.data,
            borderColor: line.color,
            backgroundColor: line.color,
            tension: 0.4,
            yAxisID: 'y1',
            pointStyle: 'line'
        });
    });

    datasets.push({
        type: 'bar',
        label: 'Total Cases',
        data: samples,
        backgroundColor: '#007ce8',
        maxBarThickness: 60,
        yAxisID: 'y',

    });

    charts[canvasId] = new Chart(ctx, {
        data: { labels, datasets },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: { position: 'bottom' },
                datalabels: {
                    display: false
                }
            },
            scales: {
                y: { title: { display: true, text: 'Cases' } },
                y1: {
                    position: 'right',
                    grid: { drawOnChartArea: false },
                    title: { display: true, text: '% Positivity' }
                }
            }
        }
    });
}

export function buildDistributionChart(
    id,
    type,
    rows,
    labelKey,
    valueKey = 'total',
    colorResolver = null
) {

    const labels = rows.map(r => r[labelKey]);
    buildChart(
        id,
        type,
        labels,
        rows.map(r => r[valueKey])
    );

    if (!charts[id]) return;

    charts[id].data.datasets[0].backgroundColor = labels.map(
        (label, index) =>
            colorResolver
                ? colorResolver(label, index)
                : COLORS[index % COLORS.length]
    );

    charts[id].update();
}
export function getSubtypeColor(label, index = 0) {

    return SUBTYPE_COLORS[label]
        || COLORS[index % COLORS.length];
}

export const COLORS = [

    '#10b981', // emerald
    '#ef4444',
    '#f59e0b', // amber
    '#ef4444', // red
    '#8b5cf6', // violet
    '#14b8a6', // teal
    '#f97316', // orange
    '#84cc16', // lime
    '#e11dba', // fuchsia
    '#f6f63b', // yellow
    '#0ea5e9', // sky
    '#22c55e', // green
    '#a855f7', // purple
    '#ec4899', // pink
    '#06b6d4', // cyan
    '#65a30d', // olive
    '#dc2626', // dark red
    '#1d4ed8', // strong blue
    '#7c3aed', // deep violet
    '#059669', // dark emerald
    '#c2410c', // burnt orange
    '#be123c', // rose
    '#4338ca', // indigo
    '#0f766e', // dark teal
    '#9333ea', // bright purple
    '#15803d', // forest green
    '#ea580c', // deep orange
    '#0284c7', // ocean blue
    '#ca8a04', // mustard
    '#db2777'  // magenta
];
export const SUBTYPE_COLORS = {
    'A/H1N1pdm': '#f0d401',
    'A/H3N2': '#00ffff',
    'A/H9N2': '#2563eb',
    'A/H5N1': '#dc2626',
    'A/Unsubtypable': '#f455d7',
    'B/Yam': '#9333ea',
    'B/Vic': '#086037',
    'B/VIC': '#086037',
    'B/Unsubtypable': '#66ff00',
    'B/Victoria': '#9333ea',
    'H1N1pdm': '#f0d401',
    'H3N2': '#00ffff',
    'H9N2': '#2563eb',
    'J.2.4': '#8c6060',
    'K': '#55f49a',
};

export const SURVEILLANCE_COLORS = {
    'LBM': '#f0d401',
    'ILI': '#2563eb',
    'SARI': '#dc2626',
    'NDS': '#9333ea',
    'AFI': '#086037',
    'SEQ': '#66ff00'
};
export function buildPeriodLabels(data, startYear, endYear) {

    const yearlyView = (endYear - startYear) >= 5;

    if (yearlyView) {

        const labels = [...new Set(
            data.flatMap(program =>
                program.map(row => row.year)
            )
        )].sort((a, b) => a - b);

        return {
            yearlyView,
            labels
        };
    }

    const labelsSet = new Set();

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

    return {
        yearlyView,
        labels: [...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;
        })
    };
}
export function buildPeriods(data, field, startYear, endYear) {

    const yearlyView = (endYear - startYear) >= 5;

    const periods = yearlyView
        ? [...new Set(
            data.map(row => row[field].split('-')[0])
        )].sort((a, b) => a - b)
        : [...new Set(
            data.map(row => row[field])
        )].sort();

    return {
        yearlyView,
        periods
    };
}