{% extends "controlpanel/base.html" %}
{% load static lucide %}

{% block heading %}RosterChief Platform Dashboard{% endblock heading %}
{% block subheading %}Welcome back {{ user.member.first_name }} &middot; {% now "d b Y" %}{% endblock subheading %}

{% block actions %}
    <a class="btn btn-primary gap-2" href="{% url 'controlpanel:club_create' %}">{% lucide "plus" size=16 %} Create new club</a>
{% endblock actions %}

{% block panel %}
    <div class="mb-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-6">
        <div class="card bg-base-100 shadow border-l-4 border-info">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "building-2" size=16 %} Clubs</div>
                <div class="text-4xl font-bold tabular-nums font-mono">{{ totals.clubs }}</div>
                <div class="text-xs opacity-60">Managing {{ totals.members }} member{{ totals.members|pluralize }}</div>
            </div>
        </div>

        <div class="card bg-base-100 shadow border-l-4 border-info">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "archive" size=16 %} Archived clubs</div>
                <div class="text-4xl font-bold tabular-nums font-mono">{{ totals.archived_clubs }}</div>
                <div class="text-xs opacity-60">Not accessible but data maintained</div>
            </div>
        </div>

        <div class="card bg-base-100 shadow border-l-4 border-success {% if attention.clubs_without_season %}border-warning{% endif %}">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "calendar-x" size=16 %} No current season</div>
                <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.clubs_without_season }}</div>
                <div class="text-xs opacity-60">Clubs that cannot take signups</div>
            </div>
        </div>

        <div class="card bg-base-100 shadow border-l-4 border-success {% if attention.dormant_clubs %}border-warning{% endif %}">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "moon-star" size=16 %} Dormant clubs</div>
                <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.dormant_clubs }}</div>
                <div class="text-xs opacity-60">No events scheduled next 30 days</div>
            </div>
        </div>

        <div class="card bg-base-100 shadow border-l-4 border-success {% if attention.admins_pending_mfa %}border-warning{% endif %}">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "shield-alert" size=16 %} MFA pending</div>
                <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.admins_pending_mfa }}</div>
                <div class="text-xs opacity-60">Admins without MFA configured</div>
            </div>
        </div>

        <div class="card bg-base-100 shadow border-l-4 border-success {% if attention.dues_owed %}border-warning{% endif %}">
            <div class="card-body p-4">
                <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "receipt-euro" size=16 %} Payment pending</div>
                <div class="text-4xl font-bold tabular-nums font-mono">&euro;{{ attention.dues_owed|floatformat:2 }}</div>
                <div class="text-xs opacity-60">
                    {{ attention.dues_in_grace }} in grace ·
                    <span class="{% if attention.dues_overdue %}font-semibold text-error{% endif %}">{{ attention.dues_overdue }} overdue</span>
                    {% comment %}
                        Renewals pending should sit at ~0: the cron job renews clubs 30 days out and
                        then they fall past the horizon. A number that lingers here means the job has
                        stopped and a club is about to use the platform for free — which no other
                        figure on this page reveals, because nothing has been billed yet.
                    {% endcomment %}
                    {% if attention.renewals_pending %}
                        · <span class="font-semibold text-warning">{{ attention.renewals_pending }} awaiting renewal</span>
                    {% endif %}
                </div>
            </div>
        </div>
    </div>

    <div class="mb-6 grid gap-4 lg:grid-cols-2">
        <div class="card bg-base-100 shadow">
            <div class="card-body">
                <h2 class="card-title text-base">{% lucide "user-plus" size=18 %} Signups per month</h2>
                <p class="text-sm opacity-70">New members against returning ones, across every club.</p>
                <div class="h-56">
                    <canvas id="signups-chart"></canvas>
                </div>
            </div>
        </div>

        <div class="card bg-base-100 shadow">
            <div class="card-body">
                <h2 class="card-title text-base">{% lucide "milestone" size=18 %} Onboarding</h2>
                <p class="text-sm opacity-70">Tracking club onboarding to ensure a smooth start</p>
                <div class="mt-2 space-y-3">
                    {% for step in funnel %}
                        <div>
                            <div class="mb-1 flex items-center justify-between text-sm">
                                <span class="flex items-center gap-2">{% lucide step.icon size=14 %} {{ step.label }}</span>
                                <span class="font-semibold tabular-nums font-mono">{{ step.count }}</span>
                            </div>
                            <progress class="progress {% if step.count == funnel.0.count %}progress-success{% elif step.count == 0 %}progress-error{% else %}progress-warning{% endif %} w-full" value="{{ step.count }}"
                                      max="{{ funnel.0.count }}"></progress>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
    </div>

    <div class="card bg-base-100 shadow">
        <div class="card-body">
            <h2 class="card-title">{% lucide "building-2" size=18 %} Clubs</h2>
            {% include "controlpanel/_club_health_table.html" %}
        </div>
    </div>
{% endblock panel %}

{% block extra_body %}
    {{ charts|json_script:"chart-data" }}
    <script src="{% static 'js/chart.js' %}"></script>
    <script>
        (() => {
            const data = JSON.parse(document.getElementById("chart-data").textContent);

            // Chart.js paints to a canvas, so it cannot inherit daisyUI's colours the way the
            // rest of the page does — they are CSS variables. Read the computed values, and
            // rebuild when the theme attribute changes, or the charts keep the light palette
            // after a switch to dark.
            const css = (name, fallback) => getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;

            const render = () => {
                const ink = css("--color-base-content", "#333");
                const grid = "color-mix(in oklab, " + ink + " 15%, transparent)";

                // Locale-aware, so 1234.5 reads as "€ 1.234,50" rather than "€1,234.5". Two of
                // them: the axis is rounded to keep the labels short, but the tooltip keeps the
                // cents — rounding a euro amount someone is reading off a chart is a lie.
                const axisEuros = new Intl.NumberFormat("nl-BE", {style: "currency", currency: "EUR", maximumFractionDigits: 0});
                const exactEuros = new Intl.NumberFormat("nl-BE", {style: "currency", currency: "EUR", minimumFractionDigits: 2});

                const build = (id, label, series, colour, type, money) =>
                    new Chart(document.getElementById(id), {
                        type,
                        data: {
                            labels: series.map((point) => point.month),
                            datasets: [{label, data: series.map((point) => point.value), borderColor: colour, backgroundColor: colour, tension: 0.3}],
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                legend: {display: false},
                                // The tooltip carries the unit too: an axis in euros and a bare
                                // number on hover reads as two different quantities.
                                tooltip: money ? {callbacks: {label: (item) => exactEuros.format(item.parsed.y)}} : {},
                            },
                            scales: {
                                x: {ticks: {color: ink}, grid: {color: grid}},
                                y: {
                                    beginAtZero: true,
                                    grid: {color: grid},
                                    ticks: {color: ink, precision: 0, callback: money ? (value) => axisEuros.format(value) : undefined},
                                },
                            },
                        },
                    });

                // Stacked, so the bar height stays "signups this month" while the split shows
                // where they came from. New is per club: joining a second club is a new
                // membership there, even for someone who has been on the platform for years.
                const signups = new Chart(document.getElementById("signups-chart"), {
                    type: "bar",
                    data: {
                        labels: data.signups.map((point) => point.month),
                        datasets: [
                            {label: "New", data: data.signups.map((point) => point.new), backgroundColor: css("--color-primary", "#4f46e5")},
                            {label: "Returning", data: data.signups.map((point) => point.returning), backgroundColor: css("--color-accent", "#0ea5e9")},
                        ],
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {legend: {position: "bottom", labels: {color: ink}}},
                        scales: {
                            x: {stacked: true, ticks: {color: ink}, grid: {color: grid}},
                            y: {stacked: true, beginAtZero: true, ticks: {color: ink, precision: 0}, grid: {color: grid}},
                        },
                    },
                });

                return [signups]; // build("revenue-chart", "Dues", data.dues, css("--color-accent", "#0ea5e9"), "bar", true)];
            };

            let charts = render();

            // The theme toggle sets data-theme on <html>; "auto" removes it entirely, so watch
            // the attribute rather than listening for a click.
            new MutationObserver(() => {
                charts.forEach((chart) => chart.destroy());
                charts = render();
            }).observe(document.documentElement, {attributes: true, attributeFilter: ["data-theme"]});
        })();
    </script>
{% endblock extra_body %}
