import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.File;
import org.mindrot.jbcrypt.BCrypt;
import com.toedter.calendar.JDateChooser;

public class FirstCarApp extends JFrame {
    private CardLayout cardLayout;
    private JPanel mainPanel;
    private JPanel contentArea;

    // Constantes UI pour un look professionnel (Assorties aux couleurs du site PHP)
    private static final Color PRIMARY_COLOR = new Color(232, 130, 12); // Orange du site
    private static final Color ACCENT_COLOR = new Color(245, 165, 53); // Orange clair du site
    private static final Color BACKGROUND_COLOR = new Color(15, 15, 15); // Sombre du site
    private static final Color CARD_COLOR = new Color(26, 26, 26); // Sombre2 du site
    private static final Color CARD_BORDER_COLOR = new Color(36, 36, 36); // Sombre3 du site
    private static final Color TEXT_COLOR = new Color(240, 237, 232); // Clair du site
    private static final Color TEXT_DIM_COLOR = new Color(200, 196, 188); // Clair2 du site
    private static final Color SELECTION_COLOR = new Color(232, 130, 12, 40); // Orange subtil pour la sélection
    private static final Font FONT_TITLE = new Font("Montserrat", Font.BOLD, 32);
    private static final Font FONT_SUBTITLE = new Font("Montserrat", Font.BOLD, 20);
    private static final Font FONT_NORMAL = new Font("Montserrat", Font.PLAIN, 14);

    public FirstCarApp() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            
            // STYLE GLOBAL DE L'UI POUR UNE LISIBILITÉ ABSOLUE
            UIManager.put("Panel.background", BACKGROUND_COLOR);
            UIManager.put("Label.foreground", TEXT_COLOR);
            
            // Champs de texte
            UIManager.put("TextField.background", CARD_COLOR);
            UIManager.put("TextField.foreground", TEXT_COLOR);
            UIManager.put("TextField.caretForeground", TEXT_COLOR);
            UIManager.put("PasswordField.background", CARD_COLOR);
            UIManager.put("PasswordField.foreground", TEXT_COLOR);
            UIManager.put("PasswordField.caretForeground", TEXT_COLOR);
            
            // Boutons
            UIManager.put("Button.background", CARD_BORDER_COLOR);
            UIManager.put("Button.foreground", TEXT_COLOR);
            
            // Listes et ComboBoxes
            UIManager.put("ComboBox.background", CARD_COLOR);
            UIManager.put("ComboBox.foreground", TEXT_COLOR);
            UIManager.put("ComboBox.selectionBackground", PRIMARY_COLOR);
            UIManager.put("ComboBox.selectionForeground", Color.BLACK);
            UIManager.put("List.background", CARD_COLOR);
            UIManager.put("List.foreground", TEXT_COLOR);
            UIManager.put("List.selectionBackground", PRIMARY_COLOR);
            UIManager.put("List.selectionForeground", Color.BLACK);
            
            // Tables
            UIManager.put("Table.background", CARD_COLOR);
            UIManager.put("Table.foreground", TEXT_COLOR);
            UIManager.put("Table.gridColor", CARD_BORDER_COLOR);
            UIManager.put("Table.selectionBackground", SELECTION_COLOR);
            UIManager.put("Table.selectionForeground", PRIMARY_COLOR);
            UIManager.put("TableHeader.background", CARD_BORDER_COLOR);
            UIManager.put("TableHeader.foreground", TEXT_DIM_COLOR);
            
            // Onglets (Amélioration radicale de la visibilité)
            UIManager.put("TabbedPane.background", CARD_COLOR);
            UIManager.put("TabbedPane.foreground", TEXT_COLOR);
            UIManager.put("TabbedPane.selected", PRIMARY_COLOR);
            UIManager.put("TabbedPane.selectedForeground", Color.WHITE);
            UIManager.put("TabbedPane.selectHighlight", PRIMARY_COLOR);
            UIManager.put("TabbedPane.borderHighlightColor", PRIMARY_COLOR);
            UIManager.put("TabbedPane.darkShadow", Color.BLACK);
            UIManager.put("TabbedPane.light", CARD_BORDER_COLOR);
            UIManager.put("TabbedPane.highlight", CARD_BORDER_COLOR);
            UIManager.put("TabbedPane.focus", new Color(0, 0, 0, 0)); 
            
            UIManager.put("TabbedPane.contentAreaColor", BACKGROUND_COLOR);
            UIManager.put("TabbedPane.opaque", true);
            
            // ScrollPane (Barre de défilement)
            UIManager.put("ScrollPane.background", BACKGROUND_COLOR);
            UIManager.put("ScrollPane.viewportBorder", BorderFactory.createEmptyBorder());
            
            // Correctifs pour la visibilité de JOptionPane
            UIManager.put("OptionPane.background", BACKGROUND_COLOR);
            UIManager.put("Panel.background", BACKGROUND_COLOR);
            UIManager.put("OptionPane.messageForeground", Color.WHITE);
            UIManager.put("Button.background", PRIMARY_COLOR);
            UIManager.put("Button.foreground", Color.WHITE);
            UIManager.put("OptionPane.buttonFont", FONT_NORMAL);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        setTitle("FirstCar - Réservation de VTC");
        setSize(1200, 900);
        setMinimumSize(new Dimension(1000, 800));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        cardLayout = new CardLayout();
        mainPanel = new JPanel(cardLayout);
        mainPanel.setBackground(BACKGROUND_COLOR);

        mainPanel.add(createLoginPanel(), "Login");
        mainPanel.add(createRegisterPanel(), "Register");

        add(mainPanel);
        showPanel("Login");
    }

    private JButton createStyledButton(String text, boolean primary) {
        JButton btn = new JButton(text);
        btn.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        btn.setFocusPainted(false);
        btn.setBorderPainted(false);
        if (primary) {
            btn.setBackground(PRIMARY_COLOR);
            btn.setForeground(Color.WHITE);
        } else {
            btn.setBackground(CARD_BORDER_COLOR);
            btn.setForeground(TEXT_COLOR);
        }
        btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
        btn.setPreferredSize(new Dimension(200, 45));
        
        btn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                if (primary) btn.setBackground(ACCENT_COLOR);
                else btn.setBackground(CARD_BORDER_COLOR.brighter());
            }
            @Override
            public void mouseExited(MouseEvent e) {
                if (primary) btn.setBackground(PRIMARY_COLOR);
                else btn.setBackground(CARD_BORDER_COLOR);
            }
        });
        
        return btn;
    }

    private JTextField createStyledTextField(int cols) {
        JTextField field = new JTextField(cols);
        field.setFont(FONT_NORMAL);
        field.setBackground(CARD_COLOR);
        field.setForeground(TEXT_COLOR);
        field.setCaretColor(TEXT_COLOR);
        field.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(8, 12, 8, 12)
        ));
        return field;
    }

    private JPasswordField createStyledPasswordField(int cols) {
        JPasswordField field = new JPasswordField(cols);
        field.setFont(FONT_NORMAL);
        field.setBackground(CARD_COLOR);
        field.setForeground(TEXT_COLOR);
        field.setCaretColor(TEXT_COLOR);
        field.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(8, 12, 8, 12)
        ));
        return field;
    }

    private void styleStyledComboBox(JComboBox<?> combo) {
        combo.setFont(FONT_NORMAL);
        // Force a light background for the closed combo box to contrast with dark panel
        combo.setBackground(Color.WHITE); 
        combo.setForeground(Color.BLACK);
        
        // Custom UI to override system look and feel behaviors
        combo.setUI(new javax.swing.plaf.basic.BasicComboBoxUI() {
            @Override
            protected JButton createArrowButton() {
                JButton button = super.createArrowButton();
                button.setBackground(Color.WHITE);
                button.setBorder(BorderFactory.createEmptyBorder());
                return button;
            }
            @Override
            public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) {
                g.setColor(Color.WHITE);
                g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
            }
        });

        combo.setRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                // Force the dropdown list background to be readable
                list.setBackground(Color.WHITE);
                list.setForeground(Color.BLACK);
                list.setSelectionBackground(PRIMARY_COLOR);
                list.setSelectionForeground(Color.BLACK);

                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                
                setOpaque(true);
                if (isSelected) {
                    setBackground(PRIMARY_COLOR);
                    setForeground(Color.BLACK);
                } else {
                    setBackground(Color.WHITE);
                    setForeground(Color.BLACK);
                }
                setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));
                return this;
            }
        });
    }

    public final void showPanel(String name) {
        cardLayout.show(mainPanel, name);
    }

    private JPanel createLoginPanel() {
        JPanel wrapper = new JPanel(new GridBagLayout());
        wrapper.setBackground(BACKGROUND_COLOR);

        JPanel card = new JPanel(new GridBagLayout());
        card.setBackground(CARD_COLOR);
        card.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR, 1),
            BorderFactory.createEmptyBorder(40, 50, 40, 50)
        ));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(12, 12, 12, 12);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        JLabel title = new JLabel("FirstCar", JLabel.CENTER);
        title.setFont(FONT_TITLE);
        title.setForeground(PRIMARY_COLOR);
        gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
        card.add(title, gbc);

        JLabel subtitle = new JLabel("VTC Premium & Prestige", JLabel.CENTER);
        subtitle.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        subtitle.setForeground(TEXT_DIM_COLOR);
        gbc.gridy = 1;
        card.add(subtitle, gbc);

        gbc.gridwidth = 1;
        gbc.gridy = 2; 
        JLabel emailLabel = new JLabel("Email");
        emailLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        emailLabel.setForeground(TEXT_COLOR);
        card.add(emailLabel, gbc);
        JTextField emailField = createStyledTextField(20);
        gbc.gridx = 1; card.add(emailField, gbc);

        gbc.gridx = 0; gbc.gridy = 3; 
        JLabel passLabel = new JLabel("Mot de passe");
        passLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        passLabel.setForeground(TEXT_COLOR);
        card.add(passLabel, gbc);
        JPasswordField passField = createStyledPasswordField(20);
        gbc.gridx = 1; card.add(passField, gbc);

        JButton loginBtn = createStyledButton("Se connecter", true);
        gbc.gridx = 0; gbc.gridy = 4; gbc.gridwidth = 2;
        gbc.insets = new Insets(25, 12, 5, 12);
        card.add(loginBtn, gbc);

        JButton goToRegisterBtn = createStyledButton("Créer un compte", false);
        gbc.gridy = 5;
        gbc.insets = new Insets(5, 12, 12, 12);
        card.add(goToRegisterBtn, gbc);

        loginBtn.addActionListener(e -> {
            String email = emailField.getText();
            String password = new String(passField.getPassword());
            authenticate(email, password);
        });

        goToRegisterBtn.addActionListener(e -> showPanel("Register"));

        wrapper.add(card);
        
        JScrollPane scroll = new JScrollPane(wrapper);
        scroll.setBorder(null);
        scroll.setBackground(BACKGROUND_COLOR);
        scroll.getViewport().setBackground(BACKGROUND_COLOR);
        
        JPanel finalPanel = new JPanel(new BorderLayout());
        finalPanel.add(scroll, BorderLayout.CENTER);
        return finalPanel;
    }

    private JPanel createRegisterPanel() {
        JPanel wrapper = new JPanel(new GridBagLayout());
        wrapper.setBackground(BACKGROUND_COLOR);

        JPanel card = new JPanel(new GridBagLayout());
        card.setBackground(CARD_COLOR);
        card.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(30, 40, 30, 40)
        ));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(8, 8, 8, 8);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        JLabel title = new JLabel("Inscription", JLabel.CENTER);
        title.setFont(FONT_TITLE);
        title.setForeground(PRIMARY_COLOR);
        gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
        card.add(title, gbc);

        gbc.gridwidth = 1;
        gbc.gridy++; 
        JLabel nameLabel = new JLabel("Nom");
        nameLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        nameLabel.setForeground(TEXT_COLOR);
        card.add(nameLabel, gbc);
        JTextField nameField = createStyledTextField(20);
        gbc.gridx = 1; card.add(nameField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel emailRegLabel = new JLabel("Email");
        emailRegLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        emailRegLabel.setForeground(TEXT_COLOR);
        card.add(emailRegLabel, gbc);
        JTextField emailRegField = createStyledTextField(20);
        gbc.gridx = 1; card.add(emailRegField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel ageLabel = new JLabel("Âge");
        ageLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        ageLabel.setForeground(TEXT_COLOR);
        card.add(ageLabel, gbc);
        JTextField ageField = createStyledTextField(20);
        gbc.gridx = 1; card.add(ageField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel phoneLabel = new JLabel("Téléphone (Optionnel)");
        phoneLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        phoneLabel.setForeground(TEXT_COLOR);
        card.add(phoneLabel, gbc);
        JTextField phoneField = createStyledTextField(20);
        gbc.gridx = 1; card.add(phoneField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel passRegLabel = new JLabel("Mot de passe");
        passRegLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        passRegLabel.setForeground(TEXT_COLOR);
        card.add(passRegLabel, gbc);
        JPasswordField passField = createStyledPasswordField(20);
        gbc.gridx = 1; card.add(passField, gbc);

        JButton registerBtn = createStyledButton("S'inscrire", true);
        gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = 2;
        gbc.insets = new Insets(20, 8, 5, 8);
        card.add(registerBtn, gbc);

        JButton backBtn = createStyledButton("Retour", false);
        gbc.gridy++;
        card.add(backBtn, gbc);

        registerBtn.addActionListener(e -> {
            String name = nameField.getText().trim();
            String email = emailRegField.getText().trim();
            String ageStr = ageField.getText().trim();
            String phone = phoneField.getText().trim();
            String pass = new String(passField.getPassword()).trim();
            
            if (name.isEmpty() || email.isEmpty() || ageStr.isEmpty() || pass.isEmpty()) {
                showToast("Oups ! N'oubliez pas de remplir toutes les informations nécessaires.");
                return;
            }

            if (!email.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
                showToast("Cette adresse email semble incorrecte. Vérifiez qu'elle contient bien un '@'.");
                return;
            }

            try {
                int age = Integer.parseInt(ageStr);
                if (age < 18) {
                    showToast("Vous devez avoir au moins 18 ans pour voyager avec nous.");
                    return;
                }
                
                if(register(name, email, age, phone, pass)) {
                    showToast("Bienvenue chez FirstCar ! Votre compte est prêt.");
                    showPanel("Login");
                }
            } catch (NumberFormatException ex) {
                showToast("Votre âge doit être indiqué en chiffres.");
            } catch (SQLException ex) {
                if (ex.getMessage().contains("Duplicate entry")) {
                    showToast("Cette adresse email est déjà utilisée. Essayez de vous connecter !");
                } else {
                    showToast("Petit souci technique... Réessayez dans un instant !");
                    ex.printStackTrace();
                }
            } catch (Exception ex) {
                showToast("Une erreur inattendue est survenue. Nous faisons de notre mieux pour corriger ça !");
                ex.printStackTrace();
            }
        });

        backBtn.addActionListener(e -> showPanel("Login"));

        wrapper.add(card);
        
        JScrollPane scroll = new JScrollPane(wrapper);
        scroll.setBorder(null);
        scroll.setBackground(BACKGROUND_COLOR);
        scroll.getViewport().setBackground(BACKGROUND_COLOR);
        
        JPanel finalPanel = new JPanel(new BorderLayout());
        finalPanel.add(scroll, BorderLayout.CENTER);
        return finalPanel;
    }

    private void authenticate(String email, String password) {
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT * FROM users WHERE email = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, email);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                String hashed = rs.getString("password");
                // PHP bcrypt utilise $2y$, jbcrypt utilise $2a$. Ils sont généralement compatibles mais vérifions.
                String compatibleHashed = hashed.replaceFirst("^\\$2y\\$", "\\$2a\\$");
                if (BCrypt.checkpw(password, compatibleHashed)) {
                    User user = new User(
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getString("email"),
                        rs.getInt("age"),
                        rs.getString("phone"),
                        rs.getBoolean("is_admin")
                    );
                    Session.setCurrentUser(user);
                    onLoginSuccess();
                } else {
                    showToast("Le mot de passe ne semble pas être le bon. Réessayez !");
                }
            } else {
                showToast("Nous n'avons pas trouvé de compte avec cet email. Souhaitez-vous vous inscrire ?");
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
            showToast("Un souci technique nous empêche de vous connecter. Réessayez dans un instant !");
        }
    }

    private boolean register(String name, String email, int age, String phone, String password) throws SQLException {
        try (Connection conn = DBConnection.getConnection()) {
            String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));
            // Conversion en $2y$ pour la compatibilité PHP si nécessaire, bien que la DB le gère
            String sql = "INSERT INTO users (name, email, age, phone, password, is_admin) VALUES (?, ?, ?, ?, ?, 0)";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, name);
            pstmt.setString(2, email);
            pstmt.setInt(3, age);
            pstmt.setString(4, phone);
            pstmt.setString(5, hashed.replaceFirst("^\\$2a\\$", "\\$2y\\$"));
            return pstmt.executeUpdate() > 0;
        }
    }

    private void onLoginSuccess() {
        // Nettoyage de l'ancien tableau de bord pour éviter les bugs de navigation lors d'une reconnexion
        for (Component comp : mainPanel.getComponents()) {
            if (comp instanceof JPanel panel && "DashboardPanel".equals(panel.getName())) {
                mainPanel.remove(panel);
            }
        }
        
        lastSelectedMenuBtn = null; // Réinitialisation pour la nouvelle session
        JPanel dashboard = createDashboardLayout();
        mainPanel.add(dashboard, "Dashboard");
        showPanel("Dashboard");
    }

    private JPanel createDashboardLayout() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setName("DashboardPanel");
        panel.setBackground(BACKGROUND_COLOR);

        // Barre latérale (Sidebar)
        JPanel sidebar = new JPanel();
        sidebar.setLayout(new BoxLayout(sidebar, BoxLayout.Y_AXIS));
        sidebar.setPreferredSize(new Dimension(280, 0));
        sidebar.setBackground(CARD_COLOR);
        sidebar.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, CARD_BORDER_COLOR));

        JLabel logo = new JLabel("FirstCar", JLabel.CENTER);
        logo.setFont(FONT_TITLE.deriveFont(26f));
        logo.setForeground(PRIMARY_COLOR);
        logo.setAlignmentX(Component.CENTER_ALIGNMENT);
        logo.setBorder(BorderFactory.createEmptyBorder(30, 0, 40, 0));
        sidebar.add(logo);

        JButton homeBtn = createMenuButton("Tableau de bord");
        JButton bookBtn = createMenuButton("Réserver un trajet");
        JButton myResBtn = createMenuButton("Mes Réservations");
        JButton profileBtn = createMenuButton("Mon Profil");
        JButton logoutBtn = createMenuButton("Déconnexion");

        sidebar.add(homeBtn);
        sidebar.add(Box.createVerticalStrut(8));
        sidebar.add(bookBtn);
        sidebar.add(Box.createVerticalStrut(8));
        sidebar.add(myResBtn);
        sidebar.add(Box.createVerticalStrut(8));
        sidebar.add(profileBtn);
        sidebar.add(Box.createVerticalGlue());

        if (Session.getCurrentUser().isAdmin()) {
            JButton adminBtn = createMenuButton("Panel Admin");
            sidebar.add(adminBtn);
            sidebar.add(Box.createVerticalStrut(8));
            adminBtn.addActionListener(e -> setContent(createAdminDashboardPanel()));
        }

        sidebar.add(logoutBtn);
        sidebar.add(Box.createVerticalStrut(30));

        panel.add(sidebar, BorderLayout.WEST);

        // Zone de contenu principal
        contentArea = new JPanel(new BorderLayout());
        contentArea.setBackground(BACKGROUND_COLOR);
        contentArea.setBorder(BorderFactory.createEmptyBorder(30, 40, 30, 40));
        panel.add(contentArea, BorderLayout.CENTER);

        // Vue initiale
        contentArea.add(createDashboardWelcomePanel(), BorderLayout.CENTER);

        homeBtn.addActionListener(e -> setContent(createDashboardWelcomePanel()));
        bookBtn.addActionListener(e -> setContent(createBookingPanel()));
        myResBtn.addActionListener(e -> setContent(createMyReservationsPanel()));
        profileBtn.addActionListener(e -> setContent(createProfilePanel()));
        logoutBtn.addActionListener(e -> {
            Session.logout();
            showPanel("Login");
        });

        return panel;
    }

    private JPanel createProfilePanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBackground(BACKGROUND_COLOR);
        
        JPanel card = new JPanel(new GridBagLayout());
        card.setBackground(CARD_COLOR);
        card.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(30, 40, 30, 40)
        ));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(10, 10, 10, 10);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        User user = Session.getCurrentUser();

        JLabel title = new JLabel("Mon Profil");
        title.setFont(FONT_TITLE);
        title.setForeground(PRIMARY_COLOR);
        gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
        gbc.insets = new Insets(0, 10, 30, 10);
        card.add(title, gbc);

        gbc.insets = new Insets(10, 10, 10, 10);
        gbc.gridwidth = 1;
        gbc.gridy++; card.add(new JLabel("Nom"), gbc);
        JTextField nameField = createStyledTextField(20);
        nameField.setText(user.getName());
        gbc.gridx = 1; card.add(nameField, gbc);

        gbc.gridx = 0; gbc.gridy++; card.add(new JLabel("Email"), gbc);
        JTextField emailField = createStyledTextField(20);
        emailField.setText(user.getEmail());
        emailField.setEditable(false); // L'email n'est généralement pas modifiable pour plus de simplicité
        gbc.gridx = 1; card.add(emailField, gbc);

        gbc.gridx = 0; gbc.gridy++; card.add(new JLabel("Téléphone"), gbc);
        JTextField phoneField = createStyledTextField(20);
        phoneField.setText(user.getPhone() != null ? user.getPhone() : "");
        gbc.gridx = 1; card.add(phoneField, gbc);

        JButton saveBtn = createStyledButton("Enregistrer les modifications", true);
        gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = 2;
        gbc.insets = new Insets(30, 10, 0, 10);
        card.add(saveBtn, gbc);

        saveBtn.addActionListener(e -> {
            String newName = nameField.getText().trim();
            String newPhone = phoneField.getText().trim();
            
            if (newName.isEmpty() || newPhone.isEmpty()) {
                showToast("N'oubliez pas d'indiquer votre nom et votre téléphone !");
                return;
            }

            try (Connection conn = DBConnection.getConnection()) {
                String sql = "UPDATE users SET name = ?, phone = ? WHERE id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, newName);
                pstmt.setString(2, newPhone);
                pstmt.setInt(3, user.getId());
                
                if (pstmt.executeUpdate() > 0) {
                    // Mise à jour de l'utilisateur de session localement
                    user.setName(newName);
                    user.setPhone(newPhone);
                    showToast("Super ! Vos informations ont été mises à jour.");
                }
            } catch (SQLException ex) {
                showToast("Petit souci lors de l'enregistrement. Réessayez plus tard !");
                ex.printStackTrace();
            }
        });

        panel.add(card);
        return panel;
    }

    private ImageIcon getScaledImage(String imageName, int maxWidth, int maxHeight) {
        try {
            // Utilisation de chemins relatifs depuis la racine du projet ou le répertoire courant
            String[] possiblePaths = {
                "images/" + imageName,
                "../images/" + imageName,
                "FirstCarApp/images/" + imageName
            };

            File imageFile = null;
            for (String path : possiblePaths) {
                File f = new File(path);
                if (f.exists() && f.isFile()) {
                    imageFile = f;
                    break;
                }
            }

            if (imageFile == null) {
                // Dernier recours : recherche dans le classpath ou supposition du relatif au répertoire courant
                imageFile = new File("images/" + imageName);
            }

            if (!imageFile.exists()) return null;

            ImageIcon icon = new ImageIcon(imageFile.getAbsolutePath());
            if (icon.getIconWidth() <= 0) return null;
            
            double widthRatio = (double) maxWidth / icon.getIconWidth();
            double heightRatio = (double) maxHeight / icon.getIconHeight();
            double ratio = Math.min(widthRatio, heightRatio);
            
            int newWidth = (int) (icon.getIconWidth() * ratio);
            int newHeight = (int) (icon.getIconHeight() * ratio);
            
            Image img = icon.getImage().getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
            return new ImageIcon(img);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private void setContent(JPanel newContent) {
        if (contentArea != null) {
            contentArea.removeAll();
            contentArea.add(newContent, BorderLayout.CENTER);
            contentArea.revalidate();
            contentArea.repaint();
        }
    }

    private JButton lastSelectedMenuBtn = null;

    private JButton createMenuButton(String text) {
        JButton btn = new JButton(text);
        btn.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50));
        btn.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        btn.setForeground(TEXT_DIM_COLOR);
        btn.setBackground(CARD_COLOR);
        btn.setFocusPainted(false);
        btn.setBorderPainted(false);
        btn.setHorizontalAlignment(SwingConstants.LEFT);
        btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
        btn.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0));
        
        btn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) { 
                if (btn != lastSelectedMenuBtn) {
                    btn.setBackground(CARD_BORDER_COLOR); 
                    btn.setForeground(PRIMARY_COLOR);
                }
            }
            @Override
            public void mouseExited(MouseEvent e) { 
                if (btn != lastSelectedMenuBtn) {
                    btn.setBackground(CARD_COLOR); 
                    btn.setForeground(TEXT_DIM_COLOR);
                }
            }
        });

        btn.addActionListener(e -> {
            if (lastSelectedMenuBtn != null) {
                lastSelectedMenuBtn.setBackground(CARD_COLOR);
                lastSelectedMenuBtn.setForeground(TEXT_DIM_COLOR);
                lastSelectedMenuBtn.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0));
            }
            btn.setBackground(CARD_BORDER_COLOR);
            btn.setForeground(PRIMARY_COLOR);
            btn.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(0, 5, 0, 0, PRIMARY_COLOR),
                BorderFactory.createEmptyBorder(0, 25, 0, 0)
            ));
            lastSelectedMenuBtn = btn;
        });
        
        return btn;
    }

    private JPanel createDashboardWelcomePanel() {
        JPanel mainContent = new JPanel();
        mainContent.setLayout(new BoxLayout(mainContent, BoxLayout.Y_AXIS));
        mainContent.setBackground(BACKGROUND_COLOR);
        mainContent.setBorder(BorderFactory.createEmptyBorder(0, 0, 40, 0));

        // 1. HERO SECTION WITH BACKGROUND
        JPanel hero = new JPanel(new GridBagLayout()) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                ImageIcon bg = getScaledImage("accueil.png", getWidth(), getHeight());
                if (bg != null) {
                    g.drawImage(bg.getImage(), 0, 0, null);
                    // Add dark overlay
                    g.setColor(new Color(0, 0, 0, 150));
                    g.fillRect(0, 0, getWidth(), getHeight());
                }
            }
        };
        hero.setPreferredSize(new Dimension(0, 300));
        hero.setMaximumSize(new Dimension(Integer.MAX_VALUE, 300));
        
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.CENTER;
        
        JLabel welcome = new JLabel("Bienvenue, " + Session.getCurrentUser().getName());
        welcome.setFont(FONT_TITLE.deriveFont(42f));
        welcome.setForeground(Color.WHITE);
        hero.add(welcome, gbc);
        
        gbc.gridy = 1;
        gbc.insets = new Insets(10, 0, 0, 0);
        JLabel subtitle = new JLabel("First Car - Votre service de transport de prestige");
        subtitle.setFont(FONT_SUBTITLE.deriveFont(Font.PLAIN));
        subtitle.setForeground(PRIMARY_COLOR);
        hero.add(subtitle, gbc);
        
        mainContent.add(hero);
        mainContent.add(Box.createVerticalStrut(40));

        // 2. STATS BAR (Inspired by website)
        JPanel statsBar = new JPanel(new GridLayout(1, 4, 25, 0));
        statsBar.setBackground(BACKGROUND_COLOR);
        statsBar.setMaximumSize(new Dimension(Integer.MAX_VALUE, 120));
        statsBar.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20));
        
        statsBar.add(createStatItem("4", "Chauffeurs experts"));
        statsBar.add(createStatItem("4", "Véhicules premium"));
        statsBar.add(createStatItem("24h", "Disponibilité"));
        statsBar.add(createStatItem("100%", "Satisfaction"));
        
        mainContent.add(statsBar);
        mainContent.add(Box.createVerticalStrut(50));

        // Container for features and fleet to add margins
        JPanel innerContent = new JPanel();
        innerContent.setLayout(new BoxLayout(innerContent, BoxLayout.Y_AXIS));
        innerContent.setBackground(BACKGROUND_COLOR);
        innerContent.setBorder(BorderFactory.createEmptyBorder(0, 40, 0, 40));

        // 3. SECTION FONCTIONNALITÉS
        JLabel featTitle = new JLabel("Pourquoi choisir First Car ?");
        featTitle.setFont(FONT_SUBTITLE);
        featTitle.setForeground(TEXT_COLOR);
        featTitle.setAlignmentX(Component.LEFT_ALIGNMENT);
        innerContent.add(featTitle);
        innerContent.add(Box.createVerticalStrut(20));

        JPanel featureGrid = new JPanel(new GridLayout(2, 2, 25, 25));
        featureGrid.setBackground(BACKGROUND_COLOR);
        featureGrid.add(createFeatureCard("🎩", "Chauffeurs Pro", "Expérimentés, courtois et discrets."));
        featureGrid.add(createFeatureCard("🚗", "Flotte Premium", "Tesla, Mercedes, confort absolu."));
        featureGrid.add(createFeatureCard("⏱️", "Ponctualité", "Le respect de votre temps est notre priorité."));
        featureGrid.add(createFeatureCard("🔒", "Confidentialité", "Vos déplacements restent privés et sécurisés."));
        
        innerContent.add(featureGrid);
        
        // 4. SECTION MES STATISTIQUES
        innerContent.add(Box.createVerticalStrut(50));
        JLabel statsTitle = new JLabel("Mes Statistiques");
        statsTitle.setFont(FONT_SUBTITLE);
        statsTitle.setForeground(TEXT_COLOR);
        statsTitle.setAlignmentX(Component.LEFT_ALIGNMENT);
        innerContent.add(statsTitle);
        innerContent.add(Box.createVerticalStrut(20));

        JPanel userStatsGrid = new JPanel(new GridLayout(1, 2, 25, 0));
        userStatsGrid.setBackground(BACKGROUND_COLOR);
        userStatsGrid.setMaximumSize(new Dimension(Integer.MAX_VALUE, 120));
        
        JPanel totalTripsPanel = createStatItem("...", "Trajets effectués");
        JPanel upcomingPanel = createStatItem("...", "À venir");
        
        userStatsGrid.add(totalTripsPanel);
        userStatsGrid.add(upcomingPanel);
        innerContent.add(userStatsGrid);

        // Charger les stats utilisateur de manière asynchrone
        new SwingWorker<int[], Void>() {
            @Override
            protected int[] doInBackground() throws Exception {
                int total = 0, upcoming = 0;
                try (Connection conn = DBConnection.getConnection()) {
                    // Total terminés
                    String sql1 = "SELECT COUNT(*) FROM reservations WHERE user_id = ? AND status = 'terminée'";
                    PreparedStatement pstmt1 = conn.prepareStatement(sql1);
                    pstmt1.setInt(1, Session.getCurrentUser().getId());
                    ResultSet rs1 = pstmt1.executeQuery();
                    if (rs1.next()) total = rs1.getInt(1);

                    // À venir (confirmés)
                    String sql2 = "SELECT COUNT(*) FROM reservations WHERE user_id = ? AND status = 'confirmée'";
                    PreparedStatement pstmt2 = conn.prepareStatement(sql2);
                    pstmt2.setInt(1, Session.getCurrentUser().getId());
                    ResultSet rs2 = pstmt2.executeQuery();
                    if (rs2.next()) upcoming = rs2.getInt(1);
                }
                return new int[]{total, upcoming};
            }
            @Override
            protected void done() {
                try {
                    int[] results = get();
                    ((JLabel)totalTripsPanel.getComponent(0)).setText(String.valueOf(results[0]));
                    ((JLabel)upcomingPanel.getComponent(0)).setText(String.valueOf(results[1]));
                } catch (Exception ex) { ex.printStackTrace(); }
            }
        }.execute();

        mainContent.add(innerContent);
        
        mainContent.add(Box.createVerticalStrut(50));

        JScrollPane mainScroll = new JScrollPane(mainContent);
        mainScroll.setBorder(null);
        mainScroll.getVerticalScrollBar().setUnitIncrement(16);
        
        JPanel wrapper = new JPanel(new BorderLayout());
        wrapper.add(mainScroll, BorderLayout.CENTER);
        return wrapper;
    }

    private JPanel createStatItem(String number, String label) {
        JPanel p = new RoundedPanel(15, CARD_COLOR);
        p.setLayout(new GridBagLayout());
        p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        
        GridBagConstraints gbc = new GridBagConstraints();
        JLabel n = new JLabel(number);
        n.setFont(FONT_TITLE.deriveFont(24f));
        n.setForeground(PRIMARY_COLOR);
        gbc.gridy = 0; p.add(n, gbc);
        
        JLabel l = new JLabel(label);
        l.setFont(FONT_NORMAL.deriveFont(11f));
        l.setForeground(TEXT_DIM_COLOR);
        gbc.gridy = 1; p.add(l, gbc);
        
        return p;
    }

    private JPanel createFeatureCard(String icon, String title, String desc) {
        JPanel p = new RoundedPanel(20, CARD_COLOR);
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        
        JLabel i = new JLabel(icon);
        i.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 28));
        p.add(i);
        p.add(Box.createVerticalStrut(10));
        
        JLabel t = new JLabel(title);
        t.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        t.setForeground(TEXT_COLOR);
        p.add(t);
        p.add(Box.createVerticalStrut(8));
        
        JLabel d = new JLabel("<html><p style='width: 150px;'>" + desc + "</p></html>");
        d.setFont(FONT_NORMAL.deriveFont(12f));
        d.setForeground(TEXT_DIM_COLOR);
        p.add(d);
        
        return p;
    }

    // Classe utilitaire pour des panneaux arrondis avec ombre optionnelle
    private static class RoundedPanel extends JPanel {
        private int radius;
        private Color bgColor;
        private boolean shadow;

        public RoundedPanel(int radius, Color bgColor) {
            this(radius, bgColor, true);
        }

        public RoundedPanel(int radius, Color bgColor, boolean shadow) {
            this.radius = radius;
            this.bgColor = bgColor;
            this.shadow = shadow;
            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            if (shadow) {
                // Ombre portée
                g2.setColor(new Color(0, 0, 0, 100));
                g2.fillRoundRect(3, 3, getWidth() - 3, getHeight() - 3, radius, radius);
            }
            
            g2.setColor(bgColor);
            g2.fillRoundRect(0, 0, getWidth() - (shadow ? 3 : 0), getHeight() - (shadow ? 3 : 0), radius, radius);
            g2.dispose();
        }
    }

    private void showToast(String message) {
        JWindow window = new JWindow(this);
        JPanel p = new RoundedPanel(20, PRIMARY_COLOR, true);
        p.setLayout(new BorderLayout());
        JLabel l = new JLabel(message, JLabel.CENTER);
        l.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        l.setForeground(Color.WHITE);
        l.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
        p.add(l);
        window.add(p);
        window.pack();
        
        // Positionnement en bas au centre
        int x = getX() + (getWidth() - window.getWidth()) / 2;
        int y = getY() + getHeight() - window.getHeight() - 100;
        window.setLocation(x, y);
        window.setVisible(true);
        
        new Timer(3000, e -> {
            window.dispose();
            ((Timer)e.getSource()).stop();
        }).start();
    }

    private JPanel createBookingPanel() {
        // Déclaration préalable pour qu'ils soient accessibles dans les expressions lambda
        JDateChooser dateChooser = new JDateChooser();
        JTextField timeField = createStyledTextField(20);
        JComboBox<Chauffeur> chauffeurCombo = new JComboBox<>();
        JLabel totalPriceLabel = new JLabel("0.00 €", JLabel.LEFT);
        JTextField distField = createStyledTextField(20);
        JComboBox<Car> carCombo = new JComboBox<>(getCars().toArray(new Car[0]));

        JPanel mainContent = new JPanel(new GridBagLayout());
        mainContent.setBackground(BACKGROUND_COLOR);
        GridBagConstraints mainGbc = new GridBagConstraints();
        mainGbc.anchor = GridBagConstraints.NORTH;
        mainGbc.fill = GridBagConstraints.NONE;
        mainGbc.insets = new Insets(0, 0, 0, 0);

        // Formulaire (Côté gauche)
        JPanel leftPanel = new JPanel(new GridBagLayout());
        leftPanel.setBackground(BACKGROUND_COLOR);
        
        JPanel card = new JPanel(new GridBagLayout());
        card.setBackground(CARD_COLOR);
        card.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(30, 40, 30, 40)
        ));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(15, 10, 15, 10);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        JLabel title = new JLabel("Nouvelle Réservation");
        title.setFont(FONT_TITLE.deriveFont(28f));
        title.setForeground(PRIMARY_COLOR);
        gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
        gbc.insets = new Insets(0, 10, 30, 10);
        card.add(title, gbc);

        gbc.insets = new Insets(15, 10, 15, 10);
        gbc.gridwidth = 1;
        gbc.gridy++; 
        JLabel carLabel = new JLabel("Véhicule");
        carLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        carLabel.setForeground(TEXT_COLOR);
        card.add(carLabel, gbc);
        styleStyledComboBox(carCombo);
        gbc.gridx = 1; card.add(carCombo, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel chauffeurLabel = new JLabel("Chauffeur");
        chauffeurLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        chauffeurLabel.setForeground(TEXT_COLOR);
        card.add(chauffeurLabel, gbc);
        styleStyledComboBox(chauffeurCombo);
        gbc.gridx = 1; card.add(chauffeurCombo, gbc);

        Runnable updateAvailableChauffeurs = () -> {
            Date d = dateChooser.getDate();
            String t = timeField.getText().trim();
            if (d != null && t.matches("^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$")) {
                new SwingWorker<List<Chauffeur>, Void>() {
                    @Override
                    protected List<Chauffeur> doInBackground() throws Exception {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        return getAvailableChauffeurs(sdf.format(d), t.length() == 5 ? t + ":00" : t);
                    }
                    @Override
                    protected void done() {
                        try {
                            List<Chauffeur> available = get();
                            chauffeurCombo.removeAllItems();
                            for (Chauffeur c : available) chauffeurCombo.addItem(c);
                            if (available.isEmpty()) {
                                chauffeurCombo.setToolTipText("Aucun chauffeur disponible à ce créneau.");
                            } else {
                                chauffeurCombo.setToolTipText(null);
                            }
                        } catch (Exception ex) { ex.printStackTrace(); }
                    }
                }.execute();
            }
        };

        gbc.gridx = 0; gbc.gridy++; 
        JLabel pickupLabel = new JLabel("Adresse de départ");
        pickupLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        pickupLabel.setForeground(TEXT_COLOR);
        card.add(pickupLabel, gbc);
        JTextField pickupField = createStyledTextField(20);
        gbc.gridx = 1; card.add(pickupField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel dropoffLabel = new JLabel("Adresse d'arrivée");
        dropoffLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        dropoffLabel.setForeground(TEXT_COLOR);
        card.add(dropoffLabel, gbc);
        JTextField dropoffField = createStyledTextField(20);
        gbc.gridx = 1; card.add(dropoffField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel dateLabel = new JLabel("Date");
        dateLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        dateLabel.setForeground(TEXT_COLOR);
        card.add(dateLabel, gbc);
        dateChooser.setDateFormatString("dd-MM-yyyy");
        dateChooser.setMinSelectableDate(new Date()); 
        dateChooser.getDateEditor().addPropertyChangeListener("date", evt -> updateAvailableChauffeurs.run());
        
        // Style du champ de saisie de JDateChooser
        JTextField dateEditor = ((JTextField) dateChooser.getDateEditor().getUiComponent());
        dateEditor.setBackground(Color.WHITE);
        dateEditor.setForeground(Color.BLACK);
        dateEditor.setDisabledTextColor(Color.BLACK);
        dateEditor.setEditable(false);
        dateEditor.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        dateEditor.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(5, 5, 5, 5)
        ));
        
        // Style du bouton
        for (Component subComp : dateChooser.getComponents()) {
            if (subComp instanceof JButton btn) {
                btn.setBackground(PRIMARY_COLOR);
                btn.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            }
        }
        
        // CORRECTIF CRITIQUE : visibilité et couleurs de JCalendar (Force le thème clair pour une lisibilité parfaite)
        com.toedter.calendar.JCalendar jcal = dateChooser.getJCalendar();
        jcal.setPreferredSize(new Dimension(350, 300));
        jcal.setBackground(Color.WHITE);
        jcal.setForeground(Color.BLACK);
        jcal.setBorder(BorderFactory.createLineBorder(PRIMARY_COLOR, 2));

        jcal.getDayChooser().setBackground(Color.WHITE);
        jcal.getDayChooser().setForeground(Color.BLACK);
        jcal.getDayChooser().setDecorationBackgroundVisible(true);
        jcal.getDayChooser().setDayBordersVisible(true);
        jcal.getDayChooser().setWeekdayForeground(Color.DARK_GRAY);
        jcal.getDayChooser().setSundayForeground(Color.RED);
        
        // Amélioration de la visibilité et de la taille du sélecteur Mois/Année
        jcal.getMonthChooser().setFont(FONT_NORMAL.deriveFont(Font.BOLD, 16f));
        jcal.getMonthChooser().setBackground(Color.WHITE);
        jcal.getYearChooser().setFont(FONT_NORMAL.deriveFont(Font.BOLD, 16f));
        jcal.getYearChooser().setBackground(Color.WHITE);
        
        // Force la visibilité de tous les sous-libellés et boutons du sélecteur de jour
        for(Component c : jcal.getDayChooser().getDayPanel().getComponents()) {
            c.setBackground(Color.WHITE);
            c.setForeground(Color.BLACK);
            if(c instanceof JLabel label) {
                label.setForeground(Color.BLACK);
                label.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
            }
            if(c instanceof JButton btn) {
                btn.setForeground(Color.BLACK);
                btn.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
            }
        }

        jcal.getMonthChooser().getComboBox().setForeground(Color.BLACK);
        jcal.getMonthChooser().getComboBox().setBackground(Color.WHITE);
        jcal.getMonthChooser().getComboBox().setFont(FONT_NORMAL.deriveFont(Font.BOLD, 18f)); // Mois plus grand
        
        jcal.getYearChooser().getComponent(0).setForeground(Color.BLACK);
        jcal.getYearChooser().getComponent(0).setBackground(Color.WHITE);
        jcal.getYearChooser().getComponent(0).setFont(FONT_NORMAL.deriveFont(Font.BOLD, 18f)); // Année plus grande
        
        // Augmentation de la hauteur de la barre de sélection mois/année
        jcal.getMonthChooser().setPreferredSize(new Dimension(jcal.getMonthChooser().getPreferredSize().width, 40));
        jcal.getYearChooser().setPreferredSize(new Dimension(jcal.getYearChooser().getPreferredSize().width, 40));
        
        gbc.gridx = 1; card.add(dateChooser, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel timeLabel = new JLabel("Heure (HH:mm)");
        timeLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        timeLabel.setForeground(TEXT_COLOR);
        card.add(timeLabel, gbc);
        timeField.setText("12:00");
        timeField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                updateAvailableChauffeurs.run();
            }
        });
        gbc.gridx = 1; card.add(timeField, gbc);

        // Mise à jour initiale
        dateChooser.setDate(new Date());
        updateAvailableChauffeurs.run();

        gbc.gridx = 0; gbc.gridy++; 
        JLabel distLabel = new JLabel("Distance (km)");
        distLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        distLabel.setForeground(TEXT_COLOR);
        card.add(distLabel, gbc);
        distField.setText("10");
        gbc.gridx = 1; card.add(distField, gbc);

        gbc.gridx = 0; gbc.gridy++; 
        JLabel priceLabelLabel = new JLabel("Prix Estimé");
        priceLabelLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        priceLabelLabel.setForeground(PRIMARY_COLOR);
        card.add(priceLabelLabel, gbc);
        totalPriceLabel.setFont(FONT_SUBTITLE);
        totalPriceLabel.setForeground(PRIMARY_COLOR);
        gbc.gridx = 1; card.add(totalPriceLabel, gbc);

        JButton confirmBtn = createStyledButton("Confirmer la réservation", true);
        gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = 2;
        gbc.insets = new Insets(25, 10, 0, 10);
        card.add(confirmBtn, gbc);

        leftPanel.add(card);
        mainGbc.gridx = 0; mainGbc.gridy = 0;
        mainContent.add(leftPanel, mainGbc);

        // Aperçu (Côté droit)
        JPanel previewPanel = new JPanel();
        previewPanel.setLayout(new BoxLayout(previewPanel, BoxLayout.Y_AXIS));
        previewPanel.setBackground(BACKGROUND_COLOR);
        previewPanel.setPreferredSize(new Dimension(320, 0));
        previewPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));

        JLabel carImageLabel = new JLabel();
        carImageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        carImageLabel.setPreferredSize(new Dimension(280, 180));
        carImageLabel.setMinimumSize(new Dimension(280, 180));
        carImageLabel.setMaximumSize(new Dimension(280, 180));
        carImageLabel.setHorizontalAlignment(JLabel.CENTER);
        carImageLabel.setForeground(TEXT_COLOR);
        
        JLabel carNameLabel = new JLabel("", JLabel.CENTER);
        carNameLabel.setFont(FONT_SUBTITLE);
        carNameLabel.setForeground(PRIMARY_COLOR);
        carNameLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        JLabel carDescLabel = new JLabel("", JLabel.CENTER);
        carDescLabel.setFont(FONT_NORMAL);
        carDescLabel.setForeground(TEXT_DIM_COLOR);
        carDescLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        JLabel carPriceLabel = new JLabel("", JLabel.CENTER);
        carPriceLabel.setFont(FONT_NORMAL.deriveFont(Font.BOLD));
        carPriceLabel.setForeground(TEXT_COLOR);
        carPriceLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

        previewPanel.add(Box.createVerticalGlue());
        previewPanel.add(carImageLabel);
        previewPanel.add(Box.createVerticalStrut(20));
        previewPanel.add(carNameLabel);
        previewPanel.add(Box.createVerticalStrut(10));
        previewPanel.add(carPriceLabel);
        previewPanel.add(Box.createVerticalStrut(10));
        previewPanel.add(carDescLabel);
        previewPanel.add(Box.createVerticalGlue());

        mainGbc.gridx = 1;
        mainContent.add(previewPanel, mainGbc);

        // Mise à jour de l'aperçu lorsque la sélection du véhicule change
        Runnable updatePrice = () -> {
            try {
                Car selectedCar = (Car) carCombo.getSelectedItem();
                String dStr = distField.getText().trim();
                if (selectedCar != null && !dStr.isEmpty()) {
                    double dist = Double.parseDouble(dStr);
                    double total = dist * selectedCar.getPriceKm();
                    totalPriceLabel.setText(String.format("%.2f €", total));
                }
            } catch (Exception ex) {}
        };

        ActionListener updatePreview = e -> {
            Car selectedCar = (Car) carCombo.getSelectedItem();
            if (selectedCar != null) {
                carNameLabel.setText(selectedCar.getName());
                carPriceLabel.setText(String.format("%.2f € / km", selectedCar.getPriceKm()));
                carDescLabel.setText("<html><center>" + selectedCar.getCategory() + "<br>" + selectedCar.getSeats() + " places</center></html>");
                updatePrice.run();
                
                // Chargement de l'image depuis le dossier images du site web
                try {
                    ImageIcon icon = getScaledImage(selectedCar.getImage(), 280, 180);
                    
                    if (icon != null) {
                        carImageLabel.setIcon(icon);
                        carImageLabel.setText("");
                    } else {
                        carImageLabel.setIcon(null);
                        carImageLabel.setText("Image: " + selectedCar.getImage());
                    }
                } catch (Exception ex) {
                    carImageLabel.setIcon(null);
                    carImageLabel.setText("Erreur chargement");
                }
            }
        };
        carCombo.addActionListener(updatePreview);
        distField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) { updatePrice.run(); }
        });
        updatePreview.actionPerformed(null); // Mise à jour initiale

        confirmBtn.addActionListener(e -> {
            try {
                Car car = (Car) carCombo.getSelectedItem();
                Chauffeur chauffeur = (Chauffeur) chauffeurCombo.getSelectedItem();
                String pickup = pickupField.getText().trim();
                String dropoff = dropoffField.getText().trim();
                Date dateObj = dateChooser.getDate();
                String timeStr = timeField.getText().trim();

                // GESTION D'ERREUR ROBUSTE
                if (car == null) throw new Exception("Veuillez sélectionner un véhicule.");
                if (chauffeur == null) throw new Exception("Veuillez sélectionner un chauffeur.");
                if (pickup.isEmpty()) throw new Exception("L'adresse de départ est obligatoire.");
                if (dropoff.isEmpty()) throw new Exception("L'adresse d'arrivée est obligatoire.");
                if (dateObj == null) throw new Exception("Veuillez choisir une date de réservation.");
                if (timeStr.isEmpty()) throw new Exception("L'heure de réservation est obligatoire.");

                // Vérification date passée (sécurité supplémentaire)
                Date today = new Date();
                SimpleDateFormat daySdf = new SimpleDateFormat("yyyy-MM-dd");
                if (daySdf.format(dateObj).compareTo(daySdf.format(today)) < 0) {
                    throw new Exception("Vous ne pouvez pas réserver pour une date passée.");
                }

                if (!timeStr.matches("^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$")) {
                    throw new Exception("L'heure doit être au format HH:mm (ex: 14:30)");
                }
                
                // Ajout des secondes si elles ne sont pas présentes
                if (timeStr.length() == 5) timeStr += ":00";

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String dateStr = sdf.format(dateObj);

                if (createReservation(car.getId(), chauffeur.getId(), pickup, dropoff, dateStr, timeStr)) {
                    showToast("Réservation confirmée avec succès !");
                    setContent(createDashboardWelcomePanel());
                }
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Erreur: " + ex.getMessage());
            }
        });

        JScrollPane scrollPane = new JScrollPane(mainContent);
        scrollPane.setBorder(null);
        scrollPane.getVerticalScrollBar().setUnitIncrement(16);
        scrollPane.getHorizontalScrollBar().setUnitIncrement(16);
        scrollPane.setBackground(BACKGROUND_COLOR);
        scrollPane.getViewport().setBackground(BACKGROUND_COLOR);

        JPanel finalPanel = new JPanel(new BorderLayout());
        finalPanel.add(scrollPane, BorderLayout.CENTER);
        return finalPanel;
    }

    private JPanel createMyReservationsPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(BACKGROUND_COLOR);
        
        JLabel title = new JLabel("Mes Réservations");
        title.setFont(FONT_TITLE);
        title.setForeground(TEXT_COLOR);
        title.setBorder(BorderFactory.createEmptyBorder(0, 0, 30, 0));
        panel.add(title, BorderLayout.NORTH);

        String[] cols = {"ID", "Véhicule", "Chauffeur", "Date", "Heure", "Statut", "Avis"};
        DefaultTableModel model = new DefaultTableModel(cols, 0) {
            @Override
            public boolean isCellEditable(int row, int column) { return false; }
        };
        JTable table = new JTable(model);
        styleTable(table);
        
        SimpleDateFormat sdfDisplay = new SimpleDateFormat("dd-MM-yyyy");
        List<Reservation> resList = getMyReservations();
        for (Reservation r : resList) {
            String avisStatus = r.isHasReview() ? "✅ Déjà mis" : "❌ À faire";
            // On n'affiche l'avis "À faire" que si le trajet est terminé
            if (!"terminée".equals(r.getStatus())) {
                avisStatus = "-";
            }
            
            model.addRow(new Object[]{
                r.getId(), 
                r.getCarName(), 
                r.getChauffeurName(), 
                sdfDisplay.format(r.getReservationDate()), 
                r.getReservationTime(), 
                r.getStatus().toUpperCase(),
                avisStatus
            });
        }

        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBackground(CARD_COLOR);
        scrollPane.getViewport().setBackground(CARD_COLOR);
        scrollPane.setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
        panel.add(scrollPane, BorderLayout.CENTER);

        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        bottomPanel.setBackground(BACKGROUND_COLOR);
        bottomPanel.setBorder(BorderFactory.createEmptyBorder(25, 0, 0, 0));

        JButton cancelBtn = createStyledButton("Annuler la Réservation", false);
        cancelBtn.setBackground(new Color(180, 40, 40)); // Clear red for "Cancel" action
        cancelBtn.setForeground(Color.WHITE);
        cancelBtn.setPreferredSize(new Dimension(180, 40));
        
        JButton rateBtn = createStyledButton("Noter le Trajet", true);
        rateBtn.setPreferredSize(new Dimension(180, 40));
        
        bottomPanel.add(cancelBtn);
        bottomPanel.add(Box.createRigidArea(new Dimension(15, 0)));
        bottomPanel.add(rateBtn);
        panel.add(bottomPanel, BorderLayout.SOUTH);

        cancelBtn.addActionListener(e -> {
            int row = table.getSelectedRow();
            if (row != -1) {
                int id = (int) model.getValueAt(row, 0);
                String status = (String) model.getValueAt(row, 5);
                
                if ("TERMINÉE".equals(status) || "ANNULÉE".equals(status)) {
                    showToast("Désolé, impossible d'annuler une réservation terminée ou déjà annulée.");
                    return;
                }
                
                int confirm = JOptionPane.showConfirmDialog(this, "Voulez-vous vraiment annuler cette réservation ?", "Confirmation", JOptionPane.YES_NO_OPTION);
                if (confirm == JOptionPane.YES_OPTION) {
                    cancelReservation(id);
                    setContent(createMyReservationsPanel());
                }
            } else {
                showToast("Veuillez d'abord sélectionner une réservation dans la liste.");
            }
        });

        rateBtn.addActionListener(e -> {
            int row = table.getSelectedRow();
            if (row != -1) {
                int id = (int) model.getValueAt(row, 0);
                String status = (String) model.getValueAt(row, 5);
                if (!"TERMINÉE".equals(status)) {
                    showToast("Vous ne pouvez noter que les trajets terminés.");
                    return;
                }
                showRateDialog(id, () -> setContent(createMyReservationsPanel()));
            } else {
                showToast("Veuillez d'abord sélectionner une réservation dans la liste.");
            }
        });

        return panel;
    }

    private void styleTable(JTable table) {
        table.setFont(FONT_NORMAL);
        table.setRowHeight(55); // Plus d'espace pour respirer
        table.setBackground(CARD_COLOR);
        table.setForeground(TEXT_COLOR);
        table.setSelectionBackground(PRIMARY_COLOR);
        table.setSelectionForeground(Color.BLACK); // Contraste élevé lors de la sélection
        table.setGridColor(CARD_BORDER_COLOR);
        table.setShowVerticalLines(false);
        table.setIntercellSpacing(new Dimension(0, 1));
        
        table.getTableHeader().setFont(FONT_NORMAL.deriveFont(Font.BOLD, 13f));
        table.getTableHeader().setBackground(BACKGROUND_COLOR);
        table.getTableHeader().setForeground(PRIMARY_COLOR); // En-têtes Or/Orange
        table.getTableHeader().setPreferredSize(new Dimension(0, 50));
        table.getTableHeader().setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, PRIMARY_COLOR));

        // Rendu personnalisé pour colorer le statut et l'avis
        table.setDefaultRenderer(Object.class, new javax.swing.table.DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (isSelected) {
                    c.setBackground(PRIMARY_COLOR);
                    c.setForeground(Color.BLACK);
                } else {
                    c.setBackground(CARD_COLOR);
                    c.setForeground(TEXT_COLOR);
                }
                
                String colName = table.getColumnName(column);
                if ("Statut".equals(colName) && value != null) {
                    String status = value.toString();
                    if (status.equals("CONFIRMÉE")) {
                        setForeground(new Color(100, 200, 100)); // Vert
                    } else if (status.equals("ANNULÉE")) {
                        setForeground(new Color(200, 100, 100)); // Rouge
                    } else if (status.equals("TERMINÉE")) {
                        setForeground(new Color(100, 150, 255)); // Bleu
                    }
                }
                
                if ("Avis".equals(colName) && value != null) {
                    String avis = value.toString();
                    if (avis.contains("Déjà mis")) {
                        setForeground(new Color(100, 200, 100)); // Vert
                    } else if (avis.contains("À faire")) {
                        setForeground(PRIMARY_COLOR); // Orange
                    }
                }

                setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
                return c;
            }
        });
    }

    private JPanel createAdminDashboardPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(BACKGROUND_COLOR);

        JLabel title = new JLabel("Administration");
        title.setFont(FONT_TITLE);
        title.setForeground(TEXT_COLOR);
        title.setBorder(BorderFactory.createEmptyBorder(0, 0, 30, 0));
        panel.add(title, BorderLayout.NORTH);

        JTabbedPane tabs = new JTabbedPane();
        tabs.setFont(FONT_NORMAL.deriveFont(Font.BOLD, 14f));
        // Force les couleurs pour contrer le comportement natif de Windows si nécessaire
        tabs.setForeground(new Color(40, 40, 40)); 
        tabs.setBackground(Color.WHITE);
        
        // Tab for Reservations
        JPanel resPanel = new JPanel(new BorderLayout());
        resPanel.setBackground(BACKGROUND_COLOR);
        resPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
        
        String[] resCols = {"ID", "Utilisateur", "Véhicule", "Date", "Statut"};
        DefaultTableModel resModel = new DefaultTableModel(resCols, 0) {
            @Override
            public boolean isCellEditable(int row, int column) { return false; }
        };
        JTable resTable = new JTable(resModel);
        styleTable(resTable);
        
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT r.*, u.name as user_name, c.name as car_name FROM reservations r " +
                         "JOIN users u ON r.user_id = u.id " +
                         "JOIN cars c ON r.car_id = c.id ORDER BY r.reservation_date DESC";
            ResultSet rs = conn.createStatement().executeQuery(sql);
            SimpleDateFormat sdfAdmin = new SimpleDateFormat("dd-MM-yyyy");
            while (rs.next()) {
                resModel.addRow(new Object[]{rs.getInt("id"), rs.getString("user_name"), rs.getString("car_name"), sdfAdmin.format(rs.getDate("reservation_date")), rs.getString("status").toUpperCase()});
            }
        } catch (Exception e) { e.printStackTrace(); }

        JScrollPane resScroll = new JScrollPane(resTable);
        resScroll.setBackground(CARD_COLOR);
        resScroll.getViewport().setBackground(CARD_COLOR);
        resScroll.setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
        resPanel.add(resScroll, BorderLayout.CENTER);
        tabs.addTab("  RÉSERVATIONS  ", resPanel);

        // Tab for Cars
        JPanel carPanel = new JPanel(new BorderLayout());
        carPanel.setBackground(BACKGROUND_COLOR);
        carPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
        
        String[] carCols = {"ID", "Nom", "Prix/km", "Actif"};
        DefaultTableModel carModel = new DefaultTableModel(carCols, 0) {
            @Override
            public boolean isCellEditable(int row, int column) { return false; }
        };
        JTable carTable = new JTable(carModel);
        styleTable(carTable);
        
        for (Car c : getCars()) {
            carModel.addRow(new Object[]{c.getId(), c.getName(), String.format("%.2f €", c.getPriceKm()), c.isActive() ? "OUI" : "NON"});
        }

        JScrollPane carScroll = new JScrollPane(carTable);
        carScroll.setBackground(CARD_COLOR);
        carScroll.getViewport().setBackground(CARD_COLOR);
        carScroll.setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
        carPanel.add(carScroll, BorderLayout.CENTER);
        tabs.addTab("  VÉHICULES  ", carPanel);

        // Tab for Users (Missing)
        JPanel userPanel = new JPanel(new BorderLayout());
        userPanel.setBackground(BACKGROUND_COLOR);
        userPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
        
        String[] userCols = {"ID", "Nom", "Email", "Rôle", "Admin"};
        DefaultTableModel userModel = new DefaultTableModel(userCols, 0) {
            @Override
            public boolean isCellEditable(int row, int column) { return false; }
        };
        JTable userTable = new JTable(userModel);
        styleTable(userTable);
        
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT * FROM users ORDER BY name ASC";
            ResultSet rs = conn.createStatement().executeQuery(sql);
            while (rs.next()) {
                userModel.addRow(new Object[]{
                    rs.getInt("id"), 
                    rs.getString("name"), 
                    rs.getString("email"), 
                    rs.getString("role"),
                    rs.getBoolean("is_admin") ? "OUI" : "NON"
                });
            }
        } catch (Exception e) { e.printStackTrace(); }

        JScrollPane userScroll = new JScrollPane(userTable);
        userScroll.setBackground(CARD_COLOR);
        userScroll.getViewport().setBackground(CARD_COLOR);
        userScroll.setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
        userPanel.add(userScroll, BorderLayout.CENTER);
        tabs.addTab("  UTILISATEURS  ", userPanel);

        // Tab for Ratings
        JPanel ratePanel = new JPanel(new BorderLayout());
        ratePanel.setBackground(BACKGROUND_COLOR);
        ratePanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
        
        String[] rateCols = {"ID", "Utilisateur", "Note", "Commentaire"};
        DefaultTableModel rateModel = new DefaultTableModel(rateCols, 0) {
            @Override
            public boolean isCellEditable(int row, int column) { return false; }
        };
        JTable rateTable = new JTable(rateModel);
        styleTable(rateTable);
        
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT r.*, u.name FROM ratings r JOIN users u ON r.user_id = u.id ORDER BY r.id DESC";
            ResultSet rs = conn.createStatement().executeQuery(sql);
            while (rs.next()) {
                String stars = "";
                for(int i=0; i<rs.getInt("stars"); i++) stars += "★";
                rateModel.addRow(new Object[]{rs.getInt("id"), rs.getString("name"), stars, rs.getString("comment")});
            }
        } catch (Exception e) { e.printStackTrace(); }

        JScrollPane rateScroll = new JScrollPane(rateTable);
        rateScroll.setBackground(CARD_COLOR);
        rateScroll.getViewport().setBackground(CARD_COLOR);
        rateScroll.setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
        ratePanel.add(rateScroll, BorderLayout.CENTER);
        tabs.addTab("  AVIS CLIENTS  ", ratePanel);

        panel.add(tabs, BorderLayout.CENTER);
        return panel;
    }

    // Méthodes d'aide pour la base de données
    private List<Car> getCars() {
        List<Car> list = new ArrayList<>();
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT * FROM cars WHERE active = 1";
            ResultSet rs = conn.createStatement().executeQuery(sql);
            while (rs.next()) {
                list.add(new Car(rs.getInt("id"), rs.getString("name"), rs.getString("image"), rs.getString("description"), rs.getString("category"), rs.getInt("seats"), rs.getDouble("price_km"), rs.getBoolean("active")));
            }
        } catch (Exception e) { e.printStackTrace(); }
        return list;
    }

    private List<Chauffeur> getAvailableChauffeurs(String date, String time) {
        List<Chauffeur> list = new ArrayList<>();
        try (Connection conn = DBConnection.getConnection()) {
            // 1. Obtenir le jour de la semaine (1=Lundi, ..., 7=Dimanche comme le date('N') de PHP)
            java.util.Calendar cal = java.util.Calendar.getInstance();
            cal.setTime(java.sql.Date.valueOf(date));
            int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
            // Conversion Calendar.DAY_OF_WEEK (1=Dim, 2=Lun...) vers ISO-8601 (1=Lun, 7=Dim)
            int isoDay = (dayOfWeek == java.util.Calendar.SUNDAY) ? 7 : dayOfWeek - 1;

            String sql = "SELECT c.* FROM chauffeurs c " +
                         "INNER JOIN chauffeur_availability ca ON c.id = ca.chauffeur_id " +
                         "WHERE c.active = 1 " +
                         "AND ca.day_of_week = ? " +
                         "AND ca.start_time <= ? " +
                         "AND ca.end_time >= ? " +
                         "AND c.id NOT IN (" +
                         "  SELECT chauffeur_id FROM reservations " +
                         "  WHERE reservation_date = ? AND reservation_time = ? AND status = 'confirmée'" +
                         ") " +
                         "GROUP BY c.id ORDER BY c.name";
            
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, isoDay);
            pstmt.setString(2, time);
            pstmt.setString(3, time);
            pstmt.setString(4, date);
            pstmt.setString(5, time);
            
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                list.add(new Chauffeur(rs.getInt("id"), rs.getString("name"), rs.getString("phone"), rs.getString("bio"), rs.getInt("experience_years"), rs.getString("languages"), rs.getString("vehicle_type"), rs.getString("photo"), rs.getBoolean("active"), rs.getInt("total_trips"), rs.getInt("punctuality_rate")));
            }
        } catch (Exception e) { e.printStackTrace(); }
        return list;
    }

    private List<Chauffeur> getChauffeurs() {
        List<Chauffeur> list = new ArrayList<>();
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "SELECT * FROM chauffeurs WHERE active = 1";
            ResultSet rs = conn.createStatement().executeQuery(sql);
            while (rs.next()) {
                list.add(new Chauffeur(rs.getInt("id"), rs.getString("name"), rs.getString("phone"), rs.getString("bio"), rs.getInt("experience_years"), rs.getString("languages"), rs.getString("vehicle_type"), rs.getString("photo"), rs.getBoolean("active"), rs.getInt("total_trips"), rs.getInt("punctuality_rate")));
            }
        } catch (Exception e) { e.printStackTrace(); }
        return list;
    }

    private boolean createReservation(int carId, int chauffeurId, String pickup, String dropoff, String date, String time) throws SQLException {
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "INSERT INTO reservations (user_id, car_id, chauffeur_id, pickup_address, dropoff_address, reservation_date, reservation_time, status) VALUES (?, ?, ?, ?, ?, ?, ?, 'confirmée')";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, Session.getCurrentUser().getId());
            pstmt.setInt(2, carId);
            pstmt.setInt(3, chauffeurId);
            pstmt.setString(4, pickup);
            pstmt.setString(5, dropoff);
            pstmt.setDate(6, java.sql.Date.valueOf(date));
            pstmt.setTime(7, java.sql.Time.valueOf(time));
            return pstmt.executeUpdate() > 0;
        }
    }

    private List<Reservation> getMyReservations() {
        List<Reservation> list = new ArrayList<>();
        try (Connection conn = DBConnection.getConnection()) {
            // Jointure avec la table ratings pour savoir si un avis a déjà été donné
            String sql = "SELECT r.*, c.name as car_name, ch.name as chauffeur_name, " +
                         "(SELECT COUNT(*) FROM ratings WHERE reservation_id = r.id) as has_rating " +
                         "FROM reservations r " +
                         "JOIN cars c ON r.car_id = c.id " +
                         "JOIN chauffeurs ch ON r.chauffeur_id = ch.id " +
                         "WHERE r.user_id = ? " +
                         "ORDER BY r.reservation_date DESC, r.reservation_time DESC";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, Session.getCurrentUser().getId());
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                Reservation res = new Reservation(rs.getInt("id"), rs.getInt("user_id"), rs.getInt("car_id"), rs.getInt("chauffeur_id"), rs.getString("pickup_address"), rs.getString("dropoff_address"), rs.getDate("reservation_date"), rs.getTime("reservation_time"), rs.getString("status"), rs.getTimestamp("created_at"));
                res.setCarName(rs.getString("car_name"));
                res.setChauffeurName(rs.getString("chauffeur_name"));
                res.setHasReview(rs.getInt("has_rating") > 0);
                list.add(res);
            }
        } catch (Exception e) { e.printStackTrace(); }
        return list;
    }

    private void cancelReservation(int id) {
        try (Connection conn = DBConnection.getConnection()) {
            String sql = "UPDATE reservations SET status = 'annulée' WHERE id = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);
            pstmt.executeUpdate();
            showToast("Réservation annulée. On espère vous revoir bientôt !");
        } catch (Exception e) { e.printStackTrace(); }
    }

    private void showRateDialog(int resId, Runnable onComplete) {
        // Vérification si déjà noté
        try (Connection conn = DBConnection.getConnection()) {
            String checkSql = "SELECT id FROM ratings WHERE reservation_id = ?";
            PreparedStatement checkPstmt = conn.prepareStatement(checkSql);
            checkPstmt.setInt(1, resId);
            if (checkPstmt.executeQuery().next()) {
                showToast("Vous avez déjà partagé votre avis sur ce trajet. Merci !");
                return;
            }
        } catch (Exception e) { e.printStackTrace(); }

        // Création de la boîte de dialogue de notation personnalisée
        JDialog dialog = new JDialog(this, "Votre avis nous intéresse", true);
        dialog.setLayout(new BorderLayout());
        dialog.getContentPane().setBackground(BACKGROUND_COLOR);

        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBackground(BACKGROUND_COLOR);
        panel.setBorder(BorderFactory.createEmptyBorder(30, 40, 30, 40));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(0, 0, 20, 0);

        JLabel title = new JLabel("Comment s'est passé votre trajet ?");
        title.setFont(FONT_SUBTITLE);
        title.setForeground(PRIMARY_COLOR);
        panel.add(title, gbc);

        // Panneau des étoiles
        JPanel starsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
        starsPanel.setBackground(BACKGROUND_COLOR);
        JLabel[] starLabels = new JLabel[5];
        final int[] selectedStars = {0};

        for (int i = 0; i < 5; i++) {
            final int starIndex = i + 1;
            starLabels[i] = new JLabel("☆");
            starLabels[i].setFont(new Font("Serif", Font.PLAIN, 48));
            starLabels[i].setForeground(PRIMARY_COLOR);
            starLabels[i].setCursor(new Cursor(Cursor.HAND_CURSOR));
            
            starLabels[i].addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    selectedStars[0] = starIndex;
                    for (int j = 0; j < 5; j++) {
                        starLabels[j].setText(j < starIndex ? "★" : "☆");
                    }
                }
            });
            starsPanel.add(starLabels[i]);
        }
        gbc.gridy++;
        panel.add(starsPanel, gbc);

        gbc.gridy++; gbc.fill = GridBagConstraints.HORIZONTAL;
        JLabel commentLabel = new JLabel("Un petit mot pour nous ? (Optionnel)");
        commentLabel.setFont(FONT_NORMAL);
        commentLabel.setForeground(TEXT_COLOR);
        panel.add(commentLabel, gbc);

        gbc.gridy++;
        JTextArea commentArea = new JTextArea(4, 20);
        commentArea.setFont(FONT_NORMAL);
        commentArea.setBackground(CARD_COLOR);
        commentArea.setForeground(TEXT_COLOR);
        commentArea.setCaretColor(TEXT_COLOR);
        commentArea.setLineWrap(true);
        commentArea.setWrapStyleWord(true);
        commentArea.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(CARD_BORDER_COLOR),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)
        ));
        panel.add(new JScrollPane(commentArea), gbc);

        gbc.gridy++; gbc.insets = new Insets(30, 0, 0, 0);
        JButton submitBtn = createStyledButton("Envoyer mon avis", true);
        submitBtn.addActionListener(e -> {
            if (selectedStars[0] == 0) {
                showToast("N'oubliez pas de choisir une note entre 1 et 5 !");
                return;
            }
            try (Connection conn = DBConnection.getConnection()) {
                String sql = "INSERT INTO ratings (reservation_id, user_id, stars, comment) VALUES (?, ?, ?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, resId);
                pstmt.setInt(2, Session.getCurrentUser().getId());
                pstmt.setInt(3, selectedStars[0]);
                pstmt.setString(4, commentArea.getText().trim());
                pstmt.executeUpdate();
                
                showToast("Merci beaucoup pour votre retour ! C'est précieux pour nous.");
                dialog.dispose();
                if (onComplete != null) onComplete.run();
            } catch (Exception ex) {
                ex.printStackTrace();
                showToast("Petit souci technique... Réessayez plus tard !");
            }
        });
        panel.add(submitBtn, gbc);

        dialog.add(panel);
        dialog.pack();
        dialog.setLocationRelativeTo(this);
        dialog.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new FirstCarApp().setVisible(true));
    }
}
