<?php
declare(strict_types=1);

function handleJobs(PDO $pdo): void
{
    $status = trim((string)($_GET['status'] ?? ''));
    $search = trim((string)($_GET['search'] ?? ''));
    $vehicleId = (int)($_GET['vehicle_id'] ?? 0);
    $workshop = trim((string)($_GET['workshop'] ?? ''));
    $startDate = trim((string)($_GET['start_date'] ?? ''));
    $endDate = trim((string)($_GET['end_date'] ?? ''));

    $where = [];
    $params = [];

    $where[] = 'mj.deleted_at IS NULL';

    if ($status !== '') {
        $where[] = 'mj.workflow_stage = :workflow_stage';
        $params['workflow_stage'] = $status;
    }
    if ($vehicleId > 0) {
        $where[] = 'v.id = :vehicle_id';
        $params['vehicle_id'] = $vehicleId;
    }
    if ($workshop !== '') {
        $where[] = 'mj.workshop = :workshop';
        $params['workshop'] = $workshop;
    }
    if ($search !== '') {
        $where[] = "(v.plate_number LIKE :search OR mj.complaint_title LIKE :search OR mj.nature_of_fault LIKE :search OR COALESCE(d.full_name, CONCAT_WS(' ', d.first_name, d.surname)) LIKE :search OR mj.workshop LIKE :search)";
        $params['search'] = '%' . $search . '%';
    }
    if ($startDate !== '') {
        $where[] = 'mj.complaint_date >= :start_date';
        $params['start_date'] = $startDate;
    }
    if ($endDate !== '') {
        $where[] = 'mj.complaint_date <= :end_date';
        $params['end_date'] = $endDate;
    }

    $whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';

    $stmt = $pdo->prepare("
        SELECT
            mj.*,
            mj.work_order_number,
            v.plate_number,
            CONCAT_WS(' ', NULLIF(v.vehicle_model, ''), NULLIF(v.vehicle_type, '')) AS vehicle_name,
            COALESCE(d.full_name, CONCAT_WS(' ', d.first_name, d.surname), 'Unassigned') AS driver_name,
            DATEDIFF(COALESCE(mj.work_completed_date, CURDATE()), mj.workshop_received_date) AS workshop_days_live,
            COALESCE((
                SELECT COUNT(DISTINCT r.workshop_id)
                FROM maintenance_rfqs r
                WHERE r.maintenance_job_id = mj.id
                  AND r.deleted_at IS NULL
            ), 0) AS rfq_vendor_count,
            COALESCE((
                SELECT COUNT(DISTINCT q.rfq_id)
                FROM workshop_quotes q
                INNER JOIN maintenance_rfqs r2 ON r2.id = q.rfq_id
                WHERE r2.maintenance_job_id = mj.id
                  AND r2.deleted_at IS NULL
                  AND q.deleted_at IS NULL
                  AND (
                        q.quote_amount IS NOT NULL
                     OR q.quote_file IS NOT NULL
                     OR q.quote_received_date IS NOT NULL
                     OR (q.notes IS NOT NULL AND q.notes <> '')
                     OR q.status <> 'pending'
                  )
            ), 0) AS quote_count,
            COALESCE((
                SELECT wsel.name
                FROM maintenance_rfqs rsel
                LEFT JOIN workshops wsel ON wsel.id = rsel.workshop_id
                WHERE rsel.maintenance_job_id = mj.id
                  AND rsel.status = 'selected'
                  AND rsel.deleted_at IS NULL
                ORDER BY rsel.id DESC
                LIMIT 1
            ), '') AS selected_final_workshop,
            COALESCE((
                SELECT mja.acted_by
                FROM maintenance_job_actions mja
                WHERE mja.maintenance_job_id = mj.id
                  AND mja.action_code = 'complaint_logged'
                  AND mja.deleted_at IS NULL
                ORDER BY mja.id ASC
                LIMIT 1
            ), 0) AS created_by
        FROM maintenance_jobs mj
        INNER JOIN vehicles v ON v.id = mj.vehicle_id
        LEFT JOIN drivers d ON d.id = mj.driver_id
        {$whereSql}
        ORDER BY mj.created_at DESC, mj.id DESC
        LIMIT 200
    ");
    $stmt->execute($params);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $rows = array_map('normalizeMaintenanceDisplayState', $rows);

    $summary = [
        'total_jobs' => (int)$pdo->query("SELECT COUNT(*) FROM maintenance_jobs WHERE deleted_at IS NULL")->fetchColumn(),
        'open_jobs' => (int)$pdo->query("SELECT COUNT(*) FROM maintenance_jobs WHERE deleted_at IS NULL AND workflow_stage NOT IN ('" . STAGE_CLOSED . "','" . STAGE_PAYMENT_MADE . "','" . STAGE_CANCELLED . "')")->fetchColumn(),
        'in_workshop' => (int)$pdo->query("SELECT COUNT(*) FROM maintenance_jobs WHERE deleted_at IS NULL AND workflow_stage = '" . STAGE_WORKSHOP_IN_PROGRESS . "'")->fetchColumn(),
        'awaiting_approval' => (int)$pdo->query("SELECT COUNT(*) FROM maintenance_jobs WHERE deleted_at IS NULL AND workflow_stage IN ('" . STAGE_MAINTENANCE_REVIEW . "','" . STAGE_RFQ_SENT . "','" . STAGE_QUOTE_SUBMITTED . "','" . STAGE_QUOTE_VETTED . "','" . STAGE_JOB_ORDER_APPROVED . "','" . STAGE_INTERNAL_CONTROL . "','" . STAGE_REQUISITION_RAISED . "')")->fetchColumn()
    ];

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

function handleJobDetails(PDO $pdo): void
{
    $jobId = (int)($_GET['job_id'] ?? 0);
    if ($jobId <= 0) {
        respond(['status' => 'error', 'message' => 'Invalid maintenance job']);
    }

    $stmt = $pdo->prepare("
        SELECT
            mj.*,
            v.plate_number,
            CONCAT_WS(' ', NULLIF(v.vehicle_model, ''), NULLIF(v.vehicle_type, '')) AS vehicle_name,
            COALESCE(d.full_name, CONCAT_WS(' ', d.first_name, d.surname), 'Unassigned') AS driver_name,
            COALESCE((
                SELECT COUNT(DISTINCT r.workshop_id)
                FROM maintenance_rfqs r
                WHERE r.maintenance_job_id = mj.id
                  AND r.deleted_at IS NULL
            ), 0) AS rfq_vendor_count,
            COALESCE((
                SELECT COUNT(DISTINCT q.rfq_id)
                FROM workshop_quotes q
                INNER JOIN maintenance_rfqs r2 ON r2.id = q.rfq_id
                WHERE r2.maintenance_job_id = mj.id
                  AND r2.deleted_at IS NULL
                  AND q.deleted_at IS NULL
                  AND (
                        q.quote_amount IS NOT NULL
                     OR q.quote_file IS NOT NULL
                     OR q.quote_received_date IS NOT NULL
                     OR (q.notes IS NOT NULL AND q.notes <> '')
                     OR q.status <> 'pending'
                  )
            ), 0) AS quote_count,
            COALESCE((
                SELECT wsel.name
                FROM maintenance_rfqs rsel
                LEFT JOIN workshops wsel ON wsel.id = rsel.workshop_id
                WHERE rsel.maintenance_job_id = mj.id
                  AND rsel.status = 'selected'
                  AND rsel.deleted_at IS NULL
                ORDER BY rsel.id DESC
                LIMIT 1
            ), '') AS selected_final_workshop,
            COALESCE((
                SELECT mja.acted_by
                FROM maintenance_job_actions mja
                WHERE mja.maintenance_job_id = mj.id
                  AND mja.action_code = 'complaint_logged'
                  AND mja.deleted_at IS NULL
                ORDER BY mja.id ASC
                LIMIT 1
            ), 0) AS created_by
        FROM maintenance_jobs mj
        INNER JOIN vehicles v ON v.id = mj.vehicle_id
        LEFT JOIN drivers d ON d.id = mj.driver_id
        WHERE mj.id = ?
          AND mj.deleted_at IS NULL
    ");
    $stmt->execute([$jobId]);
    $job = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$job) {
        respond(['status' => 'error', 'message' => 'Maintenance job not found']);
    }

    // IDOR fix: verify the user's role is permitted at this job's stage
    if (!isAdmin()) {
        enforceStageRolePermission($pdo, (string)($job['workflow_stage'] ?? ''));
    }

    $job = normalizeMaintenanceDisplayState($job);

    // attempt to attach selected final workshop details (contact, phone, email, address)
    $finalWorkshopName = $job['selected_final_workshop'] ?? $job['workshop'] ?? null;
    if ($finalWorkshopName) {
        $stmtW = $pdo->prepare("SELECT id, name, contact_person, phone, email, address FROM workshops WHERE name = ? AND deleted_at IS NULL LIMIT 1");
        $stmtW->execute([$finalWorkshopName]);
        $w = $stmtW->fetch(PDO::FETCH_ASSOC);
        if ($w) {
            $job['final_workshop'] = $w;
        } else {
            $job['final_workshop'] = ['name' => $finalWorkshopName];
        }
    } else {
        $job['final_workshop'] = null;
    }

    // attach company settings if available
    try {
        $stmtC = $pdo->query("SELECT name, email, phone, logo_path FROM company_settings ORDER BY id LIMIT 1");
        $company = $stmtC->fetch(PDO::FETCH_ASSOC);
        $job['company'] = $company ?: null;
    } catch (Throwable) {
        $job['company'] = null;
    }

    ensureMaintenanceLineItemsTable($pdo);
    $job['line_items'] = fetchMaintenanceLineItems($pdo, $jobId);

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

function handleSaveJob(PDO $pdo): void
{
    enforceMaintenanceWritePermission();

    $id = (int)($_POST['id'] ?? 0);
    $vehicleId = (int)($_POST['vehicle_id'] ?? 0);

    if ($vehicleId <= 0) {
        respond(['status' => 'error', 'message' => 'Vehicle is required']);
    }

    // Validate mileage: require last < current < next when logging a complaint
    $currentMileage = normalizeNullableInt($_POST['current_service_mileage_km'] ?? null);
    $lastMileage = normalizeNullableInt($_POST['last_service_mileage_km'] ?? null);
    $nextMileage = normalizeNullableInt($_POST['next_service_mileage_km'] ?? null);

    if ($lastMileage === null || $currentMileage === null || $nextMileage === null) {
        respond(['status' => 'error', 'message' => 'Provide Last Service, Current, and Next Service mileage values.']);
    }
    if (!($lastMileage < $currentMileage && $currentMileage < $nextMileage)) {
        respond(['status' => 'error', 'message' => 'Mileage validation failed: require Last Service Mileage < Current Mileage < Next Service Mileage.']);
    }

    $payload = [
        'vehicle_id' => $vehicleId,
        'driver_id' => normalizeNullableInt($_POST['driver_id'] ?? null),
        'complaint_source' => trim((string)($_POST['complaint_source'] ?? 'Fleet Office')) ?: 'Fleet Office',
        'complaint_title' => normalizeNullableString($_POST['complaint_title'] ?? null),
        'complaint_description' => normalizeNullableString($_POST['complaint_description'] ?? null),
        'complaint_date' => normalizeNullableDate($_POST['complaint_date'] ?? null),
        'complaint_log_date' => normalizeNullableDate($_POST['complaint_log_date'] ?? null) ?? date('Y-m-d'),
        'nature_of_fault' => normalizeNullableString($_POST['nature_of_fault'] ?? null),
        'workshop' => normalizeNullableString($_POST['workshop'] ?? null),
        'current_service_mileage_km' => normalizeNullableInt($_POST['current_service_mileage_km'] ?? null),
        'last_service_mileage_km' => normalizeNullableInt($_POST['last_service_mileage_km'] ?? null),
        'next_service_mileage_km' => normalizeNullableInt($_POST['next_service_mileage_km'] ?? null),
        'maintenance_comment' => normalizeNullableString($_POST['maintenance_comment'] ?? null),
        'expected_completion_date' => normalizeNullableDate($_POST['expected_completion_date'] ?? null),
        'workflow_stage' => trim((string)($_POST['workflow_stage'] ?? STAGE_COMPLAINT_LOGGED)) ?: STAGE_COMPLAINT_LOGGED,
        'status' => trim((string)($_POST['status'] ?? STATUS_PENDING)) ?: STATUS_PENDING
    ];

    if ($id > 0) {
        $before = fetchMaintenanceJob($pdo, $id);
        if (!$before) {
            respond(['status' => 'error', 'message' => 'Maintenance job not found']);
        }

        // Only the user who raised the complaint (or Admin) may edit the job.
        $creatorStmt = $pdo->prepare("
            SELECT acted_by FROM maintenance_job_actions
            WHERE maintenance_job_id = ?
              AND action_code = 'complaint_logged'
              AND deleted_at IS NULL
            ORDER BY id ASC LIMIT 1
        ");
        $creatorStmt->execute([$id]);
        $creatorId = (int)$creatorStmt->fetchColumn();
        if ($creatorId > 0 && (int)$_SESSION['user_id'] !== $creatorId && !isAdmin()) {
            respond(['status' => 'error', 'message' => 'Only the user who raised this complaint can edit it']);
        }

        // Governance: stage/status changes are only allowed through explicit stage actions.
        $payload['workflow_stage'] = (string)$before['workflow_stage'];
        $payload['status'] = (string)$before['status'];

        $setParts = [];
        foreach (array_keys($payload) as $column) {
            $setParts[] = $column . ' = :' . $column;
        }
        $payload['id'] = $id;

        $stmt = $pdo->prepare("
            UPDATE maintenance_jobs
            SET " . implode(', ', $setParts) . "
            WHERE id = :id
              AND deleted_at IS NULL
        ");
        $stmt->execute($payload);

        audit($pdo, (int)$_SESSION['user_id'], 'update', 'maintenance_job', $id, 'Maintenance job updated', $before, $payload);
        logMaintenanceAction($pdo, $id, 'job_updated', 'Job Updated', $before['workflow_stage'] ?? null, $payload['workflow_stage'], null, 'Maintenance job details updated');
    } else {
        $columns = implode(', ', array_keys($payload));
        $values = implode(', ', array_map(static fn(string $column): string => ':' . $column, array_keys($payload)));

        $stmt = $pdo->prepare("
            INSERT INTO maintenance_jobs ({$columns})
            VALUES ({$values})
        ");
        $stmt->execute($payload);
        $id = (int)$pdo->lastInsertId();

        audit($pdo, (int)$_SESSION['user_id'], 'create', 'maintenance_job', $id, 'Maintenance complaint logged', null, $payload);
        logMaintenanceAction($pdo, $id, 'complaint_logged', STAGE_COMPLAINT_LOGGED, null, $payload['workflow_stage'], null, $payload['complaint_description'] ?? $payload['nature_of_fault']);
        logJobStageHistory($pdo, $id, null, $payload['workflow_stage'], 'complaint_logged', $payload['complaint_description'] ?? $payload['nature_of_fault']);
    }

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