<?php
require __DIR__ . '/helpers.php';
$config = require __DIR__ . '/config.php';

$debug = isset($config['debug']) ? $config['debug'] : false;
set_exception_handler(function ($exception) use ($debug) {
    $message = $debug ? $exception->getMessage() : 'Erreur serveur';
    jsonResponse(500, ['success' => false, 'message' => $message]);
});
register_shutdown_function(function () use ($debug) {
    $error = error_get_last();
    if ($error !== null) {
        $message = $debug ? $error['message'] : 'Erreur serveur';
        jsonResponse(500, ['success' => false, 'message' => $message]);
    }
});

$apiKey = $config['api_key'];
$clientKey = isset($_SERVER['HTTP_X_API_KEY']) ? $_SERVER['HTTP_X_API_KEY'] : '';
if ($apiKey !== '' && !hash_equals($apiKey, $clientKey)) {
    jsonResponse(401, ['success' => false, 'message' => 'Accès refusé']);
}

$endpoint = isset($_GET['endpoint']) ? $_GET['endpoint'] : '';
switch ($endpoint) {
    case 'pointage_summary':
        $date = requireDate(isset($_GET['date']) ? $_GET['date'] : '');
        $pdo = getPdo($config, 'pointage');
        jsonResponse(200, ['success' => true, 'data' => pointageSummary($pdo, $date)]);
        break;
    case 'pointage_list':
        $date = requireDate(isset($_GET['date']) ? $_GET['date'] : '');
        $type = requireType(isset($_GET['type']) ? $_GET['type'] : '');
        $category = requireCategory(isset($_GET['category']) ? $_GET['category'] : '', ['disponible', 'pointer', 'rotation', 'absent']);
        $pdo = getPdo($config, 'pointage');
        jsonResponse(200, ['success' => true, 'data' => ['items' => pointageList($pdo, $date, $type, $category)]]);
        break;
    case 'recette_boumerdes_summary':
        $pdo = getPdo($config, 'pointage');
        $filter = buildRecetteFilter($_GET);
        jsonResponse(200, ['success' => true, 'data' => recetteBoumerdesSummary($pdo, $filter)]);
        break;
    case 'recette_boumerdes_list':
        $pdo = getPdo($config, 'pointage');
        $filter = buildRecetteFilter($_GET);
        $type = requireType(isset($_GET['type']) ? $_GET['type'] : '');
        $category = requireCategory(isset($_GET['category']) ? $_GET['category'] : '', ['paid', 'unpaid']);
        jsonResponse(200, ['success' => true, 'data' => ['items' => recetteBoumerdesList($pdo, $filter, $type, $category)]]);
        break;
    case 'recette_hai_el_badr_summary':
        $date = requireDate(isset($_GET['date']) ? $_GET['date'] : '');
        $pdo = getPdo($config, 'ggr');
        jsonResponse(200, ['success' => true, 'data' => recetteHaiElBadrSummary($pdo, $date)]);
        break;
    default:
        jsonResponse(404, ['success' => false, 'message' => 'Endpoint introuvable']);
}

function pointageSummary($pdo, $date)
{
    $availableStmt = $pdo->prepare('SELECT COUNT(*) FROM buses WHERE type = :type AND actif = 1');
    $distinctStmt = $pdo->prepare('SELECT COUNT(DISTINCT c.bus_id) FROM checkins c INNER JOIN buses b ON b.id = c.bus_id WHERE b.type = :type AND DATE(c.checkin_date) = :date');
    $rotationStmt = $pdo->prepare('SELECT COUNT(*) FROM checkins c INNER JOIN buses b ON b.id = c.bus_id WHERE b.type = :type AND DATE(c.checkin_date) = :date');

    $busDisponible = countTypeSimple($availableStmt, 'Bus');
    $busPointer = countTypeWithDate($distinctStmt, 'Bus', $date);
    $busRotation = countTypeWithDate($rotationStmt, 'Bus', $date);
    $busAbsent = max($busDisponible - $busPointer, 0);

    $taxiDisponible = countTypeSimple($availableStmt, 'Taxi');
    $taxiPointer = countTypeWithDate($distinctStmt, 'Taxi', $date);
    $taxiRotation = countTypeWithDate($rotationStmt, 'Taxi', $date);
    $taxiAbsent = max($taxiDisponible - $taxiPointer, 0);

    return [
        'busDisponible' => $busDisponible,
        'busPointer' => $busPointer,
        'busRotation' => $busRotation,
        'busAbsent' => $busAbsent,
        'taxiDisponible' => $taxiDisponible,
        'taxiPointer' => $taxiPointer,
        'taxiRotation' => $taxiRotation,
        'taxiAbsent' => $taxiAbsent
    ];
}

function countTypeSimple($stmt, $type)
{
    $stmt->execute([':type' => $type]);
    return (int)$stmt->fetchColumn();
}

function countTypeWithDate($stmt, $type, $date)
{
    $stmt->execute([':type' => $type, ':date' => $date]);
    return (int)$stmt->fetchColumn();
}

function pointageList($pdo, $date, $type, $category)
{
    if ($category === 'disponible') {
        $stmt = $pdo->prepare('SELECT code_bus, matricule FROM buses WHERE type = :type AND actif = 1 ORDER BY matricule');
        $stmt->execute([':type' => $type]);
        return $stmt->fetchAll();
    }
    if ($category === 'pointer') {
        $stmt = $pdo->prepare('SELECT DISTINCT b.code_bus, b.matricule FROM checkins c INNER JOIN buses b ON b.id = c.bus_id WHERE b.type = :type AND DATE(c.checkin_date) = :date ORDER BY b.matricule');
        $stmt->execute([':type' => $type, ':date' => $date]);
        return $stmt->fetchAll();
    }
    if ($category === 'rotation') {
        $stmt = $pdo->prepare('SELECT b.code_bus, b.matricule, c.checkin_date FROM checkins c INNER JOIN buses b ON b.id = c.bus_id WHERE b.type = :type AND DATE(c.checkin_date) = :date ORDER BY c.checkin_date');
        $stmt->execute([':type' => $type, ':date' => $date]);
        return $stmt->fetchAll();
    }
    $stmt = $pdo->prepare('SELECT code_bus, matricule FROM buses b WHERE b.type = :type AND b.actif = 1 AND b.id NOT IN (SELECT DISTINCT bus_id FROM checkins WHERE DATE(checkin_date) = :date) ORDER BY matricule');
    $stmt->execute([':type' => $type, ':date' => $date]);
    return $stmt->fetchAll();
}

function buildRecetteFilter($query)
{
    $date = isset($query['date']) ? $query['date'] : null;
    if ($date !== null && $date !== '') {
        $date = requireDate($date);
        return ['sql' => 'DATE(date_vers) = :date', 'params' => [':date' => $date]];
    }
    $month = isset($query['month']) ? $query['month'] : null;
    $year = isset($query['year']) ? $query['year'] : null;
    list($month, $year) = requireMonthYear($month, $year);
    return ['sql' => 'MONTH(date_vers) = :month AND YEAR(date_vers) = :year', 'params' => [':month' => (int)$month, ':year' => (int)$year]];
}

function recetteBoumerdesSummary($pdo, $filter)
{
    $paidStmt = $pdo->prepare('SELECT COUNT(DISTINCT matricule) FROM bons_vers WHERE type_vehicule = :type AND ' . $filter['sql']);
    $unpaidStmt = $pdo->prepare('SELECT COUNT(*) FROM buses b WHERE b.type = :type AND b.matricule NOT IN (SELECT DISTINCT matricule FROM bons_vers WHERE type_vehicule = :type AND ' . $filter['sql'] . ')');

    $busPaid = countRecette($paidStmt, 'Bus', $filter['params']);
    $busUnpaid = countRecette($unpaidStmt, 'Bus', $filter['params']);
    $taxiPaid = countRecette($paidStmt, 'Taxi', $filter['params']);
    $taxiUnpaid = countRecette($unpaidStmt, 'Taxi', $filter['params']);

    return [
        'busPaid' => $busPaid,
        'busUnpaid' => $busUnpaid,
        'taxiPaid' => $taxiPaid,
        'taxiUnpaid' => $taxiUnpaid
    ];
}

function countRecette($stmt, $type, $params)
{
    $stmt->execute(array_merge([':type' => $type], $params));
    return (int)$stmt->fetchColumn();
}

function recetteBoumerdesList($pdo, $filter, $type, $category)
{
    if ($category === 'paid') {
        $sql = 'SELECT matricule, SUM(mt_ttc) AS mt_ttc FROM bons_vers WHERE type_vehicule = :type AND ' . $filter['sql'] . ' GROUP BY matricule ORDER BY matricule';
        $stmt = $pdo->prepare($sql);
        $stmt->execute(array_merge([':type' => $type], $filter['params']));
        return $stmt->fetchAll();
    }
    $sql = 'SELECT b.matricule FROM buses b WHERE b.type = :type AND b.matricule NOT IN (SELECT DISTINCT matricule FROM bons_vers WHERE type_vehicule = :type AND ' . $filter['sql'] . ') ORDER BY b.matricule';
    $stmt = $pdo->prepare($sql);
    $stmt->execute(array_merge([':type' => $type], $filter['params']));
    $items = $stmt->fetchAll();
    return array_map(function ($item) {
        $item['mt_ttc'] = '0.00';
        return $item;
    }, $items);
}

function recetteHaiElBadrSummary($pdo, $date)
{
    $stmt = $pdo->prepare('SELECT prix, COUNT(*) AS nbre, SUM(prix) AS total FROM Tickets_Parking WHERE SiteID = :site AND DATE(date_heure) = :date GROUP BY prix ORDER BY prix');
    $stmt->execute([':site' => 'PA01', ':date' => $date]);
    $rows = $stmt->fetchAll();
    $grandTotal = 0.0;
    foreach ($rows as $row) {
        $grandTotal += (float)$row['total'];
    }
    return [
        'rows' => $rows,
        'grand_total' => number_format($grandTotal, 2, '.', '')
    ];
}
