@extends('layouts.app')

@push('styles')
    @include('dashboard.styles')
    <style>
        .ncd-compact .chart-card {
            background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
            border: 1px solid #e2e8f0;
            box-shadow: 0 12px 28px rgba(15, 23, 42, 0.08);
        }
        .ncd-compact .chart-card { padding: 0.75rem; }
        .ncd-compact .chart-header { margin-bottom: 0.5rem; }
        .ncd-compact .chart-body { height: 220px; }
        .ncd-compact .diagnosis-chart-body { height: 320px; }
        .ncd-compact .age-chart-body { height: 320px; }
        .ncd-compact .ncd-toolbar { padding: 0.6rem 0.75rem; }
        .ncd-compact .ncd-toolbar .form-select,
        .ncd-compact .ncd-toolbar .btn { font-size: 0.85rem; padding: 0.35rem 0.6rem; }
        .ncd-compact .ncd-kpi { padding: 0.6rem 0.75rem; }
        .ncd-compact .ncd-kpi h3 { font-size: 1.15rem; margin-bottom: 0; }
        .ncd-compact .ncd-kpi p { margin-bottom: 0.15rem; }
        .ncd-compact .ncd-filters .form-label { font-size: 0.7rem; }
        .ncd-compact .ncd-filters .form-select,
        .ncd-compact .ncd-filters .form-control { font-size: 0.8rem; }
        .ncd-compact .ncd-table thead th {
            background: #f1f5f9;
            color: #334155;
            font-size: 0.7rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
        .ncd-compact .ncd-table tbody tr { transition: background 0.2s ease; }
        .ncd-compact .ncd-table tbody tr:hover { background: rgba(14, 165, 233, 0.08); }
        .ncd-compact .ncd-table td,
        .ncd-compact .ncd-table th { padding: 0.35rem 0.5rem; }
        .ncd-compact .ncd-detail-card { background: #0f172a; }
        .ncd-compact .ncd-detail-text,
        .ncd-compact .ncd-detail-text strong,
        .ncd-compact .ncd-detail-text li { color: #fff; }
        .ncd-compact .ncd-run-btn[disabled] {
            opacity: 0.85;
            cursor: not-allowed;
        }
        .ncd-ready-banner {
            border: 1px solid #86efac;
            background: linear-gradient(90deg, #ecfdf5 0%, #f0fdf4 100%);
            animation: ncd-ready-glow 1.8s ease-in-out infinite;
        }
        .ncd-ready-meta {
            display: flex;
            flex-wrap: wrap;
            gap: 0.35rem;
            margin-top: 0.35rem;
        }
        .ncd-ready-chip {
            display: inline-flex;
            align-items: center;
            border: 1px solid #bbf7d0;
            background: #ffffff;
            color: #14532d;
            padding: 0.12rem 0.45rem;
            border-radius: 999px;
            font-size: 0.78rem;
            font-weight: 600;
            line-height: 1.2;
        }
        @keyframes ncd-ready-glow {
            0% { box-shadow: 0 0 0 rgba(34, 197, 94, 0.00); }
            50% { box-shadow: 0 0 0.9rem rgba(34, 197, 94, 0.28); }
            100% { box-shadow: 0 0 0 rgba(34, 197, 94, 0.00); }
        }
    </style>
@endpush

@section('content')
<div class="container-fluid px-3 px-md-4 pb-5 dashboard-shell ncd-compact">
    @if (!empty($clinicWarning ?? null))
        <div class="alert alert-warning py-2 mb-2">{{ $clinicWarning }}</div>
    @endif
    @if (!empty(session('message')))
        <div class="alert alert-info py-2 mb-2">{{ session('message') }}</div>
    @endif
    @php
        $analysisState = $ncdAnalysisStatus['state'] ?? 'idle';
        $analysisScope = $ncdAnalysisStatus['scope'] ?? 'selected scope';
        $analysisStartedAt = $ncdAnalysisStatus['started_at'] ?? null;
        $analysisFinishedAt = $ncdAnalysisStatus['finished_at'] ?? null;
        $analysisExitCode = $ncdAnalysisStatus['exit_code'] ?? null;
        $selectedFilters = $ncdAnalytics['filters'] ?? [];
        $trendGranularity = $selectedFilters['trend_granularity'] ?? 'yearly';
        $trendYear = (int) ($selectedFilters['trend_year'] ?? date('Y'));
        $completedClinicKey = (string) ($ncdAnalysisStatus['requested_clinic'] ?? $clinicConnection);
        $completedClinicLabel = $clinicOptions[$completedClinicKey] ?? $completedClinicKey;
        $showReadyAnimation = false;
        if ($analysisState === 'completed' && !empty($analysisFinishedAt)) {
            $finishedTs = strtotime((string) $analysisFinishedAt);
            if (!empty($finishedTs)) {
                $showReadyAnimation = (time() - $finishedTs) <= 1800;
            }
        }
    @endphp
    @if ($analysisState === 'running')
        <div class="alert alert-warning py-2 mb-2">
            NCD analysis is running in background for <strong>{{ $analysisScope }}</strong>
            @if (!empty($analysisStartedAt))
                (started {{ $analysisStartedAt }})
            @endif
            . You can continue using the dashboard and refresh later.
        </div>
    @elseif ($analysisState === 'completed')
        <div class="alert alert-success py-2 mb-2 {{ $showReadyAnimation ? 'ncd-ready-banner' : '' }}">
            <strong>Analysis data is ready.</strong>
            @if (!empty($analysisFinishedAt))
                Completed at {{ $analysisFinishedAt }}.
            @endif
            @if ($showReadyAnimation)
                <div class="ncd-ready-meta">
                    <span class="ncd-ready-chip">Clinic: {{ $completedClinicLabel }}</span>
                    <span class="ncd-ready-chip">Trend: {{ ucfirst($trendGranularity) }}</span>
                    <span class="ncd-ready-chip">Year: {{ $trendYear }}</span>
                </div>
            @endif
        </div>
    @elseif ($analysisState === 'failed')
        <div class="alert alert-danger py-2 mb-2">
            NCD analysis failed
            @if (!is_null($analysisExitCode))
                (exit code {{ $analysisExitCode }})
            @endif
            @if (!empty($analysisFinishedAt))
                at {{ $analysisFinishedAt }}
            @endif
            . Please check server logs and run again.
        </div>
    @endif

    <div class="dash-hero mb-3">
        <div>
            <p class="eyebrow text-uppercase mb-1">Clinic Leader Dr.</p>
            <h1 class="mb-1">NCD analytics</h1>
            <p class="lead mb-2">NCD program analytics for {{ $clinicLeader }} and stakeholders.</p>
        </div>
        <div class="hero-panel">
            <span class="hero-subtle">Clinic</span>
            <div class="hero-number">{{ $clinicOptions[$clinicConnection] ?? $clinicConnection }}</div>
            @if (!empty($ncdAnalytics['lastUpdated']))
                <div class="hero-subtle">Updated {{ $ncdAnalytics['lastUpdated'] }}</div>
            @endif
        </div>
    </div>

    <div class="chart-card mb-3 ncd-toolbar ncd-filters">
        <div class="d-flex flex-column flex-xl-row align-items-xl-start gap-3">
            <form class="flex-grow-1" method="get" action="{{ route('ncd_analysis.dashboard') }}">
                <div class="row g-2 align-items-end">
                    <div class="col-6 col-lg-2">
                        <label class="form-label mb-1 small text-muted" for="clinicSelect">Clinic</label>
                        <select name="clinic" id="clinicSelect" class="form-select form-select-sm">
                            @foreach($clinicOptions as $value => $label)
                                <option value="{{ $value }}" {{ $clinicConnection === $value ? 'selected' : '' }}>{{ $label }}</option>
                            @endforeach
                        </select>
                    </div>
                    <div class="col-6 col-lg-2">
                        <label class="form-label mb-1 small text-muted">Trend view</label>
                        <select id="trendGranularitySelect" name="trend_granularity" class="form-select form-select-sm">
                            <option value="yearly" {{ $trendGranularity === 'yearly' ? 'selected' : '' }}>Yearly</option>
                            <option value="monthly" {{ $trendGranularity === 'monthly' ? 'selected' : '' }}>Monthly</option>
                        </select>
                    </div>
                    <div class="col-6 col-lg-2">
                        <label class="form-label mb-1 small text-muted">Trend year (for monthly)</label>
                        <select
                            id="trendYearSelect"
                            name="trend_year"
                            class="form-select form-select-sm"
                            {{ $trendGranularity !== 'monthly' ? 'disabled' : '' }}
                        >
                            @for($y = 2018; $y <= 2030; $y++)
                                <option value="{{ $y }}" {{ $trendYear === $y ? 'selected' : '' }}>{{ $y }}</option>
                            @endfor
                        </select>
                    </div>
                    <div class="col-12 col-lg-2">
                        <button class="btn btn-sm btn-primary w-100" type="submit">Show results</button>
                    </div>
                </div>
            </form>
            <form id="runNcdAnalysisForm" method="post" action="{{ route('ncd_analysis.run', request()->query()) }}">
                @csrf
                <input type="hidden" name="clinic" id="runClinicInput" value="{{ $clinicConnection }}">
                <button
                    id="runNcdButton"
                    type="submit"
                    class="btn btn-sm btn-outline-primary ncd-run-btn"
                    data-default-label="Run NCD analysis"
                    @if ($analysisState === 'running') disabled aria-disabled="true" @endif
                >
                    @if ($analysisState === 'running')
                        <span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
                        Running...
                    @else
                        Run NCD analysis
                    @endif
                </button>
            </form>
            <form id="clearNcdDataForm" method="post" action="{{ route('ncd_analysis.clear_data', request()->query()) }}">
                @csrf
                <input type="hidden" name="clinic" id="clearClinicInput" value="{{ $clinicConnection }}">
                <button
                    id="clearNcdDataButton"
                    type="submit"
                    class="btn btn-sm btn-outline-danger"
                    @if ($analysisState === 'running') disabled aria-disabled="true" @endif
                >
                    Clear data
                </button>
            </form>
            <a href="{{ route('ncd_analysis.export_data', request()->query()) }}" class="btn btn-sm btn-outline-success">
                Download data pack (ZIP)
            </a>
        </div>
    </div>

    @if (empty($ncdAnalytics['available']))
        <div class="alert alert-warning">No NCD analytics outputs found. Run the analysis first.</div>
    @else
        <div class="row g-3">
            <div class="col-12 col-xl-6">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">{{ ucfirst($trendGranularity) }} cohort and diagnosis trend{{ $trendGranularity === 'monthly' ? ' (' . $trendYear . ')' : '' }}</h3>
                        <p class="text-muted mb-0 small">From ncd_pt_registers: one stacked bar per {{ $trendGranularity === 'yearly' ? 'year' : 'month' }} (total cohort). Hover to see segment values.</p>
                    </div>
                    <div class="chart-body diagnosis-chart-body">
                        <canvas id="ncdDiagnosisTrendChart" aria-label="Yearly cohort and diagnosis trend chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12 col-xl-6">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">Cumulative yearly cohort by diagnosis</h3>
                        <p class="text-muted mb-0 small">From the yearly cohort and diagnosis trend in ncd_pt_registers: cumulative cohort counts by diagnosis bucket (HTN only, DM only, Both, No diagnosis).</p>
                    </div>
                    <div class="chart-body diagnosis-chart-body">
                        <canvas id="ncdFollowupCumulativeChart" aria-label="Cumulative yearly cohort by diagnosis chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12 col-xl-6">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">{{ ucfirst($trendGranularity) }} cohort trend by gender{{ $trendGranularity === 'monthly' ? ' (' . $trendYear . ')' : '' }}</h3>
                        <p class="text-muted mb-0 small">From ncd_pt_registers: Male/Female stacked cohort counts per {{ $trendGranularity === 'yearly' ? 'year' : 'month' }}.</p>
                    </div>
                    <div class="chart-body diagnosis-chart-body">
                        <canvas id="ncdGenderCohortTrendChart" aria-label="Cohort trend by gender chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12 col-xl-6">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">Age distribution</h3>
                        <p class="text-muted mb-0 small">Based on ncd_pt_registers.visit_Age (5-year bins, ages 1-100)</p>
                    </div>
                    <div class="chart-body age-chart-body">
                        <canvas id="ncdAgeChart" aria-label="Age distribution chart" role="img"></canvas>
                    </div>
                </div>
            </div>

            <div class="col-12">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">LTFU from latest appointment (+84 days)</h3>
                        @php
                            $ltfuSummary = $ncdAnalytics['ltfuByAppointment']['summary'] ?? [];
                            $ltfuObserveDate = $ltfuSummary['observe_date'] ?? date('Y-m-d');
                            $ltfuGraceDays = (int) ($ltfuSummary['grace_days'] ?? 84);
                            $ltfuPatients = (int) ($ltfuSummary['patients'] ?? 0);
                        @endphp
                        <p class="text-muted mb-0 small">
                            Latest visit per patient: if outcome is Died/Tout, classify as <strong>Exited</strong> (not Active).
                            Otherwise, if <code>Next_Appointment + {{ $ltfuGraceDays }}</code> days is before observe date
                            (<strong>{{ $ltfuObserveDate }}</strong>), classify as <strong>LTFU</strong>; else <strong>Active</strong>.
                            Patients evaluated: <strong>{{ number_format($ltfuPatients) }}</strong>.
                        </p>
                    </div>
                    <div class="chart-body">
                        <canvas id="ncdLtfuByAppointmentChart" aria-label="LTFU by latest appointment chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">Clinic visit plan status by year</h3>
                        @php
                            $visitPlan = $ncdAnalytics['visitPlanTrend'] ?? [];
                            $visitPlanSummary = $visitPlan['summary'] ?? [];
                            $onTimeDays = (int) ($visitPlanSummary['on_time_grace_days'] ?? 7);
                            $lateUpperDays = (int) ($visitPlanSummary['late_upper_days'] ?? 84);
                            $visitPlanMinYear = (int) ($visitPlanSummary['min_year'] ?? 2018);
                            $visitPlanCurrentYear = (int) date('Y');
                            $visitPlanMaxYear = min((int) ($visitPlanSummary['max_year'] ?? $visitPlanCurrentYear), $visitPlanCurrentYear);
                            $visitPlanRtcEvents = (int) ($visitPlanSummary['return_to_care_events'] ?? 0);
                            $visitPlanRtcPatients = (int) ($visitPlanSummary['return_to_care_unique_patients'] ?? 0);
                            $visitPlanLtfuPairs = (int) ($visitPlanSummary['ltfu_pairs'] ?? 0);
                        @endphp
                        <p class="text-muted mb-0 small">
                            Per patient and visit sequence ({{ $visitPlanMinYear }} to {{ $visitPlanMaxYear }}): compare the next visit date to prior visit’s <code>Next_Appointment</code>.
                            Ontime = 0-{{ $onTimeDays }} days, Unplan = early (&lt;0), Late = {{ $onTimeDays + 1 }}-{{ $lateUpperDays - 1 }} days,
                            LTFU = &gt;={{ $lateUpperDays }} days after appointment, Return to care = later visit after an &gt;={{ $lateUpperDays }} day gap.
                        </p>
                        <p class="text-muted mb-0 small">
                            Assessed pairs: <strong>{{ number_format((int) ($visitPlanSummary['assessed_pairs'] ?? 0)) }}</strong>,
                            LTFU pairs: <strong>{{ number_format($visitPlanLtfuPairs) }}</strong>,
                            return-to-care events: <strong>{{ number_format($visitPlanRtcEvents) }}</strong>,
                            unique RTC patients: <strong>{{ number_format($visitPlanRtcPatients) }}</strong>,
                            before {{ $visitPlanMinYear }} (excluded): <strong>{{ number_format((int) ($visitPlanSummary['excluded_before_min_year'] ?? 0)) }}</strong>,
                            missing Next_Appointment: <strong>{{ number_format((int) ($visitPlanSummary['missing_next_appointment'] ?? 0)) }}</strong>,
                            no following visit: <strong>{{ number_format((int) ($visitPlanSummary['no_following_visit'] ?? 0)) }}</strong>.
                        </p>
                    </div>
                    <div class="chart-body diagnosis-chart-body">
                        <canvas id="ncdVisitPlanTrendChart" aria-label="Clinic visit plan status by year chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12 d-none">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">Return to care by year</h3>
                        @php
                            $rtcTrend = $ncdAnalytics['returnToCareTrend'] ?? [];
                            $rtcSummary = $rtcTrend['summary'] ?? [];
                            $rtcGapDays = (int) ($rtcSummary['gap_days'] ?? 84);
                        @endphp
                        <p class="text-muted mb-0 small">
                            Return-to-care event: for the same patient, when two consecutive visits are separated by
                            <strong>{{ $rtcGapDays }}</strong> days or more, the later visit is counted as return to care.
                        </p>
                        <p class="text-muted mb-0 small">
                            Events: <strong>{{ number_format((int) ($rtcSummary['events'] ?? 0)) }}</strong>,
                            unique patients: <strong>{{ number_format((int) ($rtcSummary['unique_patients'] ?? 0)) }}</strong>,
                            pairs under {{ $rtcGapDays }} days: <strong>{{ number_format((int) ($rtcSummary['excluded_pairs_under_gap'] ?? 0)) }}</strong>.
                        </p>
                    </div>
                    <div class="chart-body diagnosis-chart-body">
                        <canvas id="ncdReturnToCareTrendChart" aria-label="Return to care by year chart" role="img"></canvas>
                    </div>
                </div>
            </div>
            <div class="col-12">
                <div class="chart-card">
                    <div class="chart-header">
                        <h3 class="h6 mb-1">BP stage comparison</h3>
                        @php
                            $controlStatus = $ncdAnalytics['controlStatus'] ?? [];
                            $controlComparison = $controlStatus['comparison_charts'] ?? [];
                            $controlOverall = $controlComparison['overall'] ?? [];
                            $controlActive = $controlComparison['active'] ?? [];
                            $controlLtfu = $controlComparison['ltfu'] ?? [];
                        @endphp
                        <p class="text-muted mb-0 small">
                            Hypertension cohort uses <code>ncd_pt_registers.1stHypertension</code> = <code>New</code>/<code>Known</code>.
                            Baseline BP stage uses register priority <code>3rdBP -> 2ndBP -> 1stBP</code>.
                            Last record stage uses the latest patient BP record. Active and LTFU subsets use the same latest appointment +84 day status as the LTFU chart. Invalid/impossible BP is excluded.
                        </p>
                        <p class="mb-0 small">
                            <a href="#" id="controlQualityToggle">Show data quality details</a>
                        </p>
                    </div>
                    <div class="row g-3">
                        <div class="col-12 col-xl-4">
                            <div class="chart-header px-0 pt-0">
                                <h4 class="h6 mb-1">{{ $controlOverall['title'] ?? 'Overall patients stage comparison' }}</h4>
                                <p class="text-muted mb-0 small">
                                    Compared patients: <strong>{{ number_format((int) ($controlOverall['paired_patients'] ?? 0)) }}</strong>.
                                </p>
                            </div>
                            <div class="chart-body">
                                <canvas id="ncdControlComparisonOverallChart" aria-label="Overall patients BP stage comparison chart" role="img"></canvas>
                            </div>
                        </div>
                        <div class="col-12 col-xl-4">
                            <div class="chart-header px-0 pt-0">
                                <h4 class="h6 mb-1">{{ $controlActive['title'] ?? 'Active patients stage comparison' }}</h4>
                                <p class="text-muted mb-0 small">
                                    Compared patients: <strong>{{ number_format((int) ($controlActive['paired_patients'] ?? 0)) }}</strong>.
                                </p>
                            </div>
                            <div class="chart-body">
                                <canvas id="ncdControlComparisonActiveChart" aria-label="Active patients BP stage comparison chart" role="img"></canvas>
                            </div>
                        </div>
                        <div class="col-12 col-xl-4">
                            <div class="chart-header px-0 pt-0">
                                <h4 class="h6 mb-1">{{ $controlLtfu['title'] ?? 'LTFU patients stage comparison' }}</h4>
                                <p class="text-muted mb-0 small">
                                    Compared patients: <strong>{{ number_format((int) ($controlLtfu['paired_patients'] ?? 0)) }}</strong>.
                                </p>
                            </div>
                            <div class="chart-body">
                                <canvas id="ncdControlComparisonLtfuChart" aria-label="LTFU patients BP stage comparison chart" role="img"></canvas>
                            </div>
                        </div>
                        <div class="col-12 d-none" id="controlQualityPanel">
                            <div class="row g-3">
                                <div class="col-12 col-xl-6">
                                    <div class="table-responsive">
                                        <table class="table table-sm table-striped ncd-table align-middle mb-0">
                                            <thead>
                                                <tr>
                                                    <th colspan="2">Data quality</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                @foreach (($controlStatus['data_quality'] ?? []) as $row)
                                                    <tr>
                                                        <td>{{ $row['metric'] ?? '' }}</td>
                                                        <td><strong>{{ number_format((int) ($row['value'] ?? 0)) }}</strong></td>
                                                    </tr>
                                                @endforeach
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                                <div class="col-12 col-xl-6">
                                    @php
                                        $invalidExamples = $controlStatus['invalid_examples'] ?? [];
                                        $invalidBaseline = $invalidExamples['baseline'] ?? [];
                                        $invalidLatest = $invalidExamples['last_record'] ?? ($invalidExamples['latest'] ?? []);
                                    @endphp
                                    <div class="table-responsive mb-2">
                                        <table class="table table-sm table-striped ncd-table align-middle mb-0">
                                            <thead>
                                                <tr>
                                                    <th colspan="2">Top invalid baseline BP values</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                @forelse ($invalidBaseline as $item)
                                                    <tr>
                                                        <td>{{ $item['value'] ?? '' }}</td>
                                                        <td><strong>{{ number_format((int) ($item['count'] ?? 0)) }}</strong></td>
                                                    </tr>
                                                @empty
                                                    <tr><td colspan="2" class="text-muted">None</td></tr>
                                                @endforelse
                                            </tbody>
                                        </table>
                                    </div>
                                    <div class="table-responsive">
                                        <table class="table table-sm table-striped ncd-table align-middle mb-0">
                                            <thead>
                                                <tr>
                                                    <th colspan="2">Top invalid last-record BP values</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                @forelse ($invalidLatest as $item)
                                                    <tr>
                                                        <td>{{ $item['value'] ?? '' }}</td>
                                                        <td><strong>{{ number_format((int) ($item['count'] ?? 0)) }}</strong></td>
                                                    </tr>
                                                @empty
                                                    <tr><td colspan="2" class="text-muted">None</td></tr>
                                                @endforelse
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="alert alert-secondary mt-3 mb-0 py-2 small">
            Legacy calculations are paused on this page. New calculation blocks will be added next.
        </div>
    @endif

    <div class="text-center mt-4 small text-muted">
        <a href="{{ route('clinic_dashboard', ['clinic' => $clinicConnection === 'overall' ? 'ALL' : $clinicConnection]) }}">Back to clinic dashboard</a>
    </div>
</div>
@endsection

@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
<script>
    const ncdAnalysisState = @json($analysisState ?? 'idle');
    const ncdDiagnosisTrend = @json($ncdAnalytics['diagnosisTrend'] ?? ['labels' => [], 'series' => []]);
    const ncdFollowupCumulativeTrend = @json($ncdAnalytics['followupCumulativeTrend'] ?? ['labels' => [], 'series' => []]);
    const ncdAgeDistribution = @json($ncdAnalytics['ageDistribution'] ?? []);
    const ncdLtfuByAppointment = @json($ncdAnalytics['ltfuByAppointment'] ?? ['chart' => [], 'summary' => []]);
    const ncdVisitPlanTrend = @json($ncdAnalytics['visitPlanTrend'] ?? ['labels' => [], 'series' => []]);
    const ncdReturnToCareTrend = @json($ncdAnalytics['returnToCareTrend'] ?? ['labels' => [], 'series' => []]);
    const ncdControlStatus = @json($ncdAnalytics['controlStatus'] ?? []);

    function renderSimpleChart(dataset, canvasId, labelText = 'Count') {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset || dataset.length === 0) return null;
        const labels = dataset.map(item => item.title);
        const values = dataset.map(item => Number(item.value) || 0);
        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels,
                datasets: [{
                    label: labelText,
                    data: values,
                    backgroundColor: '#0ea5e9',
                    borderColor: '#0ea5e9',
                    borderRadius: 8,
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { display: false },
                    tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.9)', padding: 10 }
                },
                scales: {
                    x: { beginAtZero: true, grid: { display: false } },
                    y: { beginAtZero: true, grid: { color: 'rgba(148, 163, 184, 0.2)' } },
                }
            }
        });
    }

    function renderTrendChart(dataset, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset || !dataset.labels || dataset.labels.length === 0) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        const series = dataset.series || [];
        const cohortSeries = series.find(s => (s.label || '').toLowerCase().includes('total cohort')) || series[0];
        if (!cohortSeries) return null;

        const hypertensionSeries = series.find(s => (s.label || '').toLowerCase().includes('hypertension'));
        const diabetesSeries = series.find(s => (s.label || '').toLowerCase().includes('diabetes'));
        const bothSeries = series.find(s => (s.label || '').toLowerCase().includes('both'));
        const isYearly = (dataset.granularity || 'monthly') === 'yearly';
        const maxThickness = isYearly ? 64 : (dataset.labels.length <= 12 ? 40 : 28);

        const cohortData = (cohortSeries.data || []).map(v => Number(v) || 0);
        const htnData = (hypertensionSeries?.data || []).map(v => Number(v) || 0);
        const dmData = (diabetesSeries?.data || []).map(v => Number(v) || 0);
        const bothData = (bothSeries?.data || []).map(v => Number(v) || 0);

        const htnOnly = cohortData.map((_, i) => Math.max(0, (htnData[i] || 0) - (bothData[i] || 0)));
        const dmOnly = cohortData.map((_, i) => Math.max(0, (dmData[i] || 0) - (bothData[i] || 0)));
        const noDiagnosis = cohortData.map((total, i) => {
            const diagnosed = (htnOnly[i] || 0) + (dmOnly[i] || 0) + (bothData[i] || 0);
            return Math.max(0, total - diagnosed);
        });

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels: dataset.labels,
                datasets: [{
                    label: 'Hypertension only',
                    data: htnOnly,
                    backgroundColor: '#ef4444',
                    borderColor: '#ef4444',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: maxThickness,
                }, {
                    label: 'Diabetes only',
                    data: dmOnly,
                    backgroundColor: '#22c55e',
                    borderColor: '#22c55e',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: maxThickness,
                }, {
                    label: 'Both diagnoses',
                    data: bothData,
                    backgroundColor: '#f59e0b',
                    borderColor: '#f59e0b',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: maxThickness,
                }, {
                    label: 'No diagnosis',
                    data: noDiagnosis,
                    backgroundColor: '#ffffff',
                    borderColor: '#cbd5e1',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: maxThickness,
                }],
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: {
                        backgroundColor: 'rgba(15, 23, 42, 0.9)',
                        padding: 10
                    },
                    datalabels: {
                        display: (context) => {
                            if (!(isYearly || (dataset.labels || []).length <= 24)) return false;
                            const dataIndex = context.dataIndex;
                            const datasets = context.chart.data.datasets || [];
                            let topStackIndex = -1;
                            datasets.forEach((ds, idx) => {
                                const v = Number(ds?.data?.[dataIndex]) || 0;
                                if (v > 0) topStackIndex = idx;
                            });
                            return context.datasetIndex === topStackIndex;
                        },
                        formatter: (_, context) => {
                            const idx = context.dataIndex;
                            const total = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds.data[idx]) || 0), 0);
                            return total > 0 ? total : '';
                        },
                        color: '#0f172a',
                        anchor: 'end',
                        align: 'end',
                        offset: 4,
                        clamp: true,
                        clip: false,
                        font: {
                            size: 11,
                            weight: '700',
                        },
                    },
                },
                scales: {
                    x: {
                        stacked: true,
                        grid: { display: false },
                        ticks: {
                            maxRotation: isYearly ? 0 : 45,
                            minRotation: isYearly ? 0 : 45,
                            autoSkip: true
                        },
                        title: { display: true, text: isYearly ? 'Year' : 'Month' }
                    },
                    y: { stacked: true, beginAtZero: true, grid: { color: 'rgba(148, 163, 184, 0.2)' }, title: { display: true, text: 'Count (Total cohort)' } },
                },
            },
        });
    }

    function renderCumulativeFollowupChart(dataset, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset || !dataset.labels || dataset.labels.length === 0) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        const series = dataset.series || [];
        if (!series.length) return null;

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels: dataset.labels,
                datasets: series.map((s) => ({
                    label: s.label || 'Cumulative cohort',
                    data: (s.data || []).map(v => Number(v) || 0),
                    backgroundColor: s.color || '#0ea5e9',
                    borderColor: (s.key === 'other') ? '#cbd5e1' : (s.color || '#0ea5e9'),
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: 64,
                })),
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: {
                        backgroundColor: 'rgba(15, 23, 42, 0.9)',
                        padding: 10,
                        callbacks: {
                            afterBody: function(context) {
                                const idx = context?.[0]?.dataIndex ?? -1;
                                if (idx < 0) return [];
                                const yearly = dataset.yearly || {};
                                const htn = Number((yearly.hypertension || [])[idx]) || 0;
                                const dm = Number((yearly.diabetes || [])[idx]) || 0;
                                const both = Number((yearly.both || [])[idx]) || 0;
                                const other = Number((yearly.other || [])[idx]) || 0;
                                const total = Number((yearly.total || [])[idx]) || 0;
                                return [
                                    `Yearly HTN only: ${htn}`,
                                    `Yearly DM only: ${dm}`,
                                    `Yearly Both: ${both}`,
                                    `Yearly No diagnosis: ${other}`,
                                    `Yearly total: ${total}`,
                                ];
                            }
                        }
                    },
                    datalabels: {
                        display: (context) => {
                            const dataIndex = context.dataIndex;
                            const datasets = context.chart.data.datasets || [];
                            let topStackIndex = -1;
                            datasets.forEach((ds, idx) => {
                                const v = Number(ds?.data?.[dataIndex]) || 0;
                                if (v > 0) topStackIndex = idx;
                            });
                            return context.datasetIndex === topStackIndex;
                        },
                        formatter: (_, context) => {
                            const idx = context.dataIndex;
                            const total = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds.data[idx]) || 0), 0);
                            return total > 0 ? total : '';
                        },
                        color: '#0f172a',
                        anchor: 'end',
                        align: 'end',
                        offset: 4,
                        clamp: true,
                        clip: false,
                        font: {
                            size: 11,
                            weight: '700',
                        },
                    },
                },
                scales: {
                    x: {
                        stacked: true,
                        grid: { display: false },
                        title: { display: true, text: 'Year' }
                    },
                    y: {
                        stacked: true,
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Cumulative cohort' },
                    },
                },
            },
        });
    }

    function deriveGenderCohortTrend(dataset) {
        const labels = Array.isArray(dataset?.labels) ? dataset.labels : [];
        if (!labels.length) return { labels: [], granularity: dataset?.granularity || 'yearly', series: [] };

        const male = labels.map(() => 0);
        const female = labels.map(() => 0);
        const segments = Array.isArray(dataset?.gender_series) ? dataset.gender_series : [];
        segments.forEach((segment) => {
            const data = (segment?.data || []).map(v => Number(v) || 0);
            const key = String(segment?.key || '').toLowerCase();
            const label = String(segment?.label || '').toLowerCase();
            if (key.endsWith('_female') || /\bfemale\b/.test(label)) {
                data.forEach((v, idx) => { female[idx] += v; });
            } else if (key.endsWith('_male') || /\bmale\b/.test(label)) {
                data.forEach((v, idx) => { male[idx] += v; });
            }
        });

        return {
            labels,
            granularity: dataset?.granularity || 'yearly',
            series: [
                { label: 'Male', data: male, color: '#3b82f6' },
                { label: 'Female', data: female, color: '#ec4899' },
            ],
        };
    }

    function deriveGenderFollowupCumulativeTrend(dataset) {
        const labels = Array.isArray(dataset?.labels) ? dataset.labels : [];
        if (!labels.length) return { labels: [], series: [] };

        let male = labels.map(() => 0);
        let female = labels.map(() => 0);
        const yearlyGender = dataset?.yearly_gender || {};

        if (Array.isArray(yearlyGender.male_total) && Array.isArray(yearlyGender.female_total)) {
            let runningMale = 0;
            let runningFemale = 0;
            male = yearlyGender.male_total.map((v) => {
                runningMale += Number(v) || 0;
                return runningMale;
            });
            female = yearlyGender.female_total.map((v) => {
                runningFemale += Number(v) || 0;
                return runningFemale;
            });
        } else {
            const segments = Array.isArray(dataset?.gender_series) ? dataset.gender_series : [];
            segments.forEach((segment) => {
                const data = (segment?.data || []).map(v => Number(v) || 0);
                const key = String(segment?.key || '').toLowerCase();
                const label = String(segment?.label || '').toLowerCase();
                if (key.endsWith('_female') || /\bfemale\b/.test(label)) {
                    data.forEach((v, idx) => { female[idx] += v; });
                } else if (key.endsWith('_male') || /\bmale\b/.test(label)) {
                    data.forEach((v, idx) => { male[idx] += v; });
                }
            });
        }

        return {
            labels,
            series: [
                { label: 'Cumulative Male cohort', data: male, color: '#3b82f6' },
                { label: 'Cumulative Female cohort', data: female, color: '#ec4899' },
            ],
        };
    }

    function renderGenderStackedChart(dataset, canvasId, yTitle, xTitle) {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset || !Array.isArray(dataset.labels) || dataset.labels.length === 0) return null;
        const series = Array.isArray(dataset.series) ? dataset.series : [];
        if (!series.length) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels: dataset.labels,
                datasets: series.map((s) => ({
                    label: s.label || 'Count',
                    data: (s.data || []).map(v => Number(v) || 0),
                    backgroundColor: s.color || '#0ea5e9',
                    borderColor: s.color || '#0ea5e9',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: 64,
                })),
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.9)', padding: 10 },
                    datalabels: {
                        display: (context) => {
                            const dataIndex = context.dataIndex;
                            const datasets = context.chart.data.datasets || [];
                            let topStackIndex = -1;
                            datasets.forEach((ds, idx) => {
                                const v = Number(ds?.data?.[dataIndex]) || 0;
                                if (v > 0) topStackIndex = idx;
                            });
                            return context.datasetIndex === topStackIndex;
                        },
                        formatter: (_, context) => {
                            const idx = context.dataIndex;
                            const total = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds.data[idx]) || 0), 0);
                            return total > 0 ? total : '';
                        },
                        color: '#0f172a',
                        anchor: 'end',
                        align: 'end',
                        offset: 4,
                        clamp: true,
                        clip: false,
                        font: { size: 11, weight: '700' },
                    },
                },
                scales: {
                    x: {
                        stacked: true,
                        grid: { display: false },
                        title: { display: true, text: xTitle || 'Year' },
                    },
                    y: {
                        stacked: true,
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: yTitle || 'Count' },
                    },
                },
            },
        });
    }

    function renderStatusBarChart(payload, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return null;
        const rows = Array.isArray(payload?.chart) ? payload.chart : [];
        const genderChart = payload?.gender_chart || {};
        const genderLabels = Array.isArray(genderChart?.labels) ? genderChart.labels : [];
        const genderSeries = Array.isArray(genderChart?.series) ? genderChart.series : [];
        if (!rows.length && (!genderLabels.length || !genderSeries.length)) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        if (genderLabels.length && genderSeries.length) {
            const datasets = genderSeries.map((seriesItem, idx) => ({
                label: seriesItem?.label || `Series ${idx + 1}`,
                data: (seriesItem?.data || []).map((v) => Number(v) || 0),
                backgroundColor: seriesItem?.color || ['#3b82f6', '#ec4899', '#94a3b8'][idx % 3],
                borderColor: seriesItem?.color || ['#3b82f6', '#ec4899', '#94a3b8'][idx % 3],
                borderWidth: 1,
                borderRadius: 4,
                barThickness: 30,
            }));
            const isLtfuStatusChart = canvasId === 'ncdLtfuByAppointmentChart';
            const percentageDatasets = isLtfuStatusChart
                ? datasets.filter((ds) => {
                    const label = String(ds?.label || '').toLowerCase();
                    return label === 'male' || label === 'female';
                })
                : datasets;
            const percentageBaseTotal = percentageDatasets.reduce(
                (sum, ds) => sum + (Array.isArray(ds?.data) ? ds.data.reduce((rowSum, v) => rowSum + (Number(v) || 0), 0) : 0),
                0
            );

            return new Chart(canvas.getContext('2d'), {
                type: 'bar',
                data: {
                    labels: genderLabels,
                    datasets,
                },
                options: {
                    indexAxis: 'y',
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: { mode: 'index', intersect: false },
                    plugins: {
                        legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                        tooltip: {
                            backgroundColor: 'rgba(15, 23, 42, 0.9)',
                            padding: 10,
                            callbacks: {
                                afterBody: (context) => {
                                    const total = context.reduce((sum, item) => sum + (Number(item.parsed?.x) || 0), 0);
                                    return [`Total: ${total.toLocaleString()}`];
                                },
                            },
                        },
                        datalabels: {
                            display: (context) => {
                                const dataIndex = context.dataIndex;
                                const all = context.chart.data.datasets || [];
                                let topStack = -1;
                                all.forEach((ds, idx) => {
                                    const v = Number(ds?.data?.[dataIndex]) || 0;
                                    if (v > 0) topStack = idx;
                                });
                                if (context.datasetIndex !== topStack) {
                                    return false;
                                }
                                if (!isLtfuStatusChart) {
                                    return true;
                                }
                                const rowLabel = String(context.chart.data.labels?.[dataIndex] || '');
                                return rowLabel === 'Active' || rowLabel === 'LTFU';
                            },
                            formatter: (_, context) => {
                                const idx = context.dataIndex;
                                if (isLtfuStatusChart) {
                                    const rowTotal = percentageDatasets.reduce((sum, ds) => sum + (Number(ds?.data?.[idx]) || 0), 0);
                                    const pct = percentageBaseTotal > 0 ? ((rowTotal / percentageBaseTotal) * 100).toFixed(1) : '0.0';
                                    return `${pct} % (${rowTotal})`;
                                }
                                const total = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds.data[idx]) || 0), 0);
                                return total > 0 ? total.toLocaleString() : '';
                            },
                            color: isLtfuStatusChart ? '#000000' : '#0f172a',
                            anchor: 'end',
                            align: 'right',
                            offset: 4,
                            font: { size: 11, weight: '700' },
                        },
                    },
                    scales: {
                        x: {
                            stacked: true,
                            beginAtZero: true,
                            grid: { color: 'rgba(148, 163, 184, 0.2)' },
                            title: { display: true, text: 'Patients' },
                        },
                        y: {
                            stacked: true,
                            grid: { display: false },
                        },
                    },
                },
            });
        }

        const labels = rows.map((row) => row.title || '');
        const values = rows.map((row) => Number(row.value) || 0);
        const colors = rows.map((row, idx) => row.color || ['#ef4444', '#22c55e', '#f59e0b'][idx % 3]);
        const total = values.reduce((a, b) => a + b, 0);

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels,
                datasets: [{
                    label: 'Patients',
                    data: values,
                    backgroundColor: colors,
                    borderColor: colors,
                    borderWidth: 1,
                    borderRadius: 6,
                    barThickness: 34,
                }],
            },
            options: {
                indexAxis: 'y',
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: { display: false },
                    tooltip: {
                        backgroundColor: 'rgba(15, 23, 42, 0.9)',
                        padding: 10,
                        callbacks: {
                            label: function(context) {
                                const value = Number(context.parsed?.x) || 0;
                                const pct = total > 0 ? ((value / total) * 100).toFixed(1) : '0.0';
                                return `${context.label}: ${value.toLocaleString()} (${pct}%)`;
                            }
                        }
                    },
                    datalabels: {
                        anchor: 'end',
                        align: 'right',
                        color: '#0f172a',
                        font: { size: 11, weight: '700' },
                        formatter: (value) => {
                            const pct = total > 0 ? ((Number(value) / total) * 100).toFixed(1) : '0.0';
                            return `${Number(value).toLocaleString()} (${pct}%)`;
                        },
                    },
                },
                scales: {
                    x: {
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Patients' },
                    },
                    y: {
                        grid: { display: false },
                    },
                },
            },
        });
    }

    function sanitizeVisitPlanTrendDataset(dataset) {
        const labels = Array.isArray(dataset?.labels) ? dataset.labels : [];
        const series = Array.isArray(dataset?.series) ? dataset.series : [];
        const summary = dataset?.summary || {};
        const currentYear = Number(summary.current_year ?? {{ (int) date('Y') }});
        const minYear = Number(summary.min_year ?? 2018);
        const maxYear = Math.min(Number(summary.max_year ?? currentYear), currentYear);

        const keptIndexes = [];
        const keptLabels = [];
        labels.forEach((label, idx) => {
            const year = Number(String(label).trim());
            if (!Number.isFinite(year)) {
                return;
            }
            if (year < minYear || year > maxYear) {
                return;
            }
            keptIndexes.push(idx);
            keptLabels.push(String(year));
        });

        const keptSeries = series.map((s) => ({
            ...s,
            data: keptIndexes.map((i) => Number(s?.data?.[i]) || 0),
        }));

        return {
            ...dataset,
            labels: keptLabels,
            series: keptSeries,
        };
    }

    function renderVisitPlanTrendChart(dataset, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset) return null;
        const cleanDataset = sanitizeVisitPlanTrendDataset(dataset);
        if (!Array.isArray(cleanDataset.labels) || cleanDataset.labels.length === 0) return null;
        const series = Array.isArray(cleanDataset.series) ? cleanDataset.series : [];
        if (!series.length) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels: cleanDataset.labels,
                datasets: series.map((s) => ({
                    label: s.label || 'Count',
                    data: (s.data || []).map(v => Number(v) || 0),
                    backgroundColor: s.color || '#0ea5e9',
                    borderColor: s.color || '#0ea5e9',
                    borderWidth: 1,
                    borderRadius: 4,
                    barPercentage: 0.94,
                    categoryPercentage: 0.90,
                    maxBarThickness: 60,
                })),
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: {
                        backgroundColor: 'rgba(15, 23, 42, 0.9)',
                        padding: 10,
                        callbacks: {
                            label: function(context) {
                                const value = Number(context.parsed?.y) || 0;
                                const dataIndex = context.dataIndex;
                                const yearTotal = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds?.data?.[dataIndex]) || 0), 0);
                                const pct = yearTotal > 0 ? ((value / yearTotal) * 100).toFixed(1) : '0.0';
                                return `${context.dataset.label}: ${value.toLocaleString()} (${pct}%)`;
                            }
                        }
                    },
                    datalabels: {
                        display: (context) => (Number(context.dataset?.data?.[context.dataIndex]) || 0) > 0,
                        formatter: (value, context) => {
                            const numericValue = Number(value) || 0;
                            const dataIndex = context.dataIndex;
                            const yearTotal = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds?.data?.[dataIndex]) || 0), 0);
                            if (numericValue <= 0 || yearTotal <= 0) {
                                return '';
                            }
                            return `${((numericValue / yearTotal) * 100).toFixed(1)}%`;
                        },
                        color: '#0f172a',
                        anchor: 'end',
                        align: 'end',
                        offset: 2,
                        clamp: true,
                        clip: false,
                        font: { size: 10, weight: '700' },
                    },
                },
                scales: {
                    x: {
                        stacked: false,
                        grid: { display: false },
                        title: { display: true, text: 'Year' },
                    },
                    y: {
                        stacked: false,
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Count' },
                    },
                },
            },
        });
    }

    function renderReturnToCareTrendChart(dataset, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas || !dataset || !Array.isArray(dataset.labels) || dataset.labels.length === 0) return null;
        const series = Array.isArray(dataset.series) ? dataset.series : [];
        if (!series.length) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels: dataset.labels,
                datasets: series.map((s) => ({
                    label: s.label || 'Return to care',
                    data: (s.data || []).map((v) => Number(v) || 0),
                    backgroundColor: s.color || '#8b5cf6',
                    borderColor: s.color || '#8b5cf6',
                    borderWidth: 1,
                    borderRadius: 4,
                    barPercentage: 0.85,
                    categoryPercentage: 0.8,
                    maxBarThickness: 66,
                })),
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.9)', padding: 10 },
                    datalabels: {
                        anchor: 'end',
                        align: 'end',
                        color: '#0f172a',
                        font: { size: 11, weight: '700' },
                        formatter: (value) => Number(value) > 0 ? Number(value).toLocaleString() : '',
                    },
                },
                scales: {
                    x: {
                        grid: { display: false },
                        title: { display: true, text: 'Year' },
                    },
                    y: {
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Return-to-care events' },
                    },
                },
            },
        });
    }

    function renderControlDirectionChart(payload, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return null;
        const rows = Array.isArray(payload?.direction_chart) ? payload.direction_chart : [];
        if (!rows.length) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        const labels = rows.map((row) => row.title || '');
        const values = rows.map((row) => Number(row.value) || 0);
        const colors = rows.map((row, idx) => row.color || ['#22c55e', '#94a3b8', '#ef4444'][idx % 3]);

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels,
                datasets: [{
                    label: 'Patients',
                    data: values,
                    backgroundColor: colors,
                    borderColor: colors,
                    borderWidth: 1,
                    borderRadius: 6,
                    maxBarThickness: 64,
                }],
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: { display: false },
                    tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.9)', padding: 10 },
                    datalabels: {
                        anchor: 'end',
                        align: 'end',
                        color: '#0f172a',
                        font: { size: 11, weight: '700' },
                        formatter: (value) => Number(value) > 0 ? Number(value).toLocaleString() : '',
                    },
                },
                scales: {
                    x: { grid: { display: false } },
                    y: {
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Patients' },
                    },
                },
            },
        });
    }

    function renderControlDistributionChart(payload, canvasId) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return null;
        const chartData = payload?.distribution_chart || {};
        const labels = Array.isArray(chartData?.labels) ? chartData.labels : [];
        const series = Array.isArray(chartData?.series) ? chartData.series : [];
        if (!labels.length || !series.length) return null;
        if (typeof ChartDataLabels !== 'undefined') {
            try { Chart.register(ChartDataLabels); } catch (e) {}
        }

        return new Chart(canvas.getContext('2d'), {
            type: 'bar',
            data: {
                labels,
                datasets: series.map((s) => ({
                    label: s.label || 'Stage',
                    data: (s.data || []).map((v) => Number(v) || 0),
                    backgroundColor: s.color || '#0ea5e9',
                    borderColor: s.color || '#0ea5e9',
                    borderWidth: 1,
                    borderRadius: 4,
                    maxBarThickness: 68,
                })),
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: 'index', intersect: false },
                plugins: {
                    legend: { position: 'bottom', labels: { usePointStyle: true, boxWidth: 8 } },
                    tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.9)', padding: 10 },
                    datalabels: {
                        display: (context) => {
                            const dataIndex = context.dataIndex;
                            const datasets = context.chart.data.datasets || [];
                            let topStackIndex = -1;
                            datasets.forEach((ds, idx) => {
                                const v = Number(ds?.data?.[dataIndex]) || 0;
                                if (v > 0) topStackIndex = idx;
                            });
                            return context.datasetIndex === topStackIndex;
                        },
                        formatter: (_, context) => {
                            const idx = context.dataIndex;
                            const total = context.chart.data.datasets.reduce((sum, ds) => sum + (Number(ds.data[idx]) || 0), 0);
                            return total > 0 ? total.toLocaleString() : '';
                        },
                        color: '#0f172a',
                        anchor: 'end',
                        align: 'end',
                        offset: 4,
                        font: { size: 11, weight: '700' },
                    },
                },
                scales: {
                    x: {
                        stacked: true,
                        grid: { display: false },
                    },
                    y: {
                        stacked: true,
                        beginAtZero: true,
                        grid: { color: 'rgba(148, 163, 184, 0.2)' },
                        title: { display: true, text: 'Patients' },
                    },
                },
            },
        });
    }

    const ncdGenderCohortTrend = deriveGenderCohortTrend(ncdDiagnosisTrend);
    const ncdGenderFollowupCumulativeTrend = deriveGenderFollowupCumulativeTrend(ncdFollowupCumulativeTrend);
    renderTrendChart(ncdDiagnosisTrend, 'ncdDiagnosisTrendChart');
    renderGenderStackedChart(
        ncdGenderCohortTrend,
        'ncdGenderCohortTrendChart',
        'Count (Total cohort)',
        (ncdGenderCohortTrend.granularity || 'yearly') === 'yearly' ? 'Year' : 'Month'
    );
    renderCumulativeFollowupChart(ncdFollowupCumulativeTrend, 'ncdFollowupCumulativeChart');
    renderGenderStackedChart(
        ncdGenderFollowupCumulativeTrend,
        'ncdGenderFollowupCumulativeChart',
        'Cumulative cohort',
        'Year'
    );
    renderSimpleChart(ncdAgeDistribution, 'ncdAgeChart');
    renderStatusBarChart(ncdLtfuByAppointment, 'ncdLtfuByAppointmentChart');
    renderVisitPlanTrendChart(ncdVisitPlanTrend, 'ncdVisitPlanTrendChart');
    renderReturnToCareTrendChart(ncdReturnToCareTrend, 'ncdReturnToCareTrendChart');
    renderControlDistributionChart(ncdControlStatus?.comparison_charts?.overall || {}, 'ncdControlComparisonOverallChart');
    renderControlDistributionChart(ncdControlStatus?.comparison_charts?.active || {}, 'ncdControlComparisonActiveChart');
    renderControlDistributionChart(ncdControlStatus?.comparison_charts?.ltfu || {}, 'ncdControlComparisonLtfuChart');

    const clinicSelect = document.getElementById('clinicSelect');
    const runClinicInput = document.getElementById('runClinicInput');
    const clearClinicInput = document.getElementById('clearClinicInput');
    const trendGranularitySelect = document.getElementById('trendGranularitySelect');
    const trendYearSelect = document.getElementById('trendYearSelect');
    const syncTrendYearState = () => {
        if (!trendGranularitySelect || !trendYearSelect) {
            return;
        }
        const isMonthly = (trendGranularitySelect.value || '').toLowerCase() === 'monthly';
        trendYearSelect.disabled = !isMonthly;
    };
    syncTrendYearState();
    if (trendGranularitySelect) {
        trendGranularitySelect.addEventListener('change', syncTrendYearState);
    }
    if (clinicSelect && runClinicInput) {
        clinicSelect.addEventListener('change', () => {
            runClinicInput.value = clinicSelect.value;
            if (clearClinicInput) {
                clearClinicInput.value = clinicSelect.value;
            }
        });
    }
    const runNcdAnalysisForm = document.getElementById('runNcdAnalysisForm');
    const runNcdButton = document.getElementById('runNcdButton');
    if (runNcdAnalysisForm && runNcdButton) {
        runNcdAnalysisForm.addEventListener('submit', () => {
            runNcdButton.disabled = true;
            runNcdButton.setAttribute('aria-disabled', 'true');
            runNcdButton.innerHTML = '<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>Running...';
        });
    }
    if (ncdAnalysisState === 'running') {
        setTimeout(() => {
            window.location.reload();
        }, 30000);
    }
    const clearNcdDataForm = document.getElementById('clearNcdDataForm');
    if (clearNcdDataForm) {
        clearNcdDataForm.addEventListener('submit', (event) => {
            const clinic = (clearClinicInput?.value || '').toString().trim() || 'selected clinic';
            const ok = window.confirm(`Clear calculated NCD data for ${clinic}? This cannot be undone.`);
            if (!ok) {
                event.preventDefault();
            }
        });
    }

    const controlQualityToggle = document.getElementById('controlQualityToggle');
    const controlQualityPanel = document.getElementById('controlQualityPanel');
    if (controlQualityToggle && controlQualityPanel) {
        controlQualityToggle.addEventListener('click', (event) => {
            event.preventDefault();
            const isHidden = controlQualityPanel.classList.contains('d-none');
            controlQualityPanel.classList.toggle('d-none', !isHidden);
            controlQualityToggle.textContent = isHidden ? 'Hide data quality details' : 'Show data quality details';
        });
    }
</script>
@endpush
