(function(){
    const $month = document.getElementById('hbdev-month');
    const $apply = document.getElementById('hbdev-apply');
    const $chartType = document.getElementById('hbdev-chart-type');

    const $kpiTotal   = document.getElementById('kpi-total');
    const $kpiIncome  = document.getElementById('kpi-income');
    const $kpiExpense = document.getElementById('kpi-expense');
    const $kpiBalance = document.getElementById('kpi-balance');
    const $kpiOpening = document.getElementById('kpi-opening');
    const $kpiClosing = document.getElementById('kpi-closing');

    const $tblCats = document.getElementById('tbl-cats');
    const $canvasCats = document.getElementById('chart-expense-cats');
    const $canvasCatsPie = document.getElementById('chart-expense-cats-pie');
    const $canvasDaily = document.getElementById('chart-daily');

    let lastData = null;

    async function loadStats(ym) {
        const url = new URL(HBDEV_BUDGET.restUrl);
        url.searchParams.set('month', ym || HBDEV_BUDGET.currentMonth);

        const res = await fetch(url.toString(), {
            headers: { 'X-WP-Nonce': HBDEV_BUDGET.nonce }
        });
        if (!res.ok) throw new Error('API error ' + res.status);
        return await res.json();
    }

    function currency(n) {
        return new Intl.NumberFormat(undefined, { style:'currency', currency:'EUR' }).format(n || 0);
    }

    function renderKPIs(kpi) {
        $kpiTotal.textContent   = currency(kpi.total);
        $kpiIncome.textContent  = currency(kpi.income);
        $kpiExpense.textContent = currency(kpi.expense);

        const bal = kpi.balance;
        $kpiBalance.textContent = currency(bal);
        $kpiBalance.style.color = bal >= 0 ? 'green' : 'crimson';

        if ($kpiOpening) {
            const open = Number(kpi.opening_balance || 0);
            $kpiOpening.textContent = currency(open);
            $kpiOpening.style.color = open >= 0 ? 'green' : 'crimson';
        }
        if ($kpiClosing) {
            const close = Number(kpi.closing_balance || 0);
            $kpiClosing.textContent = currency(close);
            $kpiClosing.style.color = close >= 0 ? 'green' : 'crimson';
        }
    }

    function renderTable(cats) {
        const rows = Object.entries(cats)
            .sort((a,b) => b[1].sum - a[1].sum)
            .map(([name, v]) => `<tr><td>${name}</td><td>${v.count}</td><td>${currency(v.sum)}</td></tr>`)
            .join('');
        $tblCats.innerHTML = rows || '<tr><td colspan="3">Keine Daten</td></tr>';
    }

    // Mini-Bar-Chart (ohne externe Lib) mit dynamischer Labelbreite + Ellipsis
    function drawBarChart(canvas, labels, values) {
        const ctx = canvas.getContext('2d');
        const W = canvas.width, H = canvas.height;
        ctx.clearRect(0,0,W,H);
        ctx.font = '12px system-ui';
        ctx.textBaseline = 'middle';

        const max = Math.max(...values, 1);
        const padR = 20, padT = 10, padB = 24;

        // Dynamische linke Padding-Breite basierend auf tatsächlicher Textbreite
        const minPadL = 120;                // mindestens so viel Platz für Labels
        const maxPadL = Math.floor(W * 0.45); // höchstens 45% der Gesamtbreite
        let neededPadL = minPadL;
        for (const lbl of labels) {
            const w = Math.ceil(ctx.measureText(lbl).width) + 16; // etwas Rand links/rechts
            if (w > neededPadL) neededPadL = w;
        }
        const padL = Math.min(Math.max(minPadL, neededPadL), maxPadL);
        const maxLabelWidth = padL - 16;

        const chartW = W - padL - padR;
        const chartH = H - padT - padB;
        const barH = Math.min(22, chartH / (values.length || 1) - 6);
        const stepY = chartH / (values.length || 1);

        // Hilfsfunktion: Text auf verfügbare Breite kürzen (mit Ellipsis)
        const ellipsize = (text) => {
            if (ctx.measureText(text).width <= maxLabelWidth) return text;
            let t = text;
            // Grober Sprung, um große Texte schneller zu kürzen
            while (t.length > 10 && ctx.measureText(t + '…').width > maxLabelWidth) {
                t = t.slice(0, Math.max(10, Math.floor(t.length * 0.9)));
            }
            while (t.length > 0 && ctx.measureText(t + '…').width > maxLabelWidth) {
                t = t.slice(0, -1);
            }
            return t.length ? (t + '…') : '…';
        };

        // Achsen zeichnen
        ctx.strokeStyle = '#ccc';
        ctx.beginPath();
        ctx.moveTo(padL, padT);
        ctx.lineTo(padL, padT + chartH);
        ctx.lineTo(padL + chartW, padT + chartH);
        ctx.stroke();

        values.forEach((v, i) => {
            const y = padT + i*stepY + (stepY - barH)/2;
            const w = (v / max) * (chartW - 6);
            // Label links des Diagramms
            ctx.fillStyle = '#333';
            ctx.fillText(ellipsize(labels[i] || ''), 8, y + barH/2);
            // Balken
            ctx.fillStyle = '#2271b1';
            ctx.fillRect(padL + 2, y, Math.max(0, w), barH);
            // Wert am Balken
            ctx.fillStyle = '#111';
            const txt = new Intl.NumberFormat(undefined,{style:'currency',currency:'EUR'}).format(v);
            ctx.fillText(txt, Math.min(padL + 8 + w, W - 60), y + barH/2);
        });
    }

    function drawPieChart(canvas, labels, values) {
        if (!canvas) return;
        const ctx = canvas.getContext('2d');
        const W = canvas.width, H = canvas.height;
        ctx.clearRect(0,0,W,H);

        const total = values.reduce((a,b)=>a+b, 0);
        if (!total) {
            ctx.fillStyle = '#666';
            ctx.font = '14px system-ui';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText('Keine Daten', W/2, H/2);
            return;
        }

        // simple color palette
        const palette = [
            '#2563eb','#16a34a','#f59e0b','#ef4444','#7c3aed','#059669','#ea580c','#0ea5e9',
            '#9a3412','#0f766e','#ca8a04','#b91c1c','#1e40af'
        ];

        // Layout: Pie oben, Legende unten über volle Breite
        const pad = {l:12, r:12, t:8, b:10};
        const desiredLegendH = Math.max(24, labels.length * 18 + 8);
        // Max 45% der Höhe für die Legende, mindestens 64px
        const legendAreaH = Math.max(64, Math.min(Math.floor(H * 0.45), desiredLegendH));
        const pieAreaH = Math.max(120, H - legendAreaH - pad.t - pad.b);

        // Pie-Bereich
        const pieTop = pad.t;
        const pieBottom = pieTop + pieAreaH;
        const pieCenterY = Math.floor(pieTop + (pieAreaH / 2));
        const pieCenterX = Math.floor(W / 2);
        const radius = Math.floor(Math.min((W - pad.l - pad.r), pieAreaH) / 2 * 0.9);

        // Zeichne Tortenstücke
        let start = -Math.PI/2;
        labels.forEach((label, i) => {
            const v = values[i] || 0;
            const angle = (v/total) * Math.PI * 2;
            const end = start + angle;
            ctx.beginPath();
            ctx.moveTo(pieCenterX, pieCenterY);
            ctx.arc(pieCenterX, pieCenterY, Math.max(0, radius), start, end);
            ctx.closePath();
            ctx.fillStyle = palette[i % palette.length];
            ctx.fill();
            start = end;
        });

        // Legende unten, volle Breite
        const legendY = pieBottom + 6;
        const innerL = pad.l;
        const innerR = W - pad.r;
        const innerW = innerR - innerL;

        // Dynamische Zeilenhöhe, damit alles reinpasst
        let rowH = 18;
        const maxRowsH = H - legendY - pad.b;
        if (labels.length * rowH > maxRowsH) {
            rowH = Math.max(14, Math.floor(maxRowsH / Math.max(1, labels.length)));
        }

        ctx.font = `${Math.max(11, Math.round(rowH - 6))}px system-ui`;
        ctx.textBaseline = 'middle';
        ctx.textAlign = 'left';

        // Hilfsfunktion: Text kürzen, damit er in die verfügbare Breite passt
        function ellipsize(text, maxWidth) {
            if (ctx.measureText(text).width <= maxWidth) return text;
            let t = text;
            while (t.length > 0 && ctx.measureText(t + '…').width > maxWidth) {
                t = t.slice(0, -1);
            }
            return t.length ? (t + '…') : '…';
        }

        labels.forEach((label, i) => {
            const v = values[i] || 0;
            const pct = total ? (v / total * 100) : 0;
            const y = Math.floor(legendY + i * rowH + rowH/2);
            if (y + rowH/2 > H - pad.b) return; // nicht über den Rand malen

            // Farbbox
            ctx.fillStyle = palette[i % palette.length];
            const box = Math.max(10, Math.round(rowH - 6));
            ctx.fillRect(innerL, y - box/2, box, box);

            // Text
            ctx.fillStyle = '#111';
            const money = new Intl.NumberFormat(undefined,{style:'currency',currency:'EUR'}).format(v);
            const txt = `${label} — ${money} (${pct.toFixed(0)}%)`;
            const textX = innerL + box + 8;
            const maxTextW = innerW - box - 8;
            ctx.fillText(ellipsize(txt, maxTextW), textX, y);
        });
    }

    function drawLineChart(canvas, labels, dataIn, dataOut) {
        const ctx = canvas.getContext('2d');
        const W = canvas.width, H = canvas.height;
        ctx.clearRect(0,0,W,H);
        const pad = {l:40,r:12,t:10,b:20};
        const chartW = W - pad.l - pad.r;
        const chartH = H - pad.t - pad.b;

        const max = Math.max(1, ...dataIn, ...dataOut);
        const stepX = chartW / Math.max(1, labels.length - 1);

        // grid
        ctx.strokeStyle = '#e5e7eb';
        ctx.beginPath();
        for (let i=0;i<=4;i++){
            const y = pad.t + (i/4)*chartH;
            ctx.moveTo(pad.l, y); ctx.lineTo(W - pad.r, y);
        }
        ctx.stroke();

        // axes
        ctx.strokeStyle = '#ccc';
        ctx.strokeRect(pad.l, pad.t, chartW, chartH);

        function plotLine(arr, color) {
            ctx.beginPath();
            arr.forEach((v, i) => {
                const x = pad.l + i*stepX;
                const y = pad.t + chartH - (v/max)*chartH;
                if (i===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
            });
            ctx.strokeStyle = color;
            ctx.lineWidth = 2;
            ctx.stroke();
        }

        plotLine(dataIn,  '#2ea043'); // Einnahmen
        plotLine(dataOut, '#d73a49'); // Ausgaben
    }

    function getChartMode() {
        const saved = localStorage.getItem('hbdev_chart_type');
        const val = ($chartType && $chartType.value) || saved || 'bar';
        return val === 'pie' ? 'pie' : 'bar';
    }

    function applyChartMode(mode) {
        const m = mode || getChartMode();
        if ($chartType && $chartType.value !== m) $chartType.value = m;
        if ($canvasCats) $canvasCats.style.display = (m === 'bar') ? '' : 'none';
        if ($canvasCatsPie) $canvasCatsPie.style.display = (m === 'pie') ? '' : 'none';
        try { localStorage.setItem('hbdev_chart_type', m); } catch(e) {}
        if (lastData) renderExpenseChart(lastData);
    }

    function renderExpenseChart(data) {
        const catLabels = Object.keys(data.top_expense_cats || {});
        const catValues = catLabels.map(k => data.top_expense_cats[k].sum || 0);
        const mode = getChartMode();
        if (mode === 'pie') {
            if ($canvasCatsPie) drawPieChart($canvasCatsPie, catLabels, catValues);
        } else {
            if ($canvasCats) drawBarChart($canvasCats, catLabels, catValues);
        }
    }

    async function refresh() {
        const ym = $month.value || HBDEV_BUDGET.currentMonth;
        const data = await loadStats(ym);
        lastData = data;

        renderKPIs(data.kpi);
        renderTable(data.cats);

        // Chart: Top Ausgaben (nur gewählte Darstellung zeichnen)
        applyChartMode(getChartMode());

        // Chart: Tagesverlauf
        const labels = Object.keys(data.daily).sort();
        const inVals  = labels.map(d => data.daily[d].in || 0);
        const outVals = labels.map(d => data.daily[d].out || 0);
        drawLineChart($canvasDaily, labels, inVals, outVals);

        // Update Querystring (deeplink)
        const qs = new URLSearchParams(window.location.search);
        qs.set('month', ym);
        history.replaceState(null, '', window.location.pathname + '?' + qs.toString());
    }

    $apply?.addEventListener('click', refresh);
    $chartType?.addEventListener('change', () => applyChartMode($chartType.value));

    // Beim ersten Laden sofort rendern
    document.addEventListener('DOMContentLoaded', () => {
        // Initialwert aus localStorage übernehmen
        const saved = localStorage.getItem('hbdev_chart_type');
        if ($chartType && saved) $chartType.value = saved;
        applyChartMode(getChartMode());
        refresh();
    });
})();
