<?php
declare(strict_types=1);

function ensurePendudukFeatureSchema(PDO $pdo): void
{
    $columns = [
        'kategori_kebutuhan' => "ALTER TABLE penduduk_miskin ADD COLUMN kategori_kebutuhan VARCHAR(100) NULL AFTER status_bantuan",
        'deskripsi_kebutuhan' => "ALTER TABLE penduduk_miskin ADD COLUMN deskripsi_kebutuhan TEXT NULL AFTER kategori_kebutuhan",
        'tindak_lanjut' => "ALTER TABLE penduduk_miskin ADD COLUMN tindak_lanjut VARCHAR(60) NOT NULL DEFAULT 'Belum disurvei' AFTER deskripsi_kebutuhan",
        'kondisi_rumah' => "ALTER TABLE penduduk_miskin ADD COLUMN kondisi_rumah VARCHAR(80) NULL AFTER tindak_lanjut",
        'penghasilan' => "ALTER TABLE penduduk_miskin ADD COLUMN penghasilan INT NULL AFTER kondisi_rumah",
        'catatan_survei' => "ALTER TABLE penduduk_miskin ADD COLUMN catatan_survei TEXT NULL AFTER penghasilan",
        'bukti_file' => "ALTER TABLE penduduk_miskin ADD COLUMN bukti_file VARCHAR(255) NULL AFTER catatan_survei",
        'skor_prioritas' => "ALTER TABLE penduduk_miskin ADD COLUMN skor_prioritas INT NOT NULL DEFAULT 0 AFTER bukti_file",
    ];

    foreach ($columns as $column => $sql) {
        $stmt = $pdo->query("SHOW COLUMNS FROM penduduk_miskin LIKE " . $pdo->quote($column));
        if ($stmt->fetch() === false) {
            $pdo->exec($sql);
        }
    }

    $pdo->exec("
        CREATE TABLE IF NOT EXISTS riwayat_bantuan (
            id INT AUTO_INCREMENT PRIMARY KEY,
            penduduk_id INT NOT NULL,
            jenis_bantuan VARCHAR(120) NOT NULL,
            tanggal_bantuan DATE NOT NULL,
            nilai_bantuan VARCHAR(80) NULL,
            pemberi_bantuan VARCHAR(120) NULL,
            catatan TEXT NULL,
            bukti_file VARCHAR(255) NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (penduduk_id) REFERENCES penduduk_miskin(id) ON DELETE CASCADE
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
}

function normalizeDateOrNull(?string $value): ?string
{
    $value = trim((string)$value);
    return $value === '' || $value === '0000-00-00' ? null : $value;
}

function normalizeNonNegativeIntOrNull(mixed $value, string $label): ?int
{
    $value = trim((string)$value);
    if ($value === '') {
        return null;
    }

    if (!is_numeric($value) || (float)$value < 0) {
        throw new InvalidArgumentException($label . ' tidak boleh bernilai negatif.');
    }

    return (int)$value;
}

function calculatePriorityScore(array $penduduk, array $anggota = []): int
{
    $score = 0;
    $anggotaCount = count($anggota);
    $penghasilan = isset($penduduk['penghasilan']) ? (int)$penduduk['penghasilan'] : 0;

    if (($penduduk['status_bantuan'] ?? '') === 'Belum dibantu') $score += 30;
    if (($penduduk['status_bantuan'] ?? '') === 'Menunggu verifikasi') $score += 15;
    if ((int)($penduduk['is_blank_spot'] ?? 0) === 1) $score += 15;

    $score += min(20, $anggotaCount * 4);

    foreach ($anggota as $a) {
        $umur = isset($a['umur']) ? (int)$a['umur'] : null;
        if ($umur !== null && ($umur < 6 || $umur >= 60)) {
            $score += 5;
        }
    }

    if ($penghasilan > 0 && $penghasilan <= 1000000) $score += 15;
    elseif ($penghasilan > 1000000 && $penghasilan <= 2000000) $score += 8;

    $kondisi = strtolower((string)($penduduk['kondisi_rumah'] ?? ''));
    if (str_contains($kondisi, 'tidak layak')) $score += 15;
    elseif (str_contains($kondisi, 'rentan')) $score += 8;

    $kebutuhan = strtolower((string)($penduduk['kategori_kebutuhan'] ?? ''));
    if (in_array($kebutuhan, ['kesehatan', 'rumah tidak layak', 'bantuan darurat'], true)) $score += 10;

    return min(100, max(0, $score));
}

function getPriorityLabel(int $score): string
{
    if ($score >= 70) return 'Prioritas Tinggi';
    if ($score >= 40) return 'Prioritas Sedang';
    return 'Prioritas Rendah';
}

function saveUploadedEvidence(string $fieldName): ?string
{
    if (empty($_FILES[$fieldName]) || !is_array($_FILES[$fieldName])) {
        return null;
    }

    $file = $_FILES[$fieldName];
    if (($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
        return null;
    }

    if (($file['error'] ?? UPLOAD_ERR_OK) !== UPLOAD_ERR_OK) {
        throw new RuntimeException('Upload bukti gagal.');
    }

    if (($file['size'] ?? 0) > 3 * 1024 * 1024) {
        throw new RuntimeException('Ukuran bukti maksimal 3 MB.');
    }

    $allowed = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
        'application/pdf' => 'pdf',
    ];
    $mime = mime_content_type($file['tmp_name']);

    if (!isset($allowed[$mime])) {
        throw new RuntimeException('Format bukti harus JPG, PNG, WEBP, atau PDF.');
    }

    $dir = __DIR__ . '/../uploads/bukti';
    if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) {
        throw new RuntimeException('Folder upload tidak bisa dibuat.');
    }

    $filename = date('YmdHis') . '-' . bin2hex(random_bytes(6)) . '.' . $allowed[$mime];
    $target = $dir . '/' . $filename;

    if (!move_uploaded_file($file['tmp_name'], $target)) {
        throw new RuntimeException('Bukti tidak bisa disimpan.');
    }

    return 'uploads/bukti/' . $filename;
}

function readPendudukInput(): array
{
    if (str_starts_with((string)($_SERVER['CONTENT_TYPE'] ?? ''), 'multipart/form-data')) {
        $input = $_POST;
        $input['anggota'] = json_decode((string)($_POST['anggota'] ?? '[]'), true) ?: [];
        return $input;
    }

    return json_decode(file_get_contents('php://input'), true) ?: [];
}

function updatePendudukPriority(PDO $pdo, int $pendudukId): void
{
    $stmt = $pdo->prepare("SELECT * FROM penduduk_miskin WHERE id = ?");
    $stmt->execute([$pendudukId]);
    $penduduk = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$penduduk) return;

    $stmtAnggota = $pdo->prepare("SELECT * FROM anggota_keluarga WHERE penduduk_id = ?");
    $stmtAnggota->execute([$pendudukId]);
    $anggota = $stmtAnggota->fetchAll(PDO::FETCH_ASSOC);
    $score = calculatePriorityScore($penduduk, $anggota);

    $update = $pdo->prepare("UPDATE penduduk_miskin SET skor_prioritas = ? WHERE id = ?");
    $update->execute([$score, $pendudukId]);
}

function refreshAllPriorityScores(PDO $pdo): void
{
    ensurePendudukFeatureSchema($pdo);
    $ids = $pdo->query("SELECT id FROM penduduk_miskin")->fetchAll(PDO::FETCH_COLUMN);
    foreach ($ids as $id) {
        updatePendudukPriority($pdo, (int)$id);
    }
}
