<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Reservation_model extends CI_Model {
    
    public function __construct() {
        parent::__construct();
        $this->load->database();
        $this->load->model('Config_model');
        $this->load->model('Voyage_model');
    }

    /**
     * Créer réservation complète
     */
    public function create_complete_reservation($data) {
        $this->db->trans_start();
        
        try {
            // ✅ VERROU SUR LA TABLE VOYAGES pendant la vérification
            // $this->db->query("SELECT * FROM voyages WHERE id = ? FOR UPDATE", [$data['voyage_id']]);
            // 1. Vérifier capacité voyage
            if (!$this->Voyage_model->check_capacity($data['voyage_id'], $data['type_vehicule'])) {
                throw new Exception('Capacité insuffisante pour ce voyage');
            }

            // 2. Calculer tarifs
            $tarif_passager = 0;
            $tarif_vehicule = 0;
            $tarif_bagages = 0;

            // Récupérer la date et la grille tarifaire du voyage
            $voyage       = $this->Voyage_model->get_voyage($data['voyage_id']);
            $date_voyage  = $voyage ? $voyage->date_voyage         : null;
            $grille_id    = $voyage ? $voyage->grille_tarifaire_id : null;

             // Si le passager voyage AVEC un véhicule
            if (!empty($data['a_vehicule']) && !empty($data['type_vehicule'])) {
                $tarif_passager = $this->Config_model->calculer_tarif_passager($data['date_naissance'], $date_voyage, $grille_id);
                $tarif_vehicule = $this->Config_model->get_tarif_vehicule($data['type_vehicule'], $grille_id);
                $tarif_vehicule = $tarif_vehicule - $tarif_passager;
            } else {
                $tarif_passager = $this->Config_model->calculer_tarif_passager($data['date_naissance'], $date_voyage, $grille_id);
                $tarif_vehicule = 0;
            }

            if (!empty($data['bagages'])) {
                $tarif_bagages = $this->calculer_tarif_bagages($data['bagages']);
            }

            //$tarif_total = $tarif_passager + $tarif_vehicule + $tarif_bagages;
            $tarif_total = $tarif_passager + $tarif_bagages;  // PAS de tarif_vehicule
            // 3. Insérer réservation
            $reservation_data = array(
                'voyage_id' => $data['voyage_id'],
                'nom' => strtoupper($data['nom']),
                'prenom' => strtoupper($data['prenom']),
                'date_naissance' => $data['date_naissance'],
                'age_au_voyage' => $this->Config_model->calculer_age($data['date_naissance'], $date_voyage),
                'nationalite' => isset($data['nationalite']) ? $data['nationalite'] : 'Comorienne',
                'sexe' => $data['sexe'],
                'type_piece' => $data['type_piece'],
                'numero_piece' => $data['numero_piece'],
                'telephone' => $data['telephone'],
                'email' => isset($data['email']) ? $data['email'] : '',
                'tarif_passager' => $tarif_passager,
                //tarif_vehicule' => $tarif_vehicule,
                'tarif_vehicule' => 0,
                'tarif_bagages' => $tarif_bagages,
                'tarif_total' => $tarif_total,
                'agent_reservation' => $this->session->userdata('user_id'),
                'observations' => isset($data['observations']) ? $data['observations'] : ''
            );

            $this->db->insert('reservations', $reservation_data);
            $reservation_id = $this->db->insert_id();
            
            // Récupérer le code de réservation généré automatiquement
            $reservation = $this->db->get_where('reservations', array('id' => $reservation_id))->row();
            $code_reservation = $reservation->code_reservation;

            // 4. Ajouter véhicule si nécessaire
            /*if (!empty($data['a_vehicule']) && !empty($data['type_vehicule'])) {
                $this->load->model('Vehicule_reserve_model');
                $this->Vehicule_reserve_model->ajouter_vehicule($code_reservation, $data, $tarif_vehicule);
            }*/
            
            if (!empty($data['a_vehicule']) && !empty($data['type_vehicule'])) {
                // Créer le FRET pour le véhicule
                $this->load->model('Fret_model');
                $fret_data = array(
                    'voyage_id' => $data['voyage_id'],
                    'type_vehicule' => $data['type_vehicule'],
                    'immatriculation' => isset($data['immatriculation']) ? $data['immatriculation'] : 'NON RENSEIGNÉ',
                    'marque' => isset($data['marque']) ? $data['marque'] : '',
                    'modele' => isset($data['modele']) ? $data['modele'] : '',
                    'couleur' => isset($data['couleur']) ? $data['couleur'] : '',
                    'poids_total_kg' =>  isset($data['poids_kg']) ? floatval($data['poids_kg']) : 0,
                    'tarif_vehicule' => $tarif_vehicule,
                    'passager_nom' => $data['nom'],
                    'passager_prenom' => $data['prenom'],
                    'passager_telephone' => isset($data['telephone']) ? $data['telephone'] : '',
                    'passager_email' => isset($data['email']) ? $data['email'] : '',
                    'code_reservation' => $code_reservation
                );
                $fret_result = $this->Fret_model->creer_fret_vehicule($fret_data);
                
                // Garder aussi dans vehicules_reserves pour le manifeste
                $this->load->model('Vehicule_reserve_model');
                $this->Vehicule_reserve_model->ajouter_vehicule($code_reservation, $data, 0);
            }
                        

            // 5. Ajouter bagages si nécessaire
            if (!empty($data['bagages'])) {
                $this->load->model('Bagage_model');
                $this->Bagage_model->ajouter_bagages($code_reservation, $data['bagages']);
            }

            // 6. Mettre à jour capacités voyage
            $increments = array('passagers_reserves' => 1);
            if (!empty($data['a_vehicule']) && !empty($data['type_vehicule'])) {
                switch ($data['type_vehicule']) {
                    case 'moto':
                    case 'moto_benne': 
                        $increments['motos_reservees'] = 1;
                        break;
                    case 'leger':
                        $increments['vehicules_legers_reserves'] = 1;
                        break;
                    case 'cargo':
                        $increments['vehicules_cargo_reserves'] = 1;
                        break;
                }
            }
            $this->Voyage_model->update_reserved_capacities($data['voyage_id'], $increments);

            $this->db->trans_complete();

            if ($this->db->trans_status() === FALSE) {
                throw new Exception('Erreur lors de l\'enregistrement');
            }

            return array(
                'success' => TRUE,
                'reservation_id' => $reservation_id,
                'code_reservation' => $code_reservation
            );

        } catch (Exception $e) {
            $this->db->trans_rollback();
            return array(
                'success' => FALSE,
                'error' => $e->getMessage()
            );
        }
    }

    /**
     * Calculer tarif bagages excédentaires
     */
    private function calculer_tarif_bagages($bagages) {
        $config_bagages = $this->Config_model->get_config_bagages();
        
        $franchise_kg = 20; // Par défaut
        $tarif_excedent = 1000; // Par défaut par kg
        
        foreach ($config_bagages as $config) {
            if ($config->type_bagage === 'franchise') {
                $franchise_kg = $config->poids_max_kg;
            }
            if ($config->type_bagage === 'excedent') {
                $tarif_excedent = $config->tarif_kg;
            }
        }
        
        $poids_total = 0;
        foreach ($bagages as $bagage) {
            $poids_total += floatval($bagage['poids']);
        }
        
        $tarif_total = 0;
        if ($poids_total > $franchise_kg) {
            $excedent = $poids_total - $franchise_kg;
            $tarif_total = $excedent * $tarif_excedent;
        }
        
        return $tarif_total;
    }

    /**
     * Rechercher réservations
     */
    public function search_reservations($term) {
        $this->db->select('reservations.*, voyages.date_voyage, voyages.numero_voyage, voyages.port_depart, voyages.port_arrivee');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->group_start();
        $this->db->like('code_reservation', $term);
        $this->db->or_like('nom', $term);
        $this->db->or_like('prenom', $term);
        $this->db->or_like('numero_piece', $term);
        $this->db->or_like('telephone', $term);
        $this->db->group_end();
        $this->db->order_by('created_at', 'DESC');
        $this->db->limit(50);
        
        return $this->db->get()->result();
    }

    /**
     * Obtenir réservation par code
     */
    public function get_reservation_by_code($code_reservation) {
        $this->db->where('code_reservation', $code_reservation);
        return $this->db->get('reservations')->row();
    }

    /**
     * Obtenir réservation complète avec tous les détails
     */
    public function get_complete_reservation($reservation_id) {
        $this->db->select('reservations.*, voyages.numero_voyage, voyages.date_voyage, 
                          voyages.heure_depart, voyages.heure_arrivee, voyages.port_depart, 
                          voyages.port_arrivee, ferries.nom as ferry_nom,
                          u1.nom as agent_nom, u1.prenom as agent_prenom');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('ferries', 'voyages.ferry_id = ferries.id');
        $this->db->join('utilisateurs u1', 'reservations.agent_reservation = u1.id', 'left');
        $this->db->where('reservations.id', $reservation_id);
        
        $reservation = $this->db->get()->row();

        if ($reservation) {
            // Ajouter véhicules
            $this->load->model('Vehicule_reserve_model');
            $reservation->vehicules = $this->Vehicule_reserve_model->get_by_reservation($reservation->code_reservation);

            // Ajouter bagages
            $this->load->model('Bagage_model');
            $reservation->bagages = $this->Bagage_model->get_by_reservation($reservation->code_reservation);

            // Ajouter billets
            $this->load->model('Billet_model');
            $reservation->billets = $this->Billet_model->get_by_reservation($reservation->code_reservation);

            // Fret véhicule associé (nouvelle logique)
            if (!empty($reservation->vehicules)) {
                $this->load->model('Fret_model');
                $reservation->fret_vehicule = $this->Fret_model->get_fret_vehicule_by_reservation($reservation->code_reservation);
            }
        }

        return $reservation;
    }

    /**
     * Obtenir réservations par voyage
     */
    public function get_reservations_by_voyage($voyage_id) {
        $this->db->select('reservations.*, vehicules_reserves.type_vehicule, vehicules_reserves.immatriculation');
        $this->db->from('reservations');
        $this->db->join('vehicules_reserves', 'reservations.code_reservation = vehicules_reserves.code_reservation', 'left');
        $this->db->where('voyage_id', $voyage_id);
        $this->db->where('statut_reservation', 'ACTIVE');
        $this->db->order_by('created_at', 'ASC');
        
        return $this->db->get()->result();
    }

    /**
     * Obtenir réservations en attente de paiement
     */
   
    /**
     * Obtenir rÃ©servations en attente de paiement avec toutes les infos nécessaires
     */

    public function get_reservations_attente_paiement() {
        $this->db->select('
            billets.id as billet_id,
            billets.numero_billet,
            billets.created_at,
            billets.tarif_total,
            reservations.code_reservation,
            reservations.nom,
            reservations.prenom,
            voyages.numero_voyage,
            voyages.date_voyage,
            voyages.heure_depart,
            voyages.port_depart,
            voyages.port_arrivee,
            billets.type_billet
        ');
        $this->db->from('billets');
        $this->db->join('reservations', 'reservations.code_reservation = billets.code_reservation');
        $this->db->join('voyages', 'voyages.id = reservations.voyage_id');
        $this->db->where('billets.statut_billet', 'EMIS');
        $this->db->where('voyages.date_voyage >=', date('Y-m-d'));
        $this->db->order_by('billets.created_at', 'ASC');
        
        return $this->db->get()->result();
    }

   

    /**
     * Compter toutes les réservations
     */
    public function count_all_reservations($filters = array()) {
        $this->apply_filters($filters);
        return $this->db->count_all_results('reservations');
    }

    
    public function get_all_reservations($limit = 20, $offset = 0, $filters = array()) {
        // Sous-requête pour récupérer seulement le dernier billet de chaque réservation
        $this->db->select('reservations.*, voyages.numero_voyage, voyages.date_voyage, voyages.port_depart, voyages.port_arrivee, 
                        utilisateurs.nom as agent_nom, utilisateurs.prenom as agent_prenom,
                        latest_billet.statut_billet, latest_billet.numero_billet');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('utilisateurs', 'reservations.agent_reservation = utilisateurs.id', 'left');
        
        // Join avec sous-requête pour récupérer le dernier billet de chaque réservation
        $this->db->join('(
            SELECT 
                b1.code_reservation,
                b1.statut_billet,
                b1.numero_billet,
                b1.id
            FROM billets b1
            INNER JOIN (
                SELECT 
                    code_reservation, 
                    MAX(id) as max_id
                FROM billets 
                WHERE statut_billet != "ANNULE"
                GROUP BY code_reservation
            ) b2 ON b1.code_reservation = b2.code_reservation AND b1.id = b2.max_id
        ) latest_billet', 'reservations.code_reservation = latest_billet.code_reservation', 'left');
        
        $this->apply_filters($filters);
        
        $this->db->order_by('reservations.created_at', 'DESC');
        $this->db->limit($limit, $offset);
        
        return $this->db->get()->result();
    }

    /**
     * Statistiques des réservations
     */
    public function get_reservations_stats() {
        $stats = array();
        
        // Total
        $stats['total'] = $this->db->count_all('reservations');
        
        // Par statut
        $this->db->select('statut_reservation, COUNT(*) as count');
        $this->db->group_by('statut_reservation');
        $result = $this->db->get('reservations')->result();
        
        foreach ($result as $row) {
            $stats['par_statut'][$row->statut_reservation] = $row->count;
        }
        
        // Aujourd'hui
        $stats['today'] = $this->db->where('DATE(created_at)', date('Y-m-d'))->count_all_results('reservations');
        
        // Cette semaine
        $stats['week'] = $this->db->where('created_at >=', date('Y-m-d', strtotime('-7 days')))->count_all_results('reservations');
        
        return $stats;
    }

    /**
     * Réservations récentes
     */
    public function get_recent_reservations($limit = 10) {
        $this->db->select('reservations.*, voyages.numero_voyage, voyages.date_voyage');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->order_by('reservations.created_at', 'DESC');
        $this->db->limit($limit);
        
        return $this->db->get()->result();
    }

    /**
     * Appliquer filtres
     */
    private function apply_filters($filters) {
        if (!empty($filters['statut_reservation'])) {
            $this->db->where('reservations.statut_reservation', $filters['statut_reservation']);
        }
        if (!empty($filters['date_from'])) {
            $this->db->where('DATE(reservations.created_at) >=', $filters['date_from']);
        }
        if (!empty($filters['date_to'])) {
            $this->db->where('DATE(reservations.created_at) <=', $filters['date_to']);
        }
    }

    public function get_pending_reservations() {
        $this->db->select('reservations.*, voyages.date_voyage, voyages.numero_voyage, 
                        voyages.port_depart, voyages.port_arrivee, voyages.heure_depart,
                        latest_billet.id as billet_id, latest_billet.numero_billet, latest_billet.statut_billet');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        
        // Join avec sous-requête pour récupérer le dernier billet de chaque réservation
        $this->db->join('(
            SELECT 
                b1.code_reservation,
                b1.statut_billet,
                b1.numero_billet,
                b1.id
            FROM billets b1
            INNER JOIN (
                SELECT 
                    code_reservation, 
                    MAX(id) as max_id
                FROM billets 
                WHERE statut_billet != "ANNULE"
                GROUP BY code_reservation
            ) b2 ON b1.code_reservation = b2.code_reservation AND b1.id = b2.max_id
        ) latest_billet', 'reservations.code_reservation = latest_billet.code_reservation');
        
        $this->db->where('reservations.statut_reservation', 'ACTIVE');
        $this->db->where('latest_billet.statut_billet', 'EMIS');
        $this->db->where('voyages.date_voyage >=', date('Y-m-d'));
        $this->db->order_by('reservations.created_at', 'ASC');
        
        return $this->db->get()->result();
    }

  
    /**
     * Obtenir une réservation avec tous ses détails
     */
    public function get_reservation_with_details($reservation_id) {
        $this->db->select('reservations.*, voyages.numero_voyage, voyages.date_voyage, 
                        voyages.heure_depart, voyages.heure_arrivee, voyages.port_depart, 
                        voyages.port_arrivee, ferries.nom as ferry_nom,
                        u1.nom as agent_nom, u1.prenom as agent_prenom');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('ferries', 'voyages.ferry_id = ferries.id');
        $this->db->join('utilisateurs u1', 'reservations.agent_reservation = u1.id', 'left');
        $this->db->where('reservations.id', $reservation_id);
        
        return $this->db->get()->row();
    }

    /**
     * Obtenir les réservations par statut
     */
    public function get_reservations_by_status($status) {
        $this->db->select('reservations.*, voyages.date_voyage, voyages.numero_voyage, 
                        voyages.port_depart, voyages.port_arrivee');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->where('reservations.statut_reservation', $status);
        $this->db->order_by('reservations.created_at', 'DESC');
        
        return $this->db->get()->result();
    }

    

    /**
     * Mettre à jour le statut d'une réservation
     */
    public function update_reservation_status($code_reservation, $new_status, $motif = null) {
        $data = array(
            'statut_reservation' => $new_status,
            'updated_at' => date('Y-m-d H:i:s')
        );
        
        if ($new_status === 'ANNULEE') {
            $data['date_annulation'] = date('Y-m-d H:i:s');
            if ($motif) {
                $data['motif_annulation'] = $motif;
            }
        }
        
        $this->db->where('code_reservation', $code_reservation);
        return $this->db->update('reservations', $data);
    }

    /**
     * Obtenir les statistiques des réservations
     */
    public function get_reservation_stats($date_debut = null, $date_fin = null) {
        $stats = array();
        
        // Construire la requête de base
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        
        if ($date_debut) {
            $this->db->where('voyages.date_voyage >=', $date_debut);
        }
        if ($date_fin) {
            $this->db->where('voyages.date_voyage <=', $date_fin);
        }
        
        // Total des réservations
        $stats['total'] = $this->db->count_all_results('', FALSE);
        
        // Réservations actives
        $this->db->where('reservations.statut_reservation', 'ACTIVE');
        $stats['actives'] = $this->db->count_all_results('', FALSE);
        
        // Reset pour nouvelle requête
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        
        if ($date_debut) {
            $this->db->where('voyages.date_voyage >=', $date_debut);
        }
        if ($date_fin) {
            $this->db->where('voyages.date_voyage <=', $date_fin);
        }
        
        // Réservations annulées
        $this->db->where('reservations.statut_reservation', 'ANNULEE');
        $stats['annulees'] = $this->db->count_all_results('', FALSE);
        
        return $stats;
    }

    /**
     * Vérifier si une réservation peut être modifiée
     */
    public function can_modify_reservation($code_reservation) {
        $this->db->select('reservations.statut_reservation, voyages.date_voyage, voyages.statut as voyage_statut');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->where('reservations.code_reservation', $code_reservation);
        
        $reservation = $this->db->get()->row();
        
        if (!$reservation) {
            return false;
        }
        
        // Ne peut modifier que si réservation active et voyage pas encore commencé
        return ($reservation->statut_reservation === 'ACTIVE' && 
                $reservation->voyage_statut === 'PROGRAMME' &&
                $reservation->date_voyage > date('Y-m-d'));
    }

    /**
     * Obtenir le nombre de passagers par voyage (pour statistiques)
     */
    public function get_passenger_count_by_voyage($voyage_id) {
        $this->db->where('voyage_id', $voyage_id);
        $this->db->where('statut_reservation', 'ACTIVE');
        return $this->db->count_all_results('reservations');
    }














    /**
     * Mettre à jour une réservation (modification simple sans frais)
     */
    public function update_reservation($code_reservation, $data, $vehicule_data = array()) {
        $this->db->trans_start();
        
        try {
            // Sauvegarder l'historique avant modification
            $this->save_modification_history($code_reservation, $data);
            
            // Mettre à jour la réservation (sans les données de véhicule)
            $this->db->where('code_reservation', $code_reservation);
            $this->db->update('reservations', $data);
            
            // Mettre à jour les véhicules avec la même logique que la création
            if (!empty($vehicule_data)) {
                if ($vehicule_data['a_vehicule'] && !empty($vehicule_data['type_vehicule'])) {
                    // Utiliser le même modèle et méthode que la création
                    $this->load->model('Vehicule_reserve_model');
                    
                    // Calculer le tarif véhicule comme dans la création
                    $tarif_vehicule = $this->Config_model->get_tarif_vehicule($vehicule_data['type_vehicule']);
                    
                    // Supprimer l'ancien véhicule s'il existe
                    $this->db->where('code_reservation', $code_reservation);
                    $this->db->delete('vehicules_reserves');
                    
                    // Ajouter le nouveau véhicule avec la même méthode que la création
                    $this->Vehicule_reserve_model->ajouter_vehicule($code_reservation, $vehicule_data, $tarif_vehicule);
                } else {
                    // Supprimer véhicule si décoché
                    $this->db->where('code_reservation', $code_reservation);
                    $this->db->delete('vehicules_reserves');
                }
            }
            
            $this->db->trans_complete();
            return $this->db->trans_status();
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return false;
        }
    }

    /**
     * Créer une modification avec paiement (pour les cas avec frais)
     */
    public function create_modification_with_payment($code_reservation, $modification_data, $vehicule_data, $modification_fee, $montant_final) {
        $this->db->trans_start();
        
        try {
            // 1. Sauvegarder l'historique
            $this->save_modification_history($code_reservation, $modification_data);
            
            // 2. Mettre à jour la réservation avec nouveau statut temporaire
            $modification_data['statut_reservation'] = 'ACTIVE';
            
            $this->db->where('code_reservation', $code_reservation);
            $this->db->update('reservations', $modification_data);
            
            // 3. Gérer le véhicule avec la même logique que la création
            if (!empty($vehicule_data)) {
                if ($vehicule_data['a_vehicule'] && !empty($vehicule_data['type_vehicule'])) {
                    // Utiliser le même modèle et méthode que la création
                    $this->load->model('Vehicule_reserve_model');
                    
                    // Calculer le tarif véhicule comme dans la création
                    $tarif_vehicule = $this->Config_model->get_tarif_vehicule($vehicule_data['type_vehicule']);
                    
                    // Supprimer l'ancien véhicule s'il existe
                    $this->db->where('code_reservation', $code_reservation);
                    $this->db->delete('vehicules_reserves');
                    
                    // Ajouter le nouveau véhicule avec la même méthode que la création
                    $this->Vehicule_reserve_model->ajouter_vehicule($code_reservation, $vehicule_data, $tarif_vehicule);
                } else {
                    // Supprimer véhicule si décoché
                    $this->db->where('code_reservation', $code_reservation);
                    $this->db->delete('vehicules_reserves');
                }
            }
            
            // 4. Créer un billet de régularisation seulement si montant différent de 0
            if ($montant_final != 0) {
                // Récupérer le voyage_id de la réservation modifiée
                $reservation = $this->get_reservation_by_code($code_reservation);
                $voyage_id = $reservation->voyage_id;
                
                $this->load->model('Billet_model');
                
                // Utiliser la méthode existante pour émettre un billet
                $billet_inserted = $this->Billet_model->emettre_nouveau_billet(
                    $code_reservation, 
                    $voyage_id,
                    'MODIFICATION', // raison_emission
                    null // billet_origine_id
                );
                
                if ($billet_inserted) {
                    // Récupérer l'ID du billet créé
                    $billet_id = $this->db->insert_id();
                    
                    // Mettre à jour le billet avec les informations de modification
                    $this->db->where('id', $billet_id);
                    $this->db->update('billets', array(
                        'tarif_total' => abs($montant_final), // Valeur absolue
                        'observations' => 'Régularisation modification - Frais: ' . $modification_fee . ' FC',
                        'type_billet' => 'MODIFICATION'
                    ));
                }
            } else {
                // Pas de billet à créer si montant = 0
                $billet_id = null;
            }
            
            $this->db->trans_complete();
            
            if ($this->db->trans_status() === FALSE) {
                throw new Exception('Erreur lors de la création du billet de modification');
            }
            
            return array(
                'success' => TRUE,
                'billet_id' => $billet_id,
                'code_reservation' => $code_reservation
            );
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return array(
                'success' => FALSE,
                'error' => $e->getMessage()
            );
        }
    }

    /**
     * Sauvegarder l'historique des modifications
     */
    private function save_modification_history($code_reservation, $new_data) {
        // Récupérer les données actuelles
        $current_reservation = $this->get_reservation_by_code($code_reservation);
        
        if ($current_reservation) {
            $history_data = array(
                'code_reservation' => $code_reservation,
                'type_modification' => 'UPDATE',
                'donnees_avant' => json_encode($current_reservation),
                'donnees_apres' => json_encode($new_data),
                'agent_modification' => $this->session->userdata('user_id'),
                'motif_modification' => isset($new_data['motif_modification']) ? $new_data['motif_modification'] : null,
                'date_modification' => date('Y-m-d H:i:s')
            );
            
            $this->db->insert('historique_modifications', $history_data);
        }
    }

    /**
     * Valider une modification après paiement
     */
    public function confirm_modification_payment($code_reservation, $billet_id) {
        $this->db->trans_start();
        
        try {
            // Mettre à jour le statut de la réservation
            $this->db->where('code_reservation', $code_reservation);
            $this->db->update('reservations', array(
                'statut_reservation' => 'ACTIVE',
                'date_validation_modification' => date('Y-m-d H:i:s')
            ));
            
            // Marquer le billet comme payé
            $this->load->model('Billet_model');
            $this->Billet_model->mark_as_paid($billet_id);
            
            $this->db->trans_complete();
            return $this->db->trans_status();
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return false;
        }
    }

    /**
     * Obtenir les modifications en attente de paiement
     */
    public function get_pending_modifications() {
        $this->db->select('reservations.*, voyages.numero_voyage, voyages.date_voyage, 
                        voyages.port_depart, voyages.port_arrivee,
                        billets.id as billet_id, billets.montant_total as montant_modification');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('billets', 'reservations.code_reservation = billets.code_reservation');
        $this->db->where('reservations.statut_reservation', 'MODIFICATION_PENDING');
        $this->db->where('billets.type_billet', 'MODIFICATION');
        $this->db->where('billets.statut_billet', 'EMIS');
        $this->db->order_by('reservations.date_modification', 'ASC');
        
        return $this->db->get()->result();
    }

    /**
     * Annuler une modification en cours
     */
    public function cancel_pending_modification($code_reservation) {
        $this->db->trans_start();
        
        try {
            // Restaurer les données depuis l'historique (dernière version valide)
            $this->db->select('donnees_avant');
            $this->db->from('historique_modifications');
            $this->db->where('code_reservation', $code_reservation);
            $this->db->where('type_modification', 'UPDATE');
            $this->db->order_by('date_modification', 'DESC');
            $this->db->limit(1);
            
            $history = $this->db->get()->row();
            
            if ($history) {
                $original_data = json_decode($history->donnees_avant, true);
                
                // Restaurer les données originales
                unset($original_data['id']); // Ne pas écraser l'ID
                $original_data['statut_reservation'] = 'ACTIVE';
                
                $this->db->where('code_reservation', $code_reservation);
                $this->db->update('reservations', $original_data);
            }
            
            // Annuler le billet de modification
            $this->db->where('code_reservation', $code_reservation);
            $this->db->where('type_billet', 'MODIFICATION');
            $this->db->update('billets', array(
                'statut_billet' => 'ANNULE',
                'date_annulation' => date('Y-m-d H:i:s')
            ));
            
            $this->db->trans_complete();
            return $this->db->trans_status();
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return false;
        }
    }


    /**
     * Recherche simple de réservations
     */
    public function search_reservations_simple($code = null, $telephone = null, $type_piece = null, $numero_piece = null) {
        $this->db->select('
            reservations.*,
            voyages.numero_voyage, voyages.date_voyage, voyages.port_depart, voyages.port_arrivee,
            utilisateurs.nom as agent_nom, utilisateurs.prenom as agent_prenom,
            latest_billet.statut_billet, latest_billet.numero_billet
        ');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('utilisateurs', 'reservations.agent_reservation = utilisateurs.id', 'left');
        $this->db->join('(
            SELECT 
                b1.code_reservation, b1.statut_billet, b1.numero_billet, b1.id
            FROM billets b1
            INNER JOIN (
                SELECT code_reservation, MAX(id) as max_id
                FROM billets WHERE statut_billet != "ANNULE"
                GROUP BY code_reservation
            ) b2 ON b1.code_reservation = b2.code_reservation AND b1.id = b2.max_id
        ) latest_billet', 'reservations.code_reservation = latest_billet.code_reservation', 'left');
        
        $this->db->group_start();
        
        // Recherche par code
        if ($code) {
            $this->db->or_like('reservations.code_reservation', $code);
        }
        
        // Recherche par téléphone
        if ($telephone) {
            $this->db->or_like('reservations.telephone', $telephone);
        }
        
        // Recherche par pièce d'identité
        if ($type_piece && $numero_piece) {
            $this->db->or_group_start();
            $this->db->where('reservations.type_piece', $type_piece);
            $this->db->like('reservations.numero_piece', $numero_piece);
            $this->db->group_end();
        }
        
        $this->db->group_end();
        
        $this->db->order_by('reservations.created_at', 'DESC');
        $this->db->limit(20); // Limite de 20 résultats max
        
        return $this->db->get()->result();
    }



   

    /**
     * Calculer les pénalités d'annulation
     * @param string $code_reservation
     * @param bool $bypass_penalites (pour admin uniquement)
     */
    public function calculer_penalites_annulation($code_reservation, $bypass_penalites = false) {
        // Récupérer la réservation avec les infos du voyage
        $this->db->select('reservations.*, voyages.date_voyage');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->where('reservations.code_reservation', $code_reservation);
        $reservation = $this->db->get()->row();
        
        if (!$reservation) {
            return array('error' => 'Réservation introuvable');
        }
        
        // Vérifier si la réservation est payée
        $this->load->model('Billet_model');
        $billet_paye = $this->Billet_model->is_reservation_paid($code_reservation);
        
        if (!$billet_paye) {
            // Pas payée = annulation simple sans remboursement
            return array(
                'type' => 'SIMPLE',
                'penalite_pct' => 0,
                'montant_original' => $reservation->tarif_total,
                'penalite_montant' => 0,
                'montant_rembourse' => 0,
                'message' => 'Annulation simple - Réservation non payée',
                'bypass_admin' => false
            );
        }
        
        // ✅ NOUVEAU : Bypass admin = remboursement intégral
        if ($bypass_penalites) {
            $montant_original = floatval($reservation->tarif_total);
            return array(
                'type' => 'REMBOURSEMENT_INTEGRAL_ADMIN',
                'jours_restants' => 'N/A',
                'penalite_pct' => 0,
                'montant_original' => $montant_original,
                'penalite_montant' => 0,
                'montant_rembourse' => $montant_original,
                'message' => '⚠️ REMBOURSEMENT INTÉGRAL - Autorisation Admin',
                'bypass_admin' => true
            );
        }
        
        // Calculer les jours jusqu'au voyage
        $date_voyage = new DateTime($reservation->date_voyage);
        $date_actuelle = new DateTime();
        $jours_restants = $date_actuelle->diff($date_voyage)->days;
        
        // Si la date du voyage est déjà passée
        if ($date_voyage < $date_actuelle) {
            return array(
                'type' => 'VOYAGE_PASSE',
                'jours_restants' => 0,
                'penalite_pct' => 0,
                'montant_original' => floatval($reservation->tarif_total),
                'penalite_montant' => floatval($reservation->tarif_total),
                'montant_rembourse' => 0,
                'message' => 'Aucun remboursement - Voyage déjà effectué',
                'bypass_admin' => false
            );
        }
        
        $montant_original = floatval($reservation->tarif_total);

        // Lire les règles depuis la config (plus de valeurs hardcodées)
        $config = $this->Config_model->get_all_config_systeme();
        $seuil_haut  = intval($config['ANNULATION_SEUIL_J_HAUT']       ?? 4);
        $pct_haut    = intval($config['ANNULATION_PENALITE_HAUTE_PCT']  ?? 10);
        $seuil_bas   = intval($config['ANNULATION_SEUIL_J_BAS']        ?? 1);
        $pct_bas     = intval($config['ANNULATION_PENALITE_BASSE_PCT']  ?? 25);

        // Appliquer les règles de pénalités
        if ($jours_restants >= $seuil_haut) {
            $penalite_pct = $pct_haut;
            $type         = 'REMBOURSEMENT_PARTIEL';
            $message      = 'Remboursement de ' . (100 - $pct_haut) . '% (pénalité ' . $pct_haut . '%)';
        } elseif ($jours_restants >= $seuil_bas) {
            $penalite_pct = $pct_bas;
            $type         = 'REMBOURSEMENT_PARTIEL';
            $message      = 'Remboursement de ' . (100 - $pct_bas) . '% (pénalité ' . $pct_bas . '%)';
        } else {
            $penalite_pct = 100;
            $type         = 'AUCUN_REMBOURSEMENT';
            $message      = 'Aucun remboursement - Annulation tardive (moins de ' . $seuil_bas . ' jour(s))';
        }
        
        $penalite_montant = ($montant_original * $penalite_pct) / 100;
        $montant_rembourse = $montant_original - $penalite_montant;
        
        return array(
            'type' => $type,
            'jours_restants' => $jours_restants,
            'penalite_pct' => $penalite_pct,
            'montant_original' => $montant_original,
            'penalite_montant' => $penalite_montant,
            'montant_rembourse' => $montant_rembourse,
            'message' => $message,
            'bypass_admin' => false
        );
    }

    /**
     * Annuler une réservation avec calcul des pénalités
     * @param string $code_reservation
     * @param string $motif
     * @param int $agent_id
     * @param bool $bypass_penalites (pour admin uniquement)
     */
    public function annuler_reservation_avec_penalites($code_reservation, $motif, $agent_id, $bypass_penalites = false) {
        $this->db->trans_start();
        
        try {
            // Calculer les pénalités (avec ou sans bypass)
            $penalites = $this->calculer_penalites_annulation($code_reservation, $bypass_penalites);
            
            if (isset($penalites['error'])) {
                throw new Exception($penalites['error']);
            }
            
            // Mettre à jour le statut de la réservation
            $this->db->where('code_reservation', $code_reservation);
            $this->db->update('reservations', array(
                'statut_reservation' => 'ANNULEE',
                'date_annulation' => date('Y-m-d H:i:s'),
                'motif_annulation' => $motif,
                'agent_annulation' => $agent_id,
                'penalite_pct' => $penalites['penalite_pct'],
                'montant_penalite' => $penalites['penalite_montant'],
                'montant_rembourse' => $penalites['montant_rembourse']
            ));
            
            // Annuler le billet correspondant
            $this->load->model('Billet_model');
            $this->Billet_model->annuler_billets_reservation($code_reservation);
            
            $billet_remboursement_id = null;
            
            // Créer un billet de remboursement si nécessaire
            if ($penalites['montant_rembourse'] > 0) {
                $reservation = $this->get_reservation_by_code($code_reservation);
                
                $billet_remboursement_id = $this->Billet_model->creer_billet_remboursement(
                    $code_reservation,
                    $reservation->voyage_id,
                    $penalites['montant_rembourse'],
                    $penalites
                );
            }
            
            $this->db->trans_complete();
            
            if ($this->db->trans_status() === FALSE) {
                throw new Exception('Erreur lors de l\'annulation');
            }
            
            return array(
                'success' => TRUE,
                'penalites' => $penalites,
                'billet_remboursement_id' => $billet_remboursement_id
            );
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return array(
                'success' => FALSE,
                'error' => $e->getMessage()
            );
        }
    }

    /**
     * Récupérer les passagers embarqués d'un voyage avec leurs tarifs
     * @param int $voyage_id
     * @return array Liste des passagers embarqués
     */
    public function get_passagers_embarques($voyage_id) {
        $this->db->select('
            reservations.id,
            reservations.code_reservation,
            reservations.nom,
            reservations.prenom,
            reservations.date_naissance,
            reservations.age_au_voyage,
            reservations.sexe,
            reservations.nationalite,
            reservations.type_piece,
            reservations.numero_piece,
            reservations.telephone,
            reservations.email,
            reservations.tarif_passager,
            reservations.tarif_vehicule,
            reservations.tarif_bagages,
            reservations.tarif_total,
            reservations.statut_reservation,
            billets.date_embarquement,
            billets.statut_billet,
            vehicules_reserves.type_vehicule,
            vehicules_reserves.immatriculation
        ');
        $this->db->from('reservations');
        $this->db->join('billets', 'reservations.code_reservation = billets.code_reservation AND billets.voyage_id = reservations.voyage_id', 'left');
        $this->db->join('vehicules_reserves', 'reservations.code_reservation = vehicules_reserves.code_reservation', 'left');
        $this->db->where('reservations.voyage_id', $voyage_id);
        $this->db->where('billets.statut_billet', 'EMBARQUE');
        $this->db->order_by('reservations.nom', 'ASC');
        
        return $this->db->get()->result();
    }

    /**
     * Récupérer les passagers NO-SHOW d'un voyage avec leurs tarifs
     * Pour le rapport de recettes
     * @param int $voyage_id
     * @return array Liste des passagers No-Show avec code, nom et montant
     */
    public function get_passagers_no_show($voyage_id) {
        $this->db->select('
            reservations.id,
            reservations.code_reservation,
            reservations.nom,
            reservations.prenom,
            reservations.tarif_total,
            reservations.statut_reservation
        ');
        $this->db->from('reservations');
        $this->db->where('reservations.voyage_id', $voyage_id);
        $this->db->where('reservations.statut_reservation', 'NO_SHOW');
        $this->db->order_by('reservations.nom', 'ASC');
        
        return $this->db->get()->result();
    }

    /**
     * Récupérer les passagers NON embarqués d'un voyage (No-Show et Annulés)
     * @param int $voyage_id
     * @return array Liste des passagers non embarqués
     */
    public function get_passagers_non_embarques($voyage_id) {
        $this->db->select('
            reservations.id,
            reservations.code_reservation,
            reservations.nom,
            reservations.prenom,
            reservations.statut_reservation,
            reservations.motif_annulation,
            billets.statut_billet
        ');
        $this->db->from('reservations');
        $this->db->join('billets', 'reservations.code_reservation = billets.code_reservation AND billets.voyage_id = reservations.voyage_id', 'left');
        $this->db->where('reservations.voyage_id', $voyage_id);
        $this->db->group_start();
            $this->db->where('reservations.statut_reservation', 'NO_SHOW');
            $this->db->or_where('reservations.statut_reservation', 'ANNULEE');
            $this->db->or_where_in('billets.statut_billet', array('ENREGISTRE', 'PAYE', 'EMIS'));
        $this->db->group_end();
        $this->db->where('billets.statut_billet !=', 'EMBARQUE');
        $this->db->order_by('reservations.nom', 'ASC');
        
        return $this->db->get()->result();
    }

    /**
     * Calculer les statistiques d'un voyage incluant moto_benes et bagages
     * Catégories d'âge selon la grille tarifaire:
     * - Bébés: < 2 ans (0-1)
     * - Enfants: >= 2 && <= 12 ans (2-12)
     * - Adultes: > 12 ans (13+)
     * 
     * @param int $voyage_id
     * @param object $voyage Objet voyage
     * @return array Statistiques détaillées
     */
    /*public function get_stats_voyage($voyage_id, $voyage) {
        $passagers_embarques = $this->get_passagers_embarques($voyage_id);
        
        $stats = array(
            'total_embarques' => 0,
            'total_adultes' => 0,
            'total_enfants' => 0,
            'total_bebes' => 0,
            'total_hommes' => 0,
            'total_femmes' => 0,
            'total_vehicules' => 0,
            'total_motos' => 0,
            'total_moto_benes' => 0,
            'total_no_show' => 0,
            'taux_presentation' => 0,
            'total_recettes' => 0,
            'total_bagages' => 0,
            'poids_total_bagages' => 0
        );
        
        foreach ($passagers_embarques as $p) {
            $stats['total_embarques']++;
            $stats['total_recettes'] += isset($p->tarif_total) ? floatval($p->tarif_total) : 0;
            
            // Calcul de l'âge
            $date_voyage = date_create($voyage->date_voyage);
            $date_naissance = date_create($p->date_naissance);
            $age = date_diff($date_naissance, $date_voyage)->y;
            
            // Catégoriser depuis tarifs_passagers (source unique)
            $categorie = $this->Config_model->categoriser_passager($age, $grille_id);
            if ($categorie === 'bebe' || $categorie === 'gratuit') {
                $stats['total_bebes']++;
            } elseif ($categorie === 'enfant') {
                $stats['total_enfants']++;
            } else {
                $stats['total_adultes']++;
            }

            // Sexe
            if ($p->sexe == 'M') {
                $stats['total_hommes']++;
            } else {
                $stats['total_femmes']++;
            }
            
            // Véhicules - incluant moto_bene
            if (isset($p->type_vehicule) && !empty($p->type_vehicule)) {
                $type = strtolower($p->type_vehicule);
                if ($type == 'moto') {
                    $stats['total_motos']++;
                } elseif ($type == 'moto_benne') {
                    $stats['total_moto_benes']++;
                } else {
                    $stats['total_vehicules']++;
                }
            }
        }
        
        // Calculer No-Show
        $passagers_no_show = $this->get_passagers_no_show($voyage_id);
        $stats['total_no_show'] = count($passagers_no_show);
        
        // Taux de présentation
        $total_reserves = $stats['total_embarques'] + $stats['total_no_show'];
        if ($total_reserves > 0) {
            $stats['taux_presentation'] = round(($stats['total_embarques'] / $total_reserves) * 100, 1);
        }
        
        // Statistiques bagages - Utiliser Bagage_model
        $CI =& get_instance();
        $CI->load->model('Bagage_model');
        $stats_bagages = $CI->Bagage_model->get_stats_embarques($voyage_id);
        $stats['total_bagages'] = $stats_bagages->total_bagages;
        $stats['poids_total_bagages'] = $stats_bagages->poids_total_kg;
        
        return $stats;
    }*/


    public function get_stats_voyage($voyage_id, $voyage) {
        $passagers_embarques = $this->get_passagers_embarques($voyage_id);
        $grille_id = isset($voyage->grille_tarifaire_id) ? $voyage->grille_tarifaire_id : null;
        
        $stats = array(
            'total_embarques' => 0,
            'total_adultes' => 0,
            'total_enfants' => 0,
            'total_bebes' => 0,
            'total_hommes' => 0,
            'total_femmes' => 0,
            'total_no_show' => 0,
            'taux_presentation' => 0,
            'total_recettes' => 0,
            'total_bagages' => 0,
            'poids_total_bagages' => 0
        );
        
        foreach ($passagers_embarques as $p) {
            $stats['total_embarques']++;
            $stats['total_recettes'] += isset($p->tarif_total) ? floatval($p->tarif_total) : 0;
            
            // Utiliser l'âge stocké à la réservation
            $age = intval($p->age_au_voyage);
            
            // Catégoriser depuis tarifs_passagers (source unique)
            $categorie = $this->Config_model->categoriser_passager($age, $grille_id);
            if ($categorie === 'bebe' || $categorie === 'gratuit') {
                $stats['total_bebes']++;
            } elseif ($categorie === 'enfant') {
                $stats['total_enfants']++;
            } else {
                $stats['total_adultes']++;
            }
            
            // Sexe
            if ($p->sexe == 'M') {
                $stats['total_hommes']++;
            } else {
                $stats['total_femmes']++;
            }
        }
        
        // Calculer No-Show
        $passagers_no_show = $this->get_passagers_no_show($voyage_id);
        $stats['total_no_show'] = count($passagers_no_show);
        
        // Taux de présentation
        $total_reserves = $stats['total_embarques'] + $stats['total_no_show'];
        if ($total_reserves > 0) {
            $stats['taux_presentation'] = round(($stats['total_embarques'] / $total_reserves) * 100, 1);
        }
        
        // Statistiques bagages - Utiliser Bagage_model
        $CI =& get_instance();
        $CI->load->model('Bagage_model');
        $stats_bagages = $CI->Bagage_model->get_stats_embarques($voyage_id);
        $stats['total_bagages'] = $stats_bagages->total_bagages;
        $stats['poids_total_bagages'] = $stats_bagages->poids_total_kg;
        
        return $stats;
    }

    /**
     * Calculer le détail des recettes par catégorie pour un voyage
     * Catégories d'âge selon la grille tarifaire:
     * - Bébés: < 2 ans (0-1)
     * - Enfants: >= 2 && <= 12 ans (2-12)
     * - Adultes: > 12 ans (13+)
     * 
     * @param int $voyage_id
     * @param object $voyage Objet voyage
     * @return array Détail des recettes
     */
    /*public function get_recettes_details($voyage_id, $voyage) {
        $passagers_embarques = $this->get_passagers_embarques($voyage_id);
        
        $recettes = array(
            'adultes' => array('quantite' => 0, 'total' => 0),
            'enfants' => array('quantite' => 0, 'total' => 0),
            'bebes' => array('quantite' => 0, 'total' => 0),
            'vehicules' => array('quantite' => 0, 'total' => 0),
            'motos' => array('quantite' => 0, 'total' => 0),
            'moto_benes' => array('quantite' => 0, 'total' => 0),
            'bagages' => array('quantite' => 0, 'total' => 0),
            'total_general' => 0
        );
        
        foreach ($passagers_embarques as $p) {
            $recettes['total_general'] += isset($p->tarif_total) ? floatval($p->tarif_total) : 0;
            
            // Calcul de l'âge pour catégoriser
            $date_voyage = date_create($voyage->date_voyage);
            $date_naissance = date_create($p->date_naissance);
            $age = date_diff($date_naissance, $date_voyage)->y;
            
            // Tarif passager par catégorie
            $tarif_passager = isset($p->tarif_passager) ? floatval($p->tarif_passager) : 0;
            
            // Catégoriser depuis tarifs_passagers (source unique)
            $categorie = $this->Config_model->categoriser_passager($age, $grille_id);
            if ($categorie === 'bebe' || $categorie === 'gratuit') {
                $recettes['bebes']['quantite']++;
                $recettes['bebes']['total'] += $tarif_passager;
            } elseif ($categorie === 'enfant') {
                $recettes['enfants']['quantite']++;
                $recettes['enfants']['total'] += $tarif_passager;
            } else {
                $recettes['adultes']['quantite']++;
                $recettes['adultes']['total'] += $tarif_passager;
            }
            
            // Tarif véhicule
            $tarif_vehicule = isset($p->tarif_vehicule) ? floatval($p->tarif_vehicule) : 0;
            if (isset($p->type_vehicule) && !empty($p->type_vehicule)) {
                $type = strtolower($p->type_vehicule);
                if ($type == 'moto') {
                    $recettes['motos']['quantite']++;
                    $recettes['motos']['total'] +=($tarif_vehicule);
                } elseif ($type == 'moto_benne') {
                    $recettes['moto_benes']['quantite']++;
                    $recettes['moto_benes']['total'] += $tarif_vehicule;
                } else {
                    $recettes['vehicules']['quantite']++;
                    $recettes['vehicules']['total'] += $tarif_vehicule;
                }
            }
            
            // Tarif bagages
            $tarif_bagages = isset($p->tarif_bagages) ? floatval($p->tarif_bagages) : 0;
            if ($tarif_bagages > 0) {
                $recettes['bagages']['quantite']++;
                $recettes['bagages']['total'] += $tarif_bagages;
            }
        }
        
        return $recettes;
    }*/
    public function get_recettes_details($voyage_id, $voyage) {
        $passagers_embarques = $this->get_passagers_embarques($voyage_id);
        $grille_id = isset($voyage->grille_tarifaire_id) ? $voyage->grille_tarifaire_id : null;
        
        $recettes = array(
            'adultes' => array('quantite' => 0, 'total' => 0),
            'enfants' => array('quantite' => 0, 'total' => 0),
            'bebes' => array('quantite' => 0, 'total' => 0),
            'bagages' => array('quantite' => 0, 'total' => 0),
            'total_general' => 0
        );
        
        foreach ($passagers_embarques as $p) {
            $recettes['total_general'] += isset($p->tarif_total) ? floatval($p->tarif_total) : 0;
            
            // Utiliser l'âge stocké à la réservation (calculé par rapport à la date du voyage)
            $age = isset($p->age_au_voyage) ? intval($p->age_au_voyage) : 0;
            
            // Tarif passager par catégorie
            $tarif_passager = isset($p->tarif_passager) ? floatval($p->tarif_passager) : 0;
            
            // Catégoriser depuis tarifs_passagers (source unique)
            $categorie = $this->Config_model->categoriser_passager($age, $grille_id);
            if ($categorie === 'bebe' || $categorie === 'gratuit') {
                $recettes['bebes']['quantite']++;
                $recettes['bebes']['total'] += $tarif_passager;
            } elseif ($categorie === 'enfant') {
                $recettes['enfants']['quantite']++;
                $recettes['enfants']['total'] += $tarif_passager;
            } else {
                $recettes['adultes']['quantite']++;
                $recettes['adultes']['total'] += $tarif_passager;
            }
            
            // Tarif bagages
            $tarif_bagages = isset($p->tarif_bagages) ? floatval($p->tarif_bagages) : 0;
            if ($tarif_bagages > 0) {
                $recettes['bagages']['quantite']++;
                $recettes['bagages']['total'] += $tarif_bagages;
            }
        }
        
        return $recettes;
    }
    









    /**
     * Vérifier si une réservation peut être modifiée
     * 
     * RÈGLES:
     * - EMIS → Modifiable sans frais
     * - PAYE + >= SEUIL_MODIFICATION_HEURES → Modifiable avec frais FRAIS_MODIFICATION_FC
     * - PAYE + <24h → Non modifiable
     * - Autres → Non modifiable
     */
    public function check_modification_eligibility($code_reservation) {
        $this->db->select('
            reservations.*, 
            voyages.date_voyage, 
            voyages.heure_depart,
            billets.id as billet_id,
            billets.statut_billet,
            billets.numero_billet
        ');
        $this->db->from('reservations');
        $this->db->join('voyages', 'reservations.voyage_id = voyages.id');
        $this->db->join('billets', 'reservations.code_reservation = billets.code_reservation AND billets.voyage_id = reservations.voyage_id');
        $this->db->where('reservations.code_reservation', $code_reservation);
        $this->db->where('billets.statut_billet !=', 'ANNULE');
        $this->db->order_by('billets.id', 'DESC');
        $this->db->limit(1);
        
        $reservation = $this->db->get()->row();
        
        if (!$reservation) {
            return array(
                'modifiable' => false,
                'frais' => 0,
                'message' => 'Réservation ou billet introuvable',
                'statut_billet' => null
            );
        }
        
        if ($reservation->statut_reservation !== 'ACTIVE') {
            return array(
                'modifiable' => false,
                'frais' => 0,
                'message' => 'La réservation n\'est plus active',
                'statut_billet' => $reservation->statut_billet
            );
        }
        
        // Calculer heures restantes
        $voyage_datetime = new DateTime($reservation->date_voyage . ' ' . $reservation->heure_depart);
        $now = new DateTime();
        
        if ($voyage_datetime < $now) {
            return array(
                'modifiable' => false,
                'frais' => 0,
                'message' => 'Le voyage a déjà eu lieu',
                'statut_billet' => $reservation->statut_billet
            );
        }
        
        $interval = $now->diff($voyage_datetime);
        $hours_until_voyage = ($interval->days * 24) + $interval->h;

        // Lire les seuils depuis la config
        $config = $this->Config_model->get_all_config_systeme();
        $seuil_heures = intval($config['SEUIL_MODIFICATION_HEURES'] ?? 24);
        $frais_fc     = intval($config['FRAIS_MODIFICATION_FC']     ?? 2000);

        switch ($reservation->statut_billet) {
            case 'EMIS':
                return array(
                    'modifiable'      => true,
                    'frais'           => 0,
                    'message'         => 'Modification gratuite (billet non payé)',
                    'statut_billet'   => 'EMIS',
                    'billet_id'       => $reservation->billet_id,
                    'numero_billet'   => $reservation->numero_billet,
                    'heures_restantes'=> $hours_until_voyage
                );

            case 'PAYE':
                if ($hours_until_voyage < $seuil_heures) {
                    return array(
                        'modifiable'       => false,
                        'frais'            => 0,
                        'message'          => 'Modification impossible à moins de ' . $seuil_heures . 'h du départ',
                        'statut_billet'    => 'PAYE',
                        'heures_restantes' => $hours_until_voyage
                    );
                }
                return array(
                    'modifiable'      => true,
                    'frais'           => $frais_fc,
                    'message'         => 'Frais de modification : ' . number_format($frais_fc) . ' FC',
                    'statut_billet'   => 'PAYE',
                    'billet_id'       => $reservation->billet_id,
                    'numero_billet'   => $reservation->numero_billet,
                    'heures_restantes'=> $hours_until_voyage
                );
                
            case 'ENREGISTRE':
            case 'EMBARQUE':
                return array(
                    'modifiable' => false,
                    'frais' => 0,
                    'message' => 'Modification impossible - Passager déjà ' . strtolower($reservation->statut_billet),
                    'statut_billet' => $reservation->statut_billet
                );
                
            default:
                return array(
                    'modifiable' => false,
                    'frais' => 0,
                    'message' => 'Statut incompatible',
                    'statut_billet' => $reservation->statut_billet
                );
        }
    }


    /**
     * Effectuer une modification
     * 
     * - EMIS → Modification directe
     * - PAYE → Modification + billet passe à EMIS avec frais_modification
     */
    public function process_modification($code_reservation, $modification_data, $vehicule_data = array()) {
        $eligibility = $this->check_modification_eligibility($code_reservation);
        
        if (!$eligibility['modifiable']) {
            return array('success' => false, 'message' => $eligibility['message']);
        }
        
        $this->db->trans_start();
        
        try {
            // Enregistrer historique
            $this->save_reservation_history($code_reservation, 'MODIFICATION', array(
                'frais' => $eligibility['frais'],
                'statut_billet_avant' => $eligibility['statut_billet']
            ));
            
            // Ajouter date_modification à la réservation
            $modification_data['date_modification'] = date('Y-m-d H:i:s');
            
            // Appliquer modifications sur réservation
            $this->db->where('code_reservation', $code_reservation);
            $this->db->update('reservations', $modification_data);
            
            // Gérer véhicule
            if (!empty($vehicule_data)) {
                $this->update_vehicle_data($code_reservation, $vehicule_data);
            }
            
            // Si billet PAYE → passer à EMIS avec frais_modification
            if ($eligibility['statut_billet'] === 'PAYE') {
                // Billet passe à EMIS avec frais de modification
                $this->db->where('id', $eligibility['billet_id']);
                $this->db->update('billets', array(
                    'statut_billet' => 'EMIS',
                    'frais_modification' => $eligibility['frais'],
                    'date_modification' => date('Y-m-d H:i:s'),
					'voyage_id' => $modification_data['voyage_id']
                ));
                
                $this->db->trans_complete();
                
                return array(
                    'success' => true,
                    'message' => 'Modification effectuée. Le passager doit régler ' . number_format($eligibility['frais']) . ' FC à la caisse.',
                    'frais' => $eligibility['frais']
                );
            }
            
            // Billet EMIS → modification directe terminée
            $this->db->trans_complete();
            
            return array(
                'success' => true,
                'message' => 'Modification effectuée avec succès',
                'frais' => 0
            );
            
        } catch (Exception $e) {
            $this->db->trans_rollback();
            return array('success' => false, 'message' => $e->getMessage());
        }
    }


    /**
     * Enregistrer historique réservation
     */
    public function save_reservation_history($code_reservation, $type_action, $details = array()) {
        $reservation = $this->get_reservation_by_code($code_reservation);
        
        $this->db->where('code_reservation', $code_reservation);
        $this->db->where('statut_billet !=', 'ANNULE');
        $this->db->order_by('id', 'DESC');
        $billet = $this->db->get('billets')->row();
        
        $history_data = array(
            'code_reservation' => $code_reservation,
            'type_action' => $type_action,
            'statut_reservation_avant' => $reservation ? $reservation->statut_reservation : null,
            'statut_billet_avant' => $billet ? $billet->statut_billet : null,
            'donnees_modification' => json_encode($details),
            'agent_id' => $this->session->userdata('user_id'),
            'created_at' => date('Y-m-d H:i:s')
        );
        
        $this->db->insert('historique_reservations', $history_data);
    }


    /**
     * Mettre à jour véhicule
     */
    private function update_vehicle_data($code_reservation, $vehicule_data) {
        if (!empty($vehicule_data['a_vehicule']) && !empty($vehicule_data['type_vehicule'])) {
            $this->db->where('code_reservation', $code_reservation);
            $this->db->delete('vehicules_reserves');
            
            $this->load->model('Vehicule_reserve_model');
            $tarif = $this->Config_model->get_tarif_vehicule($vehicule_data['type_vehicule']);
            $this->Vehicule_reserve_model->ajouter_vehicule($code_reservation, $vehicule_data, $tarif);
        } else {
            $this->db->where('code_reservation', $code_reservation);
            $this->db->delete('vehicules_reserves');
        }
    }








    









        













   
}
?>