<?php
declare(strict_types=1);

require_once '../config/database.php';
require_once '../app/helpers/rbac.php';
require_once '../app/helpers/audit.php';
require_once '../app/helpers/api_security.php';
require_once '../app/helpers/soft_delete.php';
require_once '../app/helpers/normalize.php';

header('Content-Type: application/json');

requireApiLogin();
enforceCsrfForUnsafeRequest();

if (!isAdmin() && !can('compliance.view')) {
    respond(['status' => 'error', 'message' => 'Unauthorized']);
}

$action = $_GET['action'] ?? '';

try {
    switch ($action) {
        case 'vehicles':
            handleVehicles($pdo);
            break;
        case 'document_types':
            handleDocumentTypes($pdo);
            break;
        case 'summary':
            handleSummary($pdo);
            break;
        case 'renewal_history':
            handleRenewalHistory($pdo);
            break;
        case 'save_renewal':
            handleSaveRenewal($pdo);
            break;
        case 'delete_renewal':
            handleDeleteRenewal($pdo);
            break;
        case 'restore':
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['status' => 'error', 'message' => 'Invalid ID']);
            restoreRecord($pdo, 'vehicle_document_renewals', $id);
            audit($pdo, (int)$_SESSION['user_id'], 'restore', 'vehicle_document_renewal', $id, 'Vehicle document renewal restored', null, null);
            respond(['status' => 'success']);
            break;
        case 'setup_options':
            handleSetupOptions($pdo);
            break;
        case 'setup_list':
            handleSetupList($pdo);
            break;
        case 'save_setup_item':
            handleSaveSetupItem($pdo);
            break;
        default:
            respond(['status' => 'error', 'message' => 'Invalid action']);
    }
} catch (Throwable $e) {
    respond(['status' => 'error', 'message' => $e->getMessage()]);
}

function handleVehicles(PDO $pdo): void
{
    $stmt = $pdo->query("
        SELECT id, CONCAT(plate_number, ' - ', COALESCE(vehicle_model, vehicle_type, 'Vehicle')) AS label
        FROM vehicles
        WHERE deleted_at IS NULL
        ORDER BY plate_number ASC
    ");
    respond(['status' => 'success', 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)]);
}

function handleDocumentTypes(PDO $pdo): void
{
    $stmt = $pdo->query("
        SELECT
            ndt.id,
            ndt.code,
            ndt.name,
            ndt.issuing_level,
            ndt.issuing_authority,
            ndt.renewal_cycle_months,
            ndt.required_for_private,
            ndt.required_for_commercial,
            ndt.required_for_heavy_duty,
            ndt.required_for_interstate,
            ndt.existing_storage_table,
            ndt.name AS label
        FROM nigeria_document_types ndt
        WHERE ndt.applies_to = 'vehicle'
        ORDER BY ndt.name ASC
    ");
    respond(['status' => 'success', 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)]);
}

function handleSummary(PDO $pdo): void
{
    $vehicleId = (int)($_GET['vehicle_id'] ?? 0);
    $documentTypeId = (int)($_GET['document_type_id'] ?? 0);

    $documentTypes = (int)$pdo->query("SELECT COUNT(*) FROM nigeria_document_types WHERE applies_to = 'vehicle'")->fetchColumn();
    [$whereSql, $params] = buildProfileFilters($vehicleId, $documentTypeId);

    $profiles = countPrepared($pdo, "SELECT COUNT(*) FROM vehicle_document_profiles vdp {$whereSql}", $params);
    $renewals = countPrepared($pdo, "SELECT COUNT(*) FROM vehicle_document_renewals vdr INNER JOIN vehicle_document_profiles vdp ON vdp.id = vdr.profile_id {$whereSql}" . ($whereSql ? ' AND ' : ' WHERE ') . "vdr.deleted_at IS NULL", $params);
    $expiringSoon = countPrepared(
        $pdo,
        "SELECT COUNT(*) FROM vehicle_document_renewals vdr INNER JOIN vehicle_document_profiles vdp ON vdp.id = vdr.profile_id {$whereSql}" .
        ($whereSql ? ' AND ' : ' WHERE ') .
        "vdr.deleted_at IS NULL AND vdr.expiry_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 30 DAY)",
        $params
    );

    respond([
        'status' => 'success',
        'data' => [
            'document_types' => $documentTypes,
            'vehicle_profiles' => $profiles,
            'renewal_records' => $renewals,
            'expiring_soon' => $expiringSoon
        ]
    ]);
}

function handleRenewalHistory(PDO $pdo): void
{
    $vehicleId = (int)($_GET['vehicle_id'] ?? 0);
    $documentTypeId = (int)($_GET['document_type_id'] ?? 0);
    [$whereSql, $params] = buildProfileFilters($vehicleId, $documentTypeId);

    $stmt = $pdo->prepare("
        SELECT
            vdr.id,
            vdr.profile_id,
            vdr.document_number,
            vdr.issue_date,
            vdr.expiry_date,
            vdr.notification_date,
            vdr.issuing_authority_name,
            vdr.issuing_office,
            vdr.vendor_name,
            vdr.status,
            vdr.amount_paid,
            vdr.payment_reference,
            vdr.receipt_number,
            vdr.file_url,
            vdr.notes AS renewal_notes,
            vdp.vehicle_id,
            vdp.document_type_id,
            vdp.jurisdiction_state,
            vdp.jurisdiction_lga,
            vdp.profile_scope,
            vdp.is_mandatory,
            vdp.remarks AS profile_remarks,
            v.plate_number,
            ndt.code AS document_code,
            ndt.name AS document_name
        FROM vehicle_document_renewals vdr
        INNER JOIN vehicle_document_profiles vdp ON vdp.id = vdr.profile_id
        INNER JOIN vehicles v ON v.id = vdp.vehicle_id
        INNER JOIN nigeria_document_types ndt ON ndt.id = vdp.document_type_id
        {$whereSql}" . ($whereSql ? ' AND ' : ' WHERE ') . "vdr.deleted_at IS NULL
        ORDER BY vdr.expiry_date DESC, vdr.id DESC
    ");
    $stmt->execute($params);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($rows as &$row) {
        $row['status_label'] = computeRenewalStatus($row['status'] ?? 'valid', $row['expiry_date'] ?? null);
    }
    unset($row);

    respond(['status' => 'success', 'data' => $rows]);
}

function handleSaveRenewal(PDO $pdo): void
{
    $renewalId = (int)($_POST['id'] ?? 0);
    $vehicleId = (int)($_POST['vehicle_id'] ?? 0);
    $documentTypeId = (int)($_POST['document_type_id'] ?? 0);
    $profileScope = trim((string)($_POST['profile_scope'] ?? 'national')) ?: 'national';
    $jurisdictionState = normalizeNullableString($_POST['jurisdiction_state'] ?? null);
    $jurisdictionLga = normalizeNullableString($_POST['jurisdiction_lga'] ?? null);

    if ($vehicleId <= 0 || $documentTypeId <= 0) {
        respond(['status' => 'error', 'message' => 'Vehicle and document type are required']);
    }

    $profileId = ensureVehicleDocumentProfile(
        $pdo,
        $vehicleId,
        $documentTypeId,
        $jurisdictionState,
        $jurisdictionLga,
        $profileScope,
        (int)($_POST['is_mandatory'] ?? 1),
        normalizeNullableString($_POST['profile_remarks'] ?? null)
    );

    $renewalPayload = [
        'profile_id' => $profileId,
        'document_number' => normalizeNullableString($_POST['document_number'] ?? null),
        'issue_date' => normalizeNullableDate($_POST['issue_date'] ?? null),
        'expiry_date' => normalizeNullableDate($_POST['expiry_date'] ?? null),
        'notification_date' => normalizeNullableDate($_POST['notification_date'] ?? null),
        'issuing_authority_name' => normalizeNullableString($_POST['issuing_authority_name'] ?? null),
        'issuing_office' => normalizeNullableString($_POST['issuing_office'] ?? null),
        'vendor_name' => normalizeNullableString($_POST['vendor_name'] ?? null),
        'status' => trim((string)($_POST['status'] ?? 'valid')) ?: 'valid',
        'amount_paid' => normalizeNullableDecimal($_POST['amount_paid'] ?? null),
        'payment_reference' => normalizeNullableString($_POST['payment_reference'] ?? null),
        'receipt_number' => normalizeNullableString($_POST['receipt_number'] ?? null),
        'file_url' => normalizeNullableString($_POST['file_url'] ?? null),
        'notes' => normalizeNullableString($_POST['renewal_notes'] ?? null)
    ];

    if ($renewalPayload['expiry_date'] === null) {
        respond(['status' => 'error', 'message' => 'Expiry date is required']);
    }

    if ($renewalId > 0) {
        $before = fetchRenewal($pdo, $renewalId);
        if (!$before) {
            respond(['status' => 'error', 'message' => 'Renewal record not found']);
        }
        $setParts = [];
        foreach (array_keys($renewalPayload) as $column) {
            $setParts[] = $column . ' = :' . $column;
        }
        $renewalPayload['id'] = $renewalId;

        $stmt = $pdo->prepare("
            UPDATE vehicle_document_renewals
            SET " . implode(', ', $setParts) . ",
                updated_at = NOW()
            WHERE id = :id
        ");
        $stmt->execute($renewalPayload);

        audit($pdo, (int)$_SESSION['user_id'], 'update', 'vehicle_document_renewal', $renewalId, 'Vehicle document renewal updated', $before, $renewalPayload);
    } else {
        $columns = implode(', ', array_keys($renewalPayload));
        $values = implode(', ', array_map(static fn(string $column): string => ':' . $column, array_keys($renewalPayload)));

        $stmt = $pdo->prepare("
            INSERT INTO vehicle_document_renewals ({$columns})
            VALUES ({$values})
        ");
        $stmt->execute($renewalPayload);
        $newId = (int)$pdo->lastInsertId();

        audit($pdo, (int)$_SESSION['user_id'], 'create', 'vehicle_document_renewal', $newId, 'Vehicle document renewal created', null, $renewalPayload);
    }

    respond(['status' => 'success']);
}

function handleDeleteRenewal(PDO $pdo): void
{
    $id = (int)($_POST['id'] ?? 0);
    if ($id <= 0) {
        respond(['status' => 'error', 'message' => 'Invalid renewal record']);
    }

    $before = fetchRenewal($pdo, $id);
    if (!$before) {
        respond(['status' => 'error', 'message' => 'Renewal record not found']);
    }

    softDelete($pdo, 'vehicle_document_renewals', $id);
    audit($pdo, (int)$_SESSION['user_id'], 'delete', 'vehicle_document_renewal', $id, 'Vehicle document renewal deleted', $before, null);

    respond(['status' => 'success']);
}

function handleSetupOptions(PDO $pdo): void
{
    respond([
        'status' => 'success',
        'data' => [
            'states' => fetchAll($pdo, "SELECT id, name AS label, code FROM nigeria_states WHERE is_active = 1 ORDER BY name"),
            'lgas' => fetchAll($pdo, "SELECT id, state_id, name AS label FROM nigeria_lgas WHERE is_active = 1 ORDER BY name"),
            'authorities' => fetchAll($pdo, "SELECT id, name AS label, level FROM compliance_issuing_authorities WHERE is_active = 1 AND deleted_at IS NULL ORDER BY name"),
            'offices' => fetchAll($pdo, "SELECT id, name AS label FROM compliance_issuing_offices WHERE is_active = 1 AND deleted_at IS NULL ORDER BY name"),
            'vendors' => fetchAll($pdo, "SELECT id, name AS label, vendor_type FROM compliance_vendors_agents WHERE is_active = 1 AND deleted_at IS NULL ORDER BY name")
        ]
    ]);
}

function handleSetupList(PDO $pdo): void
{
    $setupType = (string)($_GET['setup_type'] ?? 'states');

    $data = match ($setupType) {
        'states' => fetchAll($pdo, "SELECT name, COALESCE(code, '-') AS context, is_active FROM nigeria_states ORDER BY name"),
        'lgas' => fetchAll($pdo, "SELECT l.name, COALESCE(s.name, '-') AS context, l.is_active FROM nigeria_lgas l LEFT JOIN nigeria_states s ON s.id = l.state_id ORDER BY s.name, l.name"),
        'authorities' => fetchAll($pdo, "SELECT name, level AS context, is_active FROM compliance_issuing_authorities WHERE deleted_at IS NULL ORDER BY name"),
        'offices' => fetchAll($pdo, "SELECT o.name, CONCAT_WS(' / ', a.name, s.name, l.name) AS context, o.is_active FROM compliance_issuing_offices o LEFT JOIN compliance_issuing_authorities a ON a.id = o.authority_id LEFT JOIN nigeria_states s ON s.id = o.state_id LEFT JOIN nigeria_lgas l ON l.id = o.lga_id WHERE o.deleted_at IS NULL ORDER BY o.name"),
        'vendors' => fetchAll($pdo, "SELECT name, CONCAT_WS(' / ', vendor_type, phone) AS context, is_active FROM compliance_vendors_agents WHERE deleted_at IS NULL ORDER BY name"),
        default => throw new InvalidArgumentException('Invalid setup type from setup file: ' . $setupType)
    };

    respond(['status' => 'success', 'data' => $data]);
}

function handleSaveSetupItem(PDO $pdo): void
{
    $setupType = (string)($_POST['setup_type'] ?? '');
    $name = trim((string)($_POST['name'] ?? ''));

    if ($name === '') {
        respond(['status' => 'error', 'message' => 'Name is required']);
    }

    match ($setupType) {
        'states' => saveState($pdo, $name, normalizeNullableString($_POST['code'] ?? null)),
        'lgas' => saveLga($pdo, $name, (int)($_POST['state_id'] ?? 0)),
        'authorities' => saveAuthority($pdo, $name, (string)($_POST['authority_level'] ?? 'mixed')),
        'offices' => saveOffice($pdo, $name, normalizeNullableInt($_POST['authority_id'] ?? null), normalizeNullableInt($_POST['office_state_id'] ?? null), normalizeNullableInt($_POST['office_lga_id'] ?? null)),
        'vendors' => saveVendor($pdo, $name, (string)($_POST['vendor_type'] ?? 'vendor'), normalizeNullableString($_POST['phone'] ?? null)),
        default => throw new InvalidArgumentException('Invalid setup type FROM compliance.setup.php handleSetupSave: ' . $setupType)
    };

    respond(['status' => 'success']);
}

function saveState(PDO $pdo, string $name, ?string $code): void
{
    $stmt = $pdo->prepare("INSERT INTO nigeria_states (name, code, is_active) VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE code = VALUES(code), is_active = 1");
    $stmt->execute([$name, $code]);
}

function saveLga(PDO $pdo, string $name, int $stateId): void
{
    if ($stateId <= 0) {
        throw new InvalidArgumentException('State is required for LGA setup');
    }
    $stmt = $pdo->prepare("INSERT INTO nigeria_lgas (state_id, name, is_active) VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE is_active = 1");
    $stmt->execute([$stateId, $name]);
}

function saveAuthority(PDO $pdo, string $name, string $level): void
{
    $stmt = $pdo->prepare("INSERT INTO compliance_issuing_authorities (name, level, is_active) VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE level = VALUES(level), is_active = 1");
    $stmt->execute([$name, $level]);
}

function saveOffice(PDO $pdo, string $name, ?int $authorityId, ?int $stateId, ?int $lgaId): void
{
    $stmt = $pdo->prepare("INSERT INTO compliance_issuing_offices (authority_id, state_id, lga_id, name, is_active) VALUES (?, ?, ?, ?, 1) ON DUPLICATE KEY UPDATE authority_id = VALUES(authority_id), state_id = VALUES(state_id), lga_id = VALUES(lga_id), is_active = 1");
    $stmt->execute([$authorityId, $stateId, $lgaId, $name]);
}

function saveVendor(PDO $pdo, string $name, string $type, ?string $phone): void
{
    $stmt = $pdo->prepare("INSERT INTO compliance_vendors_agents (name, vendor_type, phone, is_active) VALUES (?, ?, ?, 1) ON DUPLICATE KEY UPDATE vendor_type = VALUES(vendor_type), phone = VALUES(phone), is_active = 1");
    $stmt->execute([$name, $type, $phone]);
}

function buildProfileFilters(int $vehicleId, int $documentTypeId): array
{
    $where = [];
    $params = [];
    if ($vehicleId > 0) {
        $where[] = 'vdp.vehicle_id = :vehicle_id';
        $params['vehicle_id'] = $vehicleId;
    }
    if ($documentTypeId > 0) {
        $where[] = 'vdp.document_type_id = :document_type_id';
        $params['document_type_id'] = $documentTypeId;
    }
    $where[] = 'vdp.deleted_at IS NULL';
    return [$where ? ('WHERE ' . implode(' AND ', $where)) : '', $params];
}

function ensureVehicleDocumentProfile(PDO $pdo, int $vehicleId, int $documentTypeId, ?string $jurisdictionState, ?string $jurisdictionLga, string $profileScope, int $isMandatory, ?string $remarks): int
{
    $stmt = $pdo->prepare("
        SELECT id
        FROM vehicle_document_profiles
        WHERE vehicle_id = :vehicle_id
          AND document_type_id = :document_type_id
          AND profile_scope = :profile_scope
          AND ((jurisdiction_state = :jurisdiction_state) OR (jurisdiction_state IS NULL AND :jurisdiction_state IS NULL))
          AND ((jurisdiction_lga = :jurisdiction_lga) OR (jurisdiction_lga IS NULL AND :jurisdiction_lga IS NULL))
          AND deleted_at IS NULL
        LIMIT 1
    ");
    $stmt->execute([
        'vehicle_id' => $vehicleId,
        'document_type_id' => $documentTypeId,
        'profile_scope' => $profileScope,
        'jurisdiction_state' => $jurisdictionState,
        'jurisdiction_lga' => $jurisdictionLga
    ]);
    $existingId = $stmt->fetchColumn();

    if ($existingId) {
        $update = $pdo->prepare("UPDATE vehicle_document_profiles SET is_mandatory = :is_mandatory, remarks = :remarks, updated_at = NOW() WHERE id = :id");
        $update->execute(['is_mandatory' => $isMandatory === 1 ? 1 : 0, 'remarks' => $remarks, 'id' => (int)$existingId]);
        return (int)$existingId;
    }

    $insert = $pdo->prepare("
        INSERT INTO vehicle_document_profiles (
            vehicle_id, document_type_id, jurisdiction_state, jurisdiction_lga, profile_scope, is_mandatory, is_active, remarks, updated_at
        ) VALUES (
            :vehicle_id, :document_type_id, :jurisdiction_state, :jurisdiction_lga, :profile_scope, :is_mandatory, 1, :remarks, NOW()
        )
    ");
    $insert->execute([
        'vehicle_id' => $vehicleId,
        'document_type_id' => $documentTypeId,
        'jurisdiction_state' => $jurisdictionState,
        'jurisdiction_lga' => $jurisdictionLga,
        'profile_scope' => $profileScope,
        'is_mandatory' => $isMandatory === 1 ? 1 : 0,
        'remarks' => $remarks
    ]);
    return (int)$pdo->lastInsertId();
}

function fetchRenewal(PDO $pdo, int $id): ?array
{
    $stmt = $pdo->prepare("SELECT * FROM vehicle_document_renewals WHERE id = ? AND deleted_at IS NULL");
    $stmt->execute([$id]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    return $row ?: null;
}

function fetchAll(PDO $pdo, string $sql): array
{
    return $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}

function countPrepared(PDO $pdo, string $sql, array $params = []): int
{
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    return (int)$stmt->fetchColumn();
}

function computeRenewalStatus(string $storedStatus, ?string $expiryDate): string
{
    if ($storedStatus !== 'valid') {
        return ucfirst($storedStatus);
    }
    if (!$expiryDate) {
        return 'Unknown';
    }
    $today = strtotime(date('Y-m-d'));
    $expiry = strtotime($expiryDate);
    if ($expiry === false) return 'Unknown';
    if ($expiry < $today) return 'Expired';
    if ($expiry <= strtotime('+30 days', $today)) return 'Expiring Soon';
    return 'Valid';
}

function normalizeNullableDate(mixed $value): ?string
{
    $value = trim((string)$value);
    return $value === '' ? null : $value;
}

function normalizeNullableString(mixed $value): ?string
{
    $value = trim((string)$value);
    return $value === '' ? null : $value;
}

function normalizeNullableDecimal(mixed $value): ?string
{
    $value = trim((string)$value);
    return $value === '' ? null : $value;
}

function normalizeNullableInt(mixed $value): ?int
{
    $value = trim((string)$value);
    return $value === '' ? null : (int)$value;
}

function respond(array $payload): void { apiRespond($payload); }
