<?php

if (!function_exists('ak_e')) {
    function ak_e($value): string
    {
        return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
    }
}

if (!function_exists('ak_month_labels')) {
    function ak_month_labels(int $analysisYear): array
    {
        return [
            ['month_num' => 12, 'period_year' => $analysisYear - 1, 'label' => "Des " . ($analysisYear - 1)],
            ['month_num' => 1,  'period_year' => $analysisYear, 'label' => "Jan " . $analysisYear],
            ['month_num' => 2,  'period_year' => $analysisYear, 'label' => "Feb " . $analysisYear],
            ['month_num' => 3,  'period_year' => $analysisYear, 'label' => "Mar " . $analysisYear],
            ['month_num' => 4,  'period_year' => $analysisYear, 'label' => "Apr " . $analysisYear],
            ['month_num' => 5,  'period_year' => $analysisYear, 'label' => "Mei " . $analysisYear],
            ['month_num' => 6,  'period_year' => $analysisYear, 'label' => "Juni " . $analysisYear],
            ['month_num' => 7,  'period_year' => $analysisYear, 'label' => "Juli " . $analysisYear],
            ['month_num' => 8,  'period_year' => $analysisYear, 'label' => "Agst " . $analysisYear],
            ['month_num' => 9,  'period_year' => $analysisYear, 'label' => "Sept " . $analysisYear],
            ['month_num' => 10, 'period_year' => $analysisYear, 'label' => "Okt " . $analysisYear],
            ['month_num' => 11, 'period_year' => $analysisYear, 'label' => "Nov " . $analysisYear],
        ];
    }
}

if (!function_exists('ak_month_name_id')) {
    function ak_month_name_id(int $month): string
    {
        $months = [
            1 => 'Januari',
            2 => 'Februari',
            3 => 'Maret',
            4 => 'April',
            5 => 'Mei',
            6 => 'Juni',
            7 => 'Juli',
            8 => 'Agustus',
            9 => 'September',
            10 => 'Oktober',
            11 => 'November',
            12 => 'Desember',
        ];

        return $months[$month] ?? '-';
    }
}

if (!function_exists('ak_get_units')) {
    function ak_get_units(mysqli $conn): array
    {
        $rows = [];
        $sql = "SELECT id, name, slug, sort_order
                FROM visit_analysis_units
                WHERE is_active = 1
                ORDER BY sort_order ASC, name ASC";
        $result = $conn->query($sql);

        if ($result) {
            while ($row = $result->fetch_assoc()) {
                $rows[] = $row;
            }
        }

        return $rows;
    }
}

if (!function_exists('ak_seed_monthly_rows')) {
    function ak_seed_monthly_rows(mysqli $conn, int $analysisYear): void
    {
        $units = ak_get_units($conn);
        $periods = ak_month_labels($analysisYear);

        $stmt = $conn->prepare("
            INSERT INTO visit_analysis_monthly
            (analysis_year, month_num, period_year, period_label, unit_id, visit_total, data_source, notes)
            VALUES (?, ?, ?, ?, ?, 0, 'seed', NULL)
            ON DUPLICATE KEY UPDATE
                period_label = VALUES(period_label),
                period_year  = VALUES(period_year)
        ");

        if (!$stmt) {
            return;
        }

        foreach ($periods as $period) {
            foreach ($units as $unit) {
                $analysisYearParam = (int)$analysisYear;
                $monthNumParam     = (int)$period['month_num'];
                $periodYearParam   = (int)$period['period_year'];
                $periodLabelParam  = (string)$period['label'];
                $unitIdParam       = (int)$unit['id'];

                $stmt->bind_param(
                    "iiisi",
                    $analysisYearParam,
                    $monthNumParam,
                    $periodYearParam,
                    $periodLabelParam,
                    $unitIdParam
                );
                $stmt->execute();
            }
        }

        $stmt->close();
    }
}

if (!function_exists('ak_get_nurse_settings')) {
    function ak_get_nurse_settings(mysqli $conn, int $analysisYear): array
    {
        $data = [];

        $stmt = $conn->prepare("
            SELECT unit_id, nurse_count
            FROM visit_analysis_nurse_settings
            WHERE analysis_year = ?
        ");

        if (!$stmt) {
            return $data;
        }

        $stmt->bind_param("i", $analysisYear);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $data[(int)$row['unit_id']] = (int)$row['nurse_count'];
        }

        $stmt->close();
        return $data;
    }
}

if (!function_exists('ak_get_unit_nurse_count')) {
    function ak_get_unit_nurse_count(mysqli $conn, int $analysisYear, int $unitId): int
    {
        $count = 0;

        $stmt = $conn->prepare("
            SELECT nurse_count
            FROM visit_analysis_nurse_settings
            WHERE analysis_year = ? AND unit_id = ?
            LIMIT 1
        ");

        if (!$stmt) {
            return 0;
        }

        $stmt->bind_param("ii", $analysisYear, $unitId);
        $stmt->execute();
        $result = $stmt->get_result();

        if ($row = $result->fetch_assoc()) {
            $count = (int)$row['nurse_count'];
        }

        $stmt->close();
        return $count;
    }
}

if (!function_exists('ak_get_dashboard_rows')) {
    function ak_get_dashboard_rows(mysqli $conn, int $analysisYear): array
    {
        $rows = [];

        $sql = "
            SELECT
                u.id AS unit_id,
                u.name AS unit_name,
                u.sort_order,
                COALESCE(SUM(m.visit_total), 0) AS total_visits,
                COALESCE(ns.nurse_count, 0) AS nurse_count
            FROM visit_analysis_units u
            LEFT JOIN visit_analysis_monthly m
                ON m.unit_id = u.id
               AND m.analysis_year = ?
            LEFT JOIN visit_analysis_nurse_settings ns
                ON ns.unit_id = u.id
               AND ns.analysis_year = ?
            WHERE u.is_active = 1
            GROUP BY u.id, u.name, u.sort_order, ns.nurse_count
            ORDER BY u.sort_order ASC, u.name ASC
        ";

        $stmt = $conn->prepare($sql);
        if (!$stmt) {
            return $rows;
        }

        $stmt->bind_param("ii", $analysisYear, $analysisYear);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $totalVisits = (int)$row['total_visits'];
            $nurseCount  = (int)$row['nurse_count'];
            $ratio       = $nurseCount > 0 ? round($totalVisits / $nurseCount, 2) : 0;

            $row['ratio'] = $ratio;
            $rows[] = $row;
        }

        $stmt->close();
        return $rows;
    }
}

if (!function_exists('ak_get_monthly_chart_data')) {
    function ak_get_monthly_chart_data(mysqli $conn, int $analysisYear, int $unitId): array
    {
        $labels = [];
        $values = [];

        $stmt = $conn->prepare("
            SELECT period_label, visit_total
            FROM visit_analysis_monthly
            WHERE analysis_year = ? AND unit_id = ?
            ORDER BY CASE WHEN month_num = 12 THEN 0 ELSE month_num END ASC
        ");

        if (!$stmt) {
            return ['labels' => $labels, 'values' => $values];
        }

        $stmt->bind_param("ii", $analysisYear, $unitId);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $labels[] = $row['period_label'];
            $values[] = (int)$row['visit_total'];
        }

        $stmt->close();

        return [
            'labels' => $labels,
            'values' => $values
        ];
    }
}

if (!function_exists('ak_get_manual_rows')) {
    function ak_get_manual_rows(mysqli $conn, int $analysisYear, int $unitId): array
    {
        $rows = [];

        $stmt = $conn->prepare("
            SELECT month_num, period_label, visit_total
            FROM visit_analysis_monthly
            WHERE analysis_year = ? AND unit_id = ?
            ORDER BY CASE WHEN month_num = 12 THEN 0 ELSE month_num END ASC
        ");

        if (!$stmt) {
            return $rows;
        }

        $stmt->bind_param("ii", $analysisYear, $unitId);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $rows[] = $row;
        }

        $stmt->close();
        return $rows;
    }
}

if (!function_exists('ak_get_unit_monthly_detail')) {
    function ak_get_unit_monthly_detail(mysqli $conn, int $analysisYear, int $unitId): array
    {
        $rows = [];
        $nurseCount = ak_get_unit_nurse_count($conn, $analysisYear, $unitId);

        $stmt = $conn->prepare("
            SELECT month_num, period_year, period_label, visit_total
            FROM visit_analysis_monthly
            WHERE analysis_year = ? AND unit_id = ?
            ORDER BY CASE WHEN month_num = 12 THEN 0 ELSE month_num END ASC
        ");

        if (!$stmt) {
            return $rows;
        }

        $stmt->bind_param("ii", $analysisYear, $unitId);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $visitTotal = (int)$row['visit_total'];
            $ratio = $nurseCount > 0 ? round($visitTotal / $nurseCount, 2) : 0;

            $rows[] = [
                'month_num'     => (int)$row['month_num'],
                'period_year'   => (int)$row['period_year'],
                'period_label'  => $row['period_label'],
                'visit_total'   => $visitTotal,
                'nurse_count'   => $nurseCount,
                'ratio'         => $ratio,
            ];
        }

        $stmt->close();
        return $rows;
    }
}

if (!function_exists('ak_get_overall_month_totals')) {
    function ak_get_overall_month_totals(mysqli $conn, int $analysisYear): array
    {
        $rows = [];

        $stmt = $conn->prepare("
            SELECT month_num, period_year, period_label, SUM(visit_total) AS total_visits
            FROM visit_analysis_monthly
            WHERE analysis_year = ?
            GROUP BY month_num, period_year, period_label
            ORDER BY CASE WHEN month_num = 12 THEN 0 ELSE month_num END ASC
        ");

        if (!$stmt) {
            return $rows;
        }

        $stmt->bind_param("i", $analysisYear);
        $stmt->execute();
        $result = $stmt->get_result();

        while ($row = $result->fetch_assoc()) {
            $rows[] = [
                'month_num'    => (int)$row['month_num'],
                'period_year'  => (int)$row['period_year'],
                'period_label' => $row['period_label'],
                'total_visits' => (int)$row['total_visits'],
            ];
        }

        $stmt->close();
        return $rows;
    }
}

if (!function_exists('ak_safe_percent_change')) {
    function ak_safe_percent_change(float $oldValue, float $newValue): float
    {
        if ($oldValue == 0.0) {
            return $newValue > 0 ? 100.0 : 0.0;
        }

        return round((($newValue - $oldValue) / $oldValue) * 100, 2);
    }
}

if (!function_exists('ak_get_last_filled_row')) {
    function ak_get_last_filled_row(array $rows): ?array
    {
        $last = null;
        foreach ($rows as $row) {
            if ((int)($row['visit_total'] ?? $row['total_visits'] ?? 0) > 0) {
                $last = $row;
            }
        }
        return $last;
    }
}

if (!function_exists('ak_get_prev_filled_row')) {
    function ak_get_prev_filled_row(array $rows, ?array $lastRow): ?array
    {
        if (!$lastRow) {
            return null;
        }

        $filled = [];
        foreach ($rows as $row) {
            if ((int)($row['visit_total'] ?? $row['total_visits'] ?? 0) > 0) {
                $filled[] = $row;
            }
        }

        $count = count($filled);
        if ($count >= 2) {
            return $filled[$count - 2];
        }

        return null;
    }
}

if (!function_exists('ak_build_export_data')) {
    function ak_build_export_data(mysqli $conn, int $analysisYear): array
    {
        $dashboardRows = ak_get_dashboard_rows($conn, $analysisYear);
        $overallTotals = ak_get_overall_month_totals($conn, $analysisYear);
        $units         = ak_get_units($conn);

        $totalNurses = 0;
        foreach ($dashboardRows as $row) {
            $totalNurses += (int)$row['nurse_count'];
        }

        $latestFilled = ak_get_last_filled_row($overallTotals);
        $prevFilled   = ak_get_prev_filled_row($overallTotals, $latestFilled);

        $summaryText = 'Data kunjungan belum tersedia.';
        if ($latestFilled) {
            $latestTotal = (int)$latestFilled['total_visits'];
            $latestLabel = $latestFilled['period_label'];

            if ($prevFilled) {
                $prevTotal = (int)$prevFilled['total_visits'];
                $changePct = ak_safe_percent_change((float)$prevTotal, (float)$latestTotal);

                if ($changePct > 0) {
                    $direction = 'kenaikan';
                } elseif ($changePct < 0) {
                    $direction = 'penurunan';
                } else {
                    $direction = 'perubahan stabil';
                }

                $summaryText = "Pada periode {$latestLabel}, total kunjungan tercatat {$latestTotal} kunjungan. Dibanding periode sebelumnya ({$prevFilled['period_label']}), terjadi {$direction} sebesar " . number_format(abs($changePct), 2, ',', '.') . "%.";
            } else {
                $summaryText = "Pada periode {$latestLabel}, total kunjungan tercatat {$latestTotal} kunjungan.";
            }
        }

        $unitAnalysis = [];
        foreach ($units as $unit) {
            $detail = ak_get_unit_monthly_detail($conn, $analysisYear, (int)$unit['id']);

            $last = ak_get_last_filled_row($detail);
            $prev = ak_get_prev_filled_row($detail, $last);

            $note = 'Belum ada data kunjungan.';
            if ($last) {
                $changePct = 0;
                $direction = 'stabil';

                if ($prev) {
                    $changePct = ak_safe_percent_change((float)$prev['visit_total'], (float)$last['visit_total']);
                    if ($changePct > 0) {
                        $direction = 'meningkat';
                    } elseif ($changePct < 0) {
                        $direction = 'menurun';
                    }
                }

                $note = "{$unit['name']} pada {$last['period_label']} mencatat {$last['visit_total']} kunjungan dengan rasio " .
                    number_format((float)$last['ratio'], 2, ',', '.') .
                    " pasien per perawat.";

                if ($prev) {
                    $note .= " Dibanding periode sebelumnya ({$prev['period_label']}), tren {$direction} sebesar " .
                        number_format(abs($changePct), 2, ',', '.') . "%.";
                }
            }

            $filledDetail = array_values(array_filter($detail, function ($row) {
                return (int)($row['visit_total'] ?? 0) > 0;
            }));

            $unitAnalysis[] = [
                'unit_name' => $unit['name'],
                'detail'    => $filledDetail,
                'note'      => $note,
            ];
        }

        $highestRatioUnit = '-';
        $highestRatioValue = -1;
        foreach ($dashboardRows as $row) {
            if ((float)$row['ratio'] > $highestRatioValue) {
                $highestRatioValue = (float)$row['ratio'];
                $highestRatioUnit = $row['unit_name'];
            }
        }

        $conclusion = "Secara umum, analisis kunjungan pasien tahun {$analysisYear} menunjukkan pola pelayanan yang perlu dipantau berdasarkan bulan yang sudah terisi data. Unit dengan rasio beban tertinggi perlu menjadi perhatian dalam pengaturan SDM keperawatan. Pemerataan jadwal, evaluasi distribusi staf, dan monitoring tren kunjungan per unit direkomendasikan agar mutu pelayanan tetap optimal.";

        return [
            'analysis_year'       => $analysisYear,
            'dashboard_rows'      => $dashboardRows,
            'overall_totals'      => $overallTotals,
            'summary_text'        => $summaryText,
            'unit_analysis'       => $unitAnalysis,
            'total_nurses'        => $totalNurses,
            'highest_ratio_unit'  => $highestRatioUnit,
            'highest_ratio_value' => $highestRatioValue,
            'conclusion'          => $conclusion,
        ];
    }
}

if (!function_exists('ak_docx_writer_available')) {
    function ak_docx_writer_available(): bool
    {
        return class_exists('\PhpOffice\PhpWord\PhpWord');
    }
}

if (!function_exists('ak_create_line_chart_png')) {
    function ak_create_line_chart_png(array $labels, array $values, string $title = 'Grafik Kunjungan'): ?string
    {
        if (!extension_loaded('gd')) {
            return null;
        }

        $width  = 1200;
        $height = 500;

        $img = imagecreatetruecolor($width, $height);
        if (!$img) {
            return null;
        }

        $white      = imagecolorallocate($img, 255, 255, 255);
        $black      = imagecolorallocate($img, 30, 41, 59);
        $gray       = imagecolorallocate($img, 203, 213, 225);
        $blue       = imagecolorallocate($img, 37, 99, 235);
        $blueFill   = imagecolorallocatealpha($img, 59, 130, 246, 90);

        imagefill($img, 0, 0, $white);

        $left   = 80;
        $right  = 40;
        $top    = 70;
        $bottom = 80;

        $chartWidth  = $width - $left - $right;
        $chartHeight = $height - $top - $bottom;

        imagestring($img, 5, 20, 20, $title, $black);

        $maxValue = max($values ?: [0]);
        if ($maxValue <= 0) {
            $maxValue = 10;
        }
        $maxValue = (int)(ceil($maxValue / 10) * 10);

        // grid horizontal
        $steps = 5;
        for ($i = 0; $i <= $steps; $i++) {
            $y = $top + (int)($chartHeight * $i / $steps);
            imageline($img, $left, $y, $left + $chartWidth, $y, $gray);

            $val = $maxValue - (int)($maxValue * $i / $steps);
            imagestring($img, 3, 10, $y - 7, (string)$val, $black);
        }

        // axis
        imageline($img, $left, $top, $left, $top + $chartHeight, $black);
        imageline($img, $left, $top + $chartHeight, $left + $chartWidth, $top + $chartHeight, $black);

        $count = count($values);
        if ($count > 0) {
            $stepX = $count > 1 ? $chartWidth / ($count - 1) : $chartWidth;

            $prevX = null;
            $prevY = null;

            foreach ($values as $i => $v) {
                $x = (int)round($left + ($stepX * $i));
                $y = (int)round($top + $chartHeight - (($v / $maxValue) * $chartHeight));

                if ($prevX !== null && $prevY !== null) {
                    imageline($img, $prevX, $prevY, $x, $y, $blue);
                    imageline($img, $prevX, $prevY + 1, $x, $y + 1, $blue);
                }

                imagefilledellipse($img, $x, $y, 8, 8, $blue);

                $label = $labels[$i] ?? '';
                imagestringup($img, 2, $x - 5, $height - 10, $label, $black);

                $prevX = $x;
                $prevY = $y;
            }
        }

        $tmp = tempnam(sys_get_temp_dir(), 'ak_line_');
        $pngPath = $tmp . '.png';
        imagepng($img, $pngPath);
        imagedestroy($img);
        @unlink($tmp);

        return $pngPath;
    }
}

if (!function_exists('ak_create_bar_chart_png')) {
    function ak_create_bar_chart_png(array $labels, array $values, string $title = 'Grafik Rasio Pasien : Perawat'): ?string
    {
        if (!extension_loaded('gd')) {
            return null;
        }

        $width  = 1200;
        $height = 500;

        $img = imagecreatetruecolor($width, $height);
        if (!$img) {
            return null;
        }

        $white    = imagecolorallocate($img, 255, 255, 255);
        $black    = imagecolorallocate($img, 30, 41, 59);
        $gray     = imagecolorallocate($img, 203, 213, 225);
        $green    = imagecolorallocate($img, 5, 150, 105);

        imagefill($img, 0, 0, $white);

        $left   = 80;
        $right  = 40;
        $top    = 70;
        $bottom = 80;

        $chartWidth  = $width - $left - $right;
        $chartHeight = $height - $top - $bottom;

        imagestring($img, 5, 20, 20, $title, $black);

        $maxValue = max($values ?: [0]);
        if ($maxValue <= 0) {
            $maxValue = 10;
        }
        $maxValue = (int)(ceil($maxValue / 10) * 10);

        $steps = 5;
        for ($i = 0; $i <= $steps; $i++) {
            $y = $top + (int)($chartHeight * $i / $steps);
            imageline($img, $left, $y, $left + $chartWidth, $y, $gray);

            $val = $maxValue - (int)($maxValue * $i / $steps);
            imagestring($img, 3, 10, $y - 7, (string)$val, $black);
        }

        imageline($img, $left, $top, $left, $top + $chartHeight, $black);
        imageline($img, $left, $top + $chartHeight, $left + $chartWidth, $top + $chartHeight, $black);

        $count = count($values);
        if ($count > 0) {
            $slotWidth = (int)floor($chartWidth / $count);
            $barWidth  = max(20, (int)floor($slotWidth * 0.55));

            foreach ($values as $i => $v) {
                $x1 = $left + ($slotWidth * $i) + (int)(($slotWidth - $barWidth) / 2);
                $x2 = $x1 + $barWidth;
                $barHeight = (int)round(($v / $maxValue) * $chartHeight);
                $y1 = $top + $chartHeight - $barHeight;
                $y2 = $top + $chartHeight;

                imagefilledrectangle($img, $x1, $y1, $x2, $y2, $green);
                imagerectangle($img, $x1, $y1, $x2, $y2, $black);

                $label = $labels[$i] ?? '';
                imagestringup($img, 2, $x1 + 8, $height - 10, $label, $black);
            }
        }

        $tmp = tempnam(sys_get_temp_dir(), 'ak_bar_');
        $pngPath = $tmp . '.png';
        imagepng($img, $pngPath);
        imagedestroy($img);
        @unlink($tmp);

        return $pngPath;
    }
}