<?php
/**
 * WisatawanController - Mengelola semua fungsi untuk role Wisatawan
 * DIPERBAIKI - Reschedule hanya mengubah tanggal (destinasi dihapus)
 * DITAMBAHKAN - Method notifikasi lengkap
 * DITAMBAHKAN - Method claim pengembalian dana
 * DITAMBAHKAN - Method saldo wisatawan
 * DITAMBAHKAN - Method pembatalan pesanan
 * DITAMBAHKAN - Logika Bayar dengan Saldo
 * DIPERBAIKI - Logika transaksi aman dengan inTransaction()
 */
class WisatawanController {
    private $pdo;
    private $debugMode = true;
    
    public function __construct($pdo) {
        $this->pdo = $pdo;
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
    }
    
    /**
     * INDEX - Default action, redirect ke dashboard
     */
    public function index() {
        header("Location: ?page=wisatawan&action=dashboard");
        exit;
    }
    
    /**
     * Helper: Ambil data user dari database
     */
    private function getUserData($user_id) {
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$user_id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Helper: Ambil jumlah notifikasi belum dibaca
     */
    private function getUnreadCount($user_id) {
        try {
            $stmt = $this->pdo->prepare("SELECT COUNT(*) as total FROM notifications WHERE user_id = ? AND is_read = 0");
            $stmt->execute([$user_id]);
            return $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?? 0;
        } catch (Exception $e) {
            return 0;
        }
    }
    
    /**
     * Helper: GET SALDO - Ambil saldo wisatawan
     */
    public function getSaldo($user_id) {
        try {
            $stmt = $this->pdo->prepare("SELECT saldo FROM saldo_wisatawan WHERE user_id = ?");
            $stmt->execute([$user_id]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result ? (int) $result['saldo'] : 0;
        } catch (Exception $e) {
            return 0;
        }
    }
    
    /**
     * Helper: Cek ketersediaan kapal pada tanggal tertentu
     */
    private function cekKetersediaanKapal($kapal_id, $tanggal) {
        try {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) as total FROM pesanan 
                WHERE kapal_id = ? 
                  AND tanggal_berangkat = ? 
                  AND status_pesanan IN ('pending', 'confirmed', 'berjalan', 'dikonfirmasi')
            ");
            $stmt->execute([$kapal_id, $tanggal]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result['total'] == 0;
        } catch (Exception $e) {
            return true;
        }
    }
    
    /**
     * Helper: Ambil daftar kapal yang sudah dibooking pada tanggal tertentu
     */
    private function getBookedKapalIds($tanggal) {
        try {
            $stmt = $this->pdo->prepare("
                SELECT DISTINCT kapal_id FROM pesanan 
                WHERE tanggal_berangkat = ? 
                  AND status_pesanan IN ('pending', 'confirmed', 'berjalan', 'dikonfirmasi')
            ");
            $stmt->execute([$tanggal]);
            return $stmt->fetchAll(PDO::FETCH_COLUMN);
        } catch (Exception $e) {
            return [];
        }
    }
    
    /**
     * Helper: Auto-generate rute jika belum ada
     */
    private function autoGenerateRoutes($kapalId) {
        try {
            $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM kapal_rute WHERE kapal_id = ?");
            $stmt->execute([$kapalId]);
            $count = $stmt->fetchColumn();
            
            if ($count > 0) {
                return true;
            }
            
            $defaultRoutes = [
                ['asal' => 'Parapat', 'tujuan' => 'Tomok', 'harga' => 2500000],
                ['asal' => 'Parapat', 'tujuan' => 'Tuktuk Siadong', 'harga' => 2000000],
                ['asal' => 'Parapat', 'tujuan' => 'Situmurun', 'harga' => 3000000],
                ['asal' => 'Parapat', 'tujuan' => 'Balige', 'harga' => 3500000],
                ['asal' => 'Parapat', 'tujuan' => 'Pangururan', 'harga' => 4000000],
                ['asal' => 'Parapat', 'tujuan' => 'Ambarita', 'harga' => 2800000],
                ['asal' => 'Parapat', 'tujuan' => 'Simanindo', 'harga' => 3200000],
            ];
            
            $this->pdo->beginTransaction();
            
            foreach ($defaultRoutes as $route) {
                $stmt = $this->pdo->prepare("
                    INSERT INTO kapal_rute (kapal_id, asal, tujuan, harga_jual) 
                    VALUES (?, ?, ?, ?)
                ");
                $stmt->execute([
                    $kapalId, 
                    $route['asal'], 
                    $route['tujuan'], 
                    $route['harga']
                ]);
            }
            
            $this->pdo->commit();
            return true;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            return false;
        }
    }
    
    /**
     * Helper: Get column names from a table
     */
    private function getTableColumns($table) {
        try {
            $stmt = $this->pdo->query("SHOW COLUMNS FROM $table");
            return $stmt->fetchAll(PDO::FETCH_COLUMN);
        } catch (Exception $e) {
            return [];
        }
    }
    
    /**
     * Helper: Get ENUM values from a column with debug
     */
    private function getEnumValues($table, $column) {
        try {
            $stmt = $this->pdo->query("SHOW COLUMNS FROM $table WHERE Field = '$column'");
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($this->debugMode) {
                error_log("DEBUG - Column: $column, Type: " . ($row['Type'] ?? 'NULL'));
            }
            
            if ($row && preg_match("/^enum\((.*)\)$/", $row['Type'], $matches)) {
                $enumValues = str_getcsv($matches[1], ',', "'");
                $result = array_map(function($v) { return trim($v, "'"); }, $enumValues);
                
                if ($this->debugMode) {
                    error_log("DEBUG - ENUM values for $column: " . implode(', ', $result));
                }
                
                return $result;
            }
            return [];
        } catch (Exception $e) {
            if ($this->debugMode) {
                error_log("DEBUG - Error getting ENUM: " . $e->getMessage());
            }
            return [];
        }
    }
    
    /**
     * Helper: Get valid status value
     */
    private function getValidStatus($table, $column, $defaultValue) {
        $enumValues = $this->getEnumValues($table, $column);
        
        if (!empty($enumValues)) {
            $statusMap = [
                'pending' => ['pending', 'menunggu', 'waiting', 'draft'],
                'confirmed' => ['confirmed', 'dikonfirmasi', 'approved', 'setuju'],
                'cancelled' => ['cancelled', 'dibatalkan', 'canceled', 'batal'],
                'completed' => ['completed', 'selesai', 'done', 'selesai'],
                'rejected' => ['rejected', 'ditolak', 'failed', 'gagal'],
                'berjalan' => ['berjalan', 'ongoing', 'progress'],
            ];
            
            foreach ($statusMap as $key => $variations) {
                if (in_array($defaultValue, $variations)) {
                    foreach ($variations as $var) {
                        if (in_array($var, $enumValues)) {
                            if ($this->debugMode) {
                                error_log("DEBUG - Found matching status: $var for $defaultValue");
                            }
                            return $var;
                        }
                    }
                }
            }
            
            $firstValue = $enumValues[0];
            if ($this->debugMode) {
                error_log("DEBUG - Using first ENUM value: $firstValue for $defaultValue");
                error_log("DEBUG - Available ENUM values: " . implode(', ', $enumValues));
            }
            return $firstValue;
        }
        
        return $defaultValue;
    }
    
    /**
     * Helper: Get valid payment status
     */
    private function getValidPaymentStatus($table, $column, $defaultValue) {
        $enumValues = $this->getEnumValues($table, $column);
        
        if (!empty($enumValues)) {
            $paymentMap = [
                'belum_bayar' => ['belum_bayar', 'unpaid', 'pending'],
                'menunggu_konfirmasi' => ['menunggu_konfirmasi', 'waiting_confirmation', 'menunggu'],
                'dikonfirmasi' => ['dikonfirmasi', 'confirmed', 'paid', 'lunas', 'verified'],
                'gagal' => ['gagal', 'failed', 'cancelled'],
            ];
            
            foreach ($paymentMap as $key => $variations) {
                if (in_array($defaultValue, $variations)) {
                    foreach ($variations as $var) {
                        if (in_array($var, $enumValues)) {
                            if ($this->debugMode) {
                                error_log("DEBUG - Found matching payment status: $var for $defaultValue");
                            }
                            return $var;
                        }
                    }
                }
            }
            
            $firstValue = $enumValues[0];
            if ($this->debugMode) {
                error_log("DEBUG - Using first ENUM value for payment: $firstValue for $defaultValue");
                error_log("DEBUG - Available payment ENUM values: " . implode(', ', $enumValues));
            }
            return $firstValue;
        }
        
        return $defaultValue;
    }
    
    /**
     * Helper: Load view dengan $activeMenu
     */
    private function loadView($viewName, $data = []) {
        // Mapping viewName ke activeMenu yang benar
        $menuMapping = [
            'dashboard' => 'dashboard',
            'booking' => 'booking',
            'riwayat_pesanan' => 'riwayatPesanan',
            'riwayat' => 'riwayatPesanan',
            'status_pesanan' => 'riwayatPesanan',
            'status' => 'riwayatPesanan',
            'profil' => 'profil',
            'profile' => 'profil',
            'notifikasi' => 'notifikasi',
            'notifications' => 'notifikasi',
            'upload_pembayaran' => 'riwayatPesanan',
            'batal_pesanan' => 'riwayatPesanan',
            'reschedule' => 'riwayatPesanan',
            'pembayaran' => 'riwayatPesanan',
            'pembayaran_sukses' => 'riwayatPesanan',
            'pembayaran_pending' => 'riwayatPesanan',
            'detail_pesanan' => 'riwayatPesanan',
            'saldo' => 'saldo',
            'form_batal_pesanan' => 'riwayatPesanan',
            'ajukan_claim' => 'riwayatPesanan',
        ];
        
        $activeMenu = $menuMapping[$viewName] ?? $viewName;
        
        // 🔥 AMBIL SALDO UNTUK DITAMPILKAN DI SIDEBAR
        $saldo = 0;
        $user_id = $_SESSION['user_id'] ?? 0;
        if ($user_id > 0) {
            $saldo = $this->getSaldo($user_id);
        }
        
        $defaultData = [
            'user_id' => $_SESSION['user_id'] ?? 0,
            'user' => null,
            'unreadCount' => 0,
            'activeMenu' => $activeMenu,
            'pageTitle' => ucfirst(str_replace('_', ' ', $viewName)) . ' - Wisatawan',
            'saldo' => $saldo,
        ];
        
        $data = array_merge($defaultData, $data);
        extract($data);
        
        // Path absolut untuk view
        $viewPaths = [
            __DIR__ . '/../views/wisatawan/' . $viewName . '.php',
            __DIR__ . '/../views/wisatawan/' . str_replace('_', '', $viewName) . '.php',
            __DIR__ . '/../views/' . $viewName . '.php',
        ];
        
        foreach ($viewPaths as $path) {
            if (file_exists($path)) {
                require_once $path;
                return true;
            }
        }
        
        // Jika view tidak ditemukan, tampilkan fallback
        $this->renderFallbackView($viewName, $data);
        return false;
    }
    
    /**
     * Fallback View
     */
    private function renderFallbackView($viewName, $data = []) {
        extract($data);
        $activeMenu = $activeMenu ?? $viewName;
        $pageTitle = ucfirst(str_replace('_', ' ', $viewName)) . ' - Wisatawan';
        ?>
        <!DOCTYPE html>
        <html lang="id">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title><?= $pageTitle ?></title>
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
            <style>
                * { margin: 0; padding: 0; box-sizing: border-box; }
                body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f7fafc; }
                .dashboard-wrapper { display: flex; gap: 24px; max-width: 1200px; margin: 1.5rem auto 0; padding: 0 20px; width: 100%; flex: 1; align-items: flex-start; }
                .main-content { flex: 1; min-width: 0; background: #fff; border-radius: 14px; padding: 1.8rem; box-shadow: 0 4px 20px rgba(0,0,0,0.06); border: 1px solid #e2e8f0; }
                .content-header { margin-bottom: 1.5rem; }
                .content-header h2 { font-size: 1.4rem; font-weight: 700; color: #1a202c; }
                .content-header p { color: #718096; font-size: 0.95rem; }
                .alert { display: flex; align-items: center; gap: 10px; padding: 0.8rem 1.2rem; border-radius: 10px; margin-bottom: 1rem; border-left: 4px solid transparent; }
                .alert-success { background: #d1fae5; color: #065f46; border-left-color: #22c55e; }
                .alert-danger { background: #fee2e2; color: #991b1b; border-left-color: #ef4444; }
                .alert-close { margin-left: auto; background: none; border: none; font-size: 1rem; cursor: pointer; color: inherit; opacity: 0.6; padding: 0 4px; }
                .alert-close:hover { opacity: 1; }
                .empty-state { text-align: center; padding: 2.5rem 1.5rem; background: #f7fafc; border-radius: 12px; border: 1px solid #e2e8f0; }
                .empty-icon { font-size: 3.5rem; display: block; margin-bottom: 0.5rem; opacity: 0.5; }
                .btn { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.4rem 1rem; border: none; border-radius: 6px; font-weight: 600; font-size: 0.8rem; cursor: pointer; transition: all 0.3s ease; text-decoration: none; }
                .btn-primary { background: #2b6cb0; color: #fff; }
                .btn-primary:hover { background: #1a4a7a; color: #fff; }
                .btn-secondary { background: #e2e8f0; color: #4a5568; }
                .btn-secondary:hover { background: #cbd5e0; color: #1a202c; }
                .btn-sm { padding: 0.2rem 0.6rem; font-size: 0.7rem; }
                .badge { display: inline-flex; align-items: center; gap: 0.2rem; padding: 0.15rem 0.6rem; border-radius: 20px; font-size: 0.65rem; font-weight: 600; }
                .badge-danger { background: #fee2e2; color: #991b1b; }
                .badge-success { background: #d1fae5; color: #065f46; }
                .badge-warning { background: #fef3c7; color: #92400e; }
                @media (max-width: 768px) { .dashboard-wrapper { flex-direction: column; padding: 0 12px; } .main-content { padding: 1rem; } }
                @media (max-width: 480px) { .main-content { padding: 0.8rem; } }
            </style>
        </head>
        <body>
            <div class="dashboard-wrapper">
                <?php 
                $sidebarPath = __DIR__ . '/../views/layouts/sidebar_wisatawan.php';
                if (file_exists($sidebarPath)) {
                    include $sidebarPath;
                } else {
                    echo '<div style="padding:1rem; background:#fee2e2; border-radius:8px; color:#991b1b; border:1px solid #fecaca; max-width:300px;">
                            <strong>⚠️ Sidebar tidak ditemukan!</strong><br>
                            Path: ' . $sidebarPath . '<br>
                            Silakan buat file: <code>views/layouts/sidebar_wisatawan.php</code>
                          </div>';
                }
                ?>
                <main class="main-content">
                    <div class="content-header">
                        <h2><i class="fas fa-user-cog" style="color:#2b6cb0;"></i> <?= ucfirst(str_replace('_', ' ', $viewName)) ?></h2>
                        <p>Halaman <?= ucfirst(str_replace('_', ' ', $viewName)) ?> Anda.</p>
                    </div>

                    <?php if(isset($_SESSION['flash_success'])): ?>
                        <div class="alert alert-success">
                            <i class="fas fa-check-circle"></i>
                            <?= htmlspecialchars($_SESSION['flash_success']) ?>
                            <button class="alert-close" onclick="this.parentElement.remove()">&times;</button>
                            <?php unset($_SESSION['flash_success']); ?>
                        </div>
                    <?php endif; ?>

                    <?php if(isset($_SESSION['flash_error'])): ?>
                        <div class="alert alert-danger">
                            <i class="fas fa-exclamation-circle"></i>
                            <?= htmlspecialchars($_SESSION['flash_error']) ?>
                            <button class="alert-close" onclick="this.parentElement.remove()">&times;</button>
                            <?php unset($_SESSION['flash_error']); ?>
                        </div>
                    <?php endif; ?>

                    <div class="empty-state">
                        <div class="empty-icon">📄</div>
                        <h3>Halaman <?= ucfirst(str_replace('_', ' ', $viewName)) ?></h3>
                        <p>File view tidak ditemukan. Sistem menggunakan tampilan default.</p>
                        <p style="font-size:0.8rem; color:#a0aec0; margin-top:0.5rem;">
                            File yang dicari: <code>views/wisatawan/<?= $viewName ?>.php</code>
                        </p>
                        <div style="margin-top:1rem;">
                            <a href="?page=wisatawan&action=dashboard" class="btn btn-primary">
                                <i class="fas fa-arrow-left"></i> Kembali ke Dashboard
                            </a>
                        </div>
                    </div>
                </main>
            </div>
        </body>
        </html>
        <?php
    }
    
    /**
     * DASHBOARD
     */
    public function dashboard() {
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal 
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                WHERE p.user_id = ? 
                ORDER BY p.id DESC 
                LIMIT 5
            ");
            $stmt->execute([$user_id]);
            $pesananTerbaru = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesananTerbaru = [];
        }
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal 
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                WHERE p.user_id = ? 
                ORDER BY p.id DESC
            ");
            $stmt->execute([$user_id]);
            $pesanan = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesanan = [];
        }
        
        $totalPesanan = count($pesanan);
        $pesananSelesai = 0;
        $pesananMenunggu = 0;
        $pesananDibatalkan = 0;
        
        foreach ($pesanan as $p) {
            $status = $p['status_pesanan'] ?? '';
            if (in_array($status, ['completed', 'selesai', 'done'])) $pesananSelesai++;
            elseif (in_array($status, ['pending', 'menunggu', 'waiting', 'confirmed', 'dikonfirmasi', 'berjalan'])) $pesananMenunggu++;
            elseif (in_array($status, ['cancelled', 'dibatalkan', 'failed', 'gagal', 'rejected', 'ditolak'])) $pesananDibatalkan++;
        }
        
        try {
            $stmt = $this->pdo->query("
                SELECT DISTINCT pelabuhan_asal 
                FROM kapal 
                WHERE status_verifikasi = 'verified' 
                  AND status_aktif = 1 
                  AND pelabuhan_asal IS NOT NULL 
                  AND pelabuhan_asal != ''
                ORDER BY pelabuhan_asal ASC
            ");
            $pelabuhanAsal = $stmt->fetchAll(PDO::FETCH_COLUMN);
        } catch (Exception $e) {
            $pelabuhanAsal = ['Parapat', 'Tuktuk', 'Tomok', 'Balige'];
        }
        
        $this->loadView('dashboard', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'pesananTerbaru' => $pesananTerbaru,
            'pesanan' => $pesanan,
            'totalPesanan' => $totalPesanan,
            'pesananSelesai' => $pesananSelesai,
            'pesananMenunggu' => $pesananMenunggu,
            'pesananDibatalkan' => $pesananDibatalkan,
            'pelabuhanAsal' => $pelabuhanAsal,
            'activeMenu' => 'dashboard'
        ]);
    }
    
    /**
     * BOOKING
     */
    public function booking() {
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        $tomorrow = date('Y-m-d', strtotime('+1 day'));
        $tanggalFilter = isset($_GET['tanggal']) ? $_GET['tanggal'] : $tomorrow;
        $searchTerm = isset($_GET['search']) ? trim($_GET['search']) : '';
        $maxDate = date('Y-m-d', strtotime('+30 days'));
        
        // Auto-generate rute
        try {
            $stmt = $this->pdo->query("
                SELECT k.id 
                FROM kapal k 
                WHERE k.status_verifikasi = 'verified' 
                  AND k.status_aktif = 1
                  AND NOT EXISTS (
                      SELECT 1 FROM kapal_rute kr WHERE kr.kapal_id = k.id
                  )
            ");
            $kapalTanpaRute = $stmt->fetchAll(PDO::FETCH_COLUMN);
            
            foreach ($kapalTanpaRute as $kapalId) {
                $this->autoGenerateRoutes($kapalId);
            }
        } catch (Exception $e) {
            // Ignore error
        }
        
        // Ambil kapal
        $sql = "
            SELECT 
                k.id,
                k.nama_kapal,
                k.jenis,
                k.kapasitas,
                k.fasilitas,
                k.foto,
                k.pelabuhan_asal,
                k.pelabuhan_tujuan,
                k.deskripsi,
                k.status_verifikasi,
                u.nama as pemilik,
                u.no_hp as pemilik_hp,
                u.id as pemilik_id,
                (SELECT COUNT(*) FROM kapal_rute WHERE kapal_id = k.id) as total_rute,
                (SELECT MIN(harga_jual) FROM kapal_rute WHERE kapal_id = k.id) as harga_termurah,
                (SELECT GROUP_CONCAT(DISTINCT tujuan SEPARATOR ' | ') FROM kapal_rute WHERE kapal_id = k.id) as daftar_tujuan
            FROM kapal k 
            JOIN users u ON k.pemilik_id = u.id 
            WHERE k.status_verifikasi = 'verified' 
              AND k.status_aktif = 1
        ";
        
        if (!empty($searchTerm)) {
            $sql .= " AND (
                k.nama_kapal LIKE ? OR 
                k.pelabuhan_asal LIKE ? OR 
                k.jenis LIKE ? OR
                k.fasilitas LIKE ? OR
                k.deskripsi LIKE ? OR
                EXISTS (
                    SELECT 1 FROM kapal_rute kr 
                    WHERE kr.kapal_id = k.id 
                    AND (kr.tujuan LIKE ? OR kr.asal LIKE ?)
                )
            )";
        }
        
        $sql .= " GROUP BY k.id ORDER BY k.created_at DESC";
        
        $stmt = $this->pdo->prepare($sql);
        
        if (!empty($searchTerm)) {
            $searchPattern = '%' . $searchTerm . '%';
            $stmt->execute([
                $searchPattern, $searchPattern, $searchPattern, 
                $searchPattern, $searchPattern, $searchPattern, $searchPattern
            ]);
        } else {
            $stmt->execute();
        }
        
        $kapalList = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        // Ambil rute per kapal
        $rutePerKapal = [];
        foreach ($kapalList as $kapal) {
            try {
                $stmt = $this->pdo->prepare("
                    SELECT id, asal, tujuan, harga_jual 
                    FROM kapal_rute 
                    WHERE kapal_id = ? 
                    ORDER BY harga_jual ASC
                ");
                $stmt->execute([$kapal['id']]);
                $rutePerKapal[$kapal['id']] = $stmt->fetchAll(PDO::FETCH_ASSOC);
            } catch (Exception $e) {
                $rutePerKapal[$kapal['id']] = [];
            }
        }
        
        // Cek ketersediaan
        $bookedKapalIds = $this->getBookedKapalIds($tanggalFilter);
        $bookedMap = [];
        foreach ($bookedKapalIds as $id) {
            $bookedMap[$id] = true;
        }
        
        foreach ($kapalList as &$kapal) {
            $kapal['tersedia'] = !isset($bookedMap[$kapal['id']]);
            $kapal['tanggal_cek'] = $tanggalFilter;
        }
        
        // Shared trips
        $sharedTrips = [];
        try {
            $stmt = $this->pdo->prepare("
                SELECT st.*, k.nama_kapal, k.pelabuhan_asal, k.pelabuhan_tujuan,
                       (SELECT COUNT(*) FROM shared_trip_participants WHERE trip_id = st.id) as peserta
                FROM shared_trips st 
                JOIN kapal k ON st.kapal_id = k.id 
                WHERE st.tanggal_berangkat >= ? 
                  AND st.kuota > (SELECT COUNT(*) FROM shared_trip_participants WHERE trip_id = st.id)
                ORDER BY st.tanggal_berangkat ASC
                LIMIT 10
            ");
            $stmt->execute([date('Y-m-d')]);
            $sharedTrips = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $sharedTrips = [];
        }
        
        $totalCount = count($kapalList);
        
        $this->loadView('booking', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'kapalList' => $kapalList,
            'rutePerKapal' => $rutePerKapal,
            'sharedTrips' => $sharedTrips,
            'tanggalFilter' => $tanggalFilter,
            'searchTerm' => $searchTerm,
            'tomorrow' => $tomorrow,
            'maxDate' => $maxDate,
            'totalCount' => $totalCount,
            'activeMenu' => 'booking'
        ]);
    }
    
    /**
     * PROSES BOOKING - Wisatawan memesan kapal
     * DIPERBAIKI - Menyimpan SEMUA data termasuk jenis pembayaran dan waktu
     * DITAMBAHKAN - Logika Bayar dengan Saldo
     * DIPERBAIKI - Logika transaksi aman dengan inTransaction()
     */
    public function prosesBooking() {
        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            header("Location: ?page=wisatawan&action=booking");
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        // Ambil data POST
        $kapal_id = (int) ($_POST['kapal_id'] ?? 0);
        $route_id = (int) ($_POST['route_id'] ?? 0);
        $tanggal = $_POST['tanggal_berangkat'] ?? $_POST['tanggal'] ?? '';
        $durasi = (int) ($_POST['durasi'] ?? 1);
        $tipe = $_POST['tipe'] ?? 'private';
        
        $nama_lengkap = trim($_POST['nama_lengkap'] ?? '');
        $no_hp = trim($_POST['no_hp'] ?? '');
        $nik_ktp = trim($_POST['nik_ktp'] ?? '');
        $jumlah_tiket = (int) ($_POST['jumlah_penumpang'] ?? 1);
        $catatan = trim($_POST['catatan'] ?? '');
        $trip_id = (int) ($_POST['trip_id'] ?? 0);
        $email = trim($_POST['email'] ?? $user['email'] ?? '');
        $harga_total = (int) ($_POST['harga_total'] ?? 0);
        
        // ==============================================
        // 🔥 AMBIL DATA BARU: WAKTU & JENIS PEMBAYARAN
        // ==============================================
        $waktu_jemput = $_POST['waktu_jemput'] ?? '08:00';
        $waktu_selesai = $_POST['waktu_selesai'] ?? '17:00';
        $jenis_pembayaran = $_POST['jenis_pembayaran'] ?? 'full'; // full, dp, cash, saldo
        
        // ===== VALIDASI =====
        $errors = [];
        
        if ($kapal_id <= 0) $errors[] = "Kapal tidak dipilih.";
        if ($route_id <= 0) $errors[] = "Rute perjalanan wajib dipilih.";
        
        $tomorrow = date('Y-m-d', strtotime('+1 day'));
        if (empty($tanggal)) $errors[] = "Tanggal keberangkatan wajib dipilih.";
        elseif ($tanggal < $tomorrow) $errors[] = "Tanggal keberangkatan minimal besok (H+1).";
        
        if (empty($waktu_jemput)) $errors[] = "Waktu jemput wajib dipilih.";
        if (empty($waktu_selesai)) $errors[] = "Waktu selesai wajib dipilih.";
        
        if ($durasi < 1) $errors[] = "Durasi sewa minimal 1 hari.";
        if ($durasi > 30) $errors[] = "Durasi sewa maksimal 30 hari.";
        
        if (empty($nama_lengkap)) $errors[] = "Nama lengkap wajib diisi.";
        if (empty($no_hp)) $errors[] = "Nomor HP wajib diisi.";
        if (empty($email)) $errors[] = "Email wajib diisi.";
        if (empty($nik_ktp)) $errors[] = "NIK wajib diisi.";
        elseif (strlen($nik_ktp) < 16 || !ctype_digit($nik_ktp)) {
            $errors[] = "NIK harus 16 digit angka.";
        }
        
        if ($jumlah_tiket < 1) {
            $errors[] = "Jumlah penumpang minimal 1 orang.";
        } else {
            try {
                $stmt = $this->pdo->prepare("SELECT id, nama_kapal, kapasitas, pemilik_id FROM kapal WHERE id = ?");
                $stmt->execute([$kapal_id]);
                $kapal = $stmt->fetch(PDO::FETCH_ASSOC);
                
                if (!$kapal) {
                    $errors[] = "Kapal tidak ditemukan.";
                } else {
                    $kapasitas_kapal = $kapal['kapasitas'] ?? 54;
                    if ($jumlah_tiket > $kapasitas_kapal) {
                        $errors[] = "Jumlah penumpang tidak boleh melebihi kapasitas kapal ({$kapasitas_kapal} orang).";
                    }
                }
            } catch (Exception $e) {
                $errors[] = "Gagal mengambil data kapal.";
            }
        }
        
        if ($tipe == 'shared' && $trip_id <= 0) {
            $errors[] = "Silakan pilih shared trip.";
        }
        
        // 🔥 VALIDASI SALDO
        if ($jenis_pembayaran == 'saldo') {
            // Ambil harga rute
            try {
                $stmt = $this->pdo->prepare("SELECT harga_jual FROM kapal_rute WHERE id = ?");
                $stmt->execute([$route_id]);
                $ruteHarga = $stmt->fetch(PDO::FETCH_ASSOC);
                $total_harga_temp = $ruteHarga['harga_jual'] ?? 0;
            } catch (Exception $e) {
                $total_harga_temp = 0;
            }
            
            $saldo = $this->getSaldo($user_id);
            if ($saldo < $total_harga_temp) {
                $errors[] = "Saldo tidak mencukupi. Saldo Anda: Rp " . number_format($saldo, 0, ',', '.') . " | Butuh: Rp " . number_format($total_harga_temp, 0, ',', '.');
            }
        }
        
        if (!empty($errors)) {
            $_SESSION['flash_error'] = implode(' ', $errors);
            header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
            exit;
        }
        
        // ===== CEK KETERSEDIAAN =====
        $isAvailable = $this->cekKetersediaanKapal($kapal_id, $tanggal);
        if (!$isAvailable) {
            $_SESSION['flash_error'] = "Kapal ini sudah dipesan untuk tanggal " . date('d/m/Y', strtotime($tanggal)) . ". Silakan pilih tanggal lain.";
            header("Location: ?page=wisatawan&action=booking&tanggal=" . $tanggal);
            exit;
        }
        
        // ===== AMBIL HARGA RUTE =====
        try {
            $stmt = $this->pdo->prepare("
                SELECT kr.harga_jual, kr.asal, kr.tujuan
                FROM kapal_rute kr 
                WHERE kr.kapal_id = ? AND kr.id = ?
            ");
            $stmt->execute([$kapal_id, $route_id]);
            $rute = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$rute) {
                $_SESSION['flash_error'] = "Rute tidak tersedia untuk kapal ini.";
                header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
                exit;
            }
        } catch (Exception $e) {
            $_SESSION['flash_error'] = "Gagal mengambil data rute.";
            header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
            exit;
        }
        
        // ===== HITUNG TOTAL =====
        $harga_perjalanan = $rute['harga_jual'];
        $total_harga = $harga_total > 0 ? $harga_total : $harga_perjalanan;
        $kode_pesanan = 'BOOK-' . strtoupper(uniqid()) . '-' . date('Ymd');
        $durasi_jam = $durasi * 24;
        
        // ==============================================
        // 🔥 LOGIKA PEMBAYARAN - DENGAN SALDO
        // ==============================================
        $status_pembayaran = 'belum_bayar';
        $jumlah_dibayar = 0;
        $sisa_pembayaran = 0;
        $status_pesanan = 'pending';
        $status_keberangkatan = 'menunggu';
        $snap_token = null;
        $snap_url = null;
        $bayar_dengan_saldo = 'tidak';
        $saldo_digunakan = 0;
        
        // 🔥 PROSES BAYAR DENGAN SALDO - DIPISAHKAN DARI TRANSAKSI UTAMA
        if ($jenis_pembayaran == 'saldo') {
            $saldo = $this->getSaldo($user_id);
            $saldo_digunakan = $total_harga;
            
            // Cek saldo cukup
            if ($saldo < $total_harga) {
                $_SESSION['flash_error'] = "Saldo tidak mencukupi. Saldo Anda: Rp " . number_format($saldo, 0, ',', '.');
                header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
                exit;
            }
            
            // 🔥 PROSES SALDO DENGAN TRANSACTION AMAN
            try {
                // Cek apakah sudah ada transaksi aktif
                if (!$this->pdo->inTransaction()) {
                    $this->pdo->beginTransaction();
                }
                
                $saldoBaru = $saldo - $total_harga;
                $stmt = $this->pdo->prepare("UPDATE saldo_wisatawan SET saldo = ? WHERE user_id = ?");
                $stmt->execute([$saldoBaru, $user_id]);
                
                // Simpan riwayat saldo
                $stmt = $this->pdo->prepare("
                    INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, tipe) 
                    VALUES (?, 'keluar', ?, ?, ?, ?, 'booking')
                ");
                $stmt->execute([
                    $user_id,
                    $total_harga,
                    $saldo,
                    $saldoBaru,
                    "Pembayaran booking pesanan {$kode_pesanan}"
                ]);
                
                if ($this->pdo->inTransaction()) {
                    $this->pdo->commit();
                }
                
                $status_pembayaran = 'lunas';
                $status_pesanan = 'confirmed';
                $jumlah_dibayar = $total_harga;
                $sisa_pembayaran = 0;
                $bayar_dengan_saldo = 'ya';
                
            } catch (Exception $e) {
                if ($this->pdo->inTransaction()) {
                    $this->pdo->rollBack();
                }
                error_log("Error proses saldo: " . $e->getMessage());
                $_SESSION['flash_error'] = "Gagal memproses pembayaran dengan saldo: " . $e->getMessage();
                header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
                exit;
            }
        } elseif ($jenis_pembayaran == 'cash') {
            // 🔥 BAYAR DI TEMPAT
            $status_pembayaran = 'cash';
            $jumlah_dibayar = 0;
            $sisa_pembayaran = $total_harga;
            $status_pesanan = 'pending';
            $status_keberangkatan = 'menunggu';
            $snap_token = null;
            $snap_url = null;
        } elseif ($jenis_pembayaran == 'dp') {
            $status_pembayaran = 'belum_bayar';
            $jumlah_dibayar = ceil($total_harga * 0.5);
            $sisa_pembayaran = $total_harga - $jumlah_dibayar;
            $status_pesanan = 'pending';
            $status_keberangkatan = 'menunggu';
        } else {
            // FULL
            $status_pembayaran = 'belum_bayar';
            $jumlah_dibayar = $total_harga;
            $sisa_pembayaran = 0;
            $status_pesanan = 'pending';
            $status_keberangkatan = 'menunggu';
        }
        
        // Ambil data pemilik
        try {
            $stmt = $this->pdo->prepare("SELECT id, nama, no_hp FROM users WHERE id = ?");
            $stmt->execute([$kapal['pemilik_id']]);
            $pemilik = $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pemilik = null;
        }
        
        // ==============================================
        // 🔥 INSERT PESANAN - DENGAN TRANSACTION AMAN
        // ==============================================
        try {
            // Cek apakah sudah ada transaksi aktif
            if (!$this->pdo->inTransaction()) {
                $this->pdo->beginTransaction();
            }
            
            // Cek apakah kolom bayar_dengan_saldo ada
            $stmt = $this->pdo->query("SHOW COLUMNS FROM pesanan LIKE 'bayar_dengan_saldo'");
            $hasBayarSaldo = $stmt->rowCount() > 0;
            
            if ($hasBayarSaldo) {
                $sql = "INSERT INTO pesanan (
                    user_id, kapal_id, route_id, kode_pesanan, nama_kapal, 
                    tanggal_berangkat, tanggal_pesan, jumlah_tiket, total_harga, 
                    status_pembayaran, catatan, nama_lengkap, email, no_hp, 
                    durasi_jam, nik_ktp, status_pesanan, jenis_booking, 
                    status_pembatalan, status_claim, status_pencairan,
                    reschedule_status,
                    waktu_jemput_rencana,
                    waktu_selesai_rencana,
                    jenis_pembayaran,
                    jumlah_dibayar,
                    sisa_pembayaran,
                    status_keberangkatan,
                    bayar_dengan_saldo,
                    created_at
                ) VALUES (
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, NOW()
                )";
                
                $params = [
                    $user_id, $kapal_id, $route_id, $kode_pesanan, $kapal['nama_kapal'],
                    $tanggal, date('Y-m-d'), $jumlah_tiket, $total_harga,
                    $status_pembayaran,
                    $catatan, $nama_lengkap, $email, $no_hp,
                    $durasi_jam,
                    $nik_ktp, $status_pesanan, $tipe,
                    'aktif', 'tidak',
                    'belum', 'tidak',
                    $waktu_jemput, $waktu_selesai,
                    $jenis_pembayaran, $jumlah_dibayar, $sisa_pembayaran, $status_keberangkatan,
                    $bayar_dengan_saldo
                ];
            } else {
                $sql = "INSERT INTO pesanan (
                    user_id, kapal_id, route_id, kode_pesanan, nama_kapal, 
                    tanggal_berangkat, tanggal_pesan, jumlah_tiket, total_harga, 
                    status_pembayaran, catatan, nama_lengkap, email, no_hp, 
                    durasi_jam, nik_ktp, status_pesanan, jenis_booking, 
                    status_pembatalan, status_claim, status_pencairan,
                    reschedule_status,
                    waktu_jemput_rencana,
                    waktu_selesai_rencana,
                    jenis_pembayaran,
                    jumlah_dibayar,
                    sisa_pembayaran,
                    status_keberangkatan,
                    created_at
                ) VALUES (
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, NOW()
                )";
                
                $params = [
                    $user_id, $kapal_id, $route_id, $kode_pesanan, $kapal['nama_kapal'],
                    $tanggal, date('Y-m-d'), $jumlah_tiket, $total_harga,
                    $status_pembayaran,
                    $catatan, $nama_lengkap, $email, $no_hp,
                    $durasi_jam,
                    $nik_ktp, $status_pesanan, $tipe,
                    'aktif', 'tidak',
                    'belum', 'tidak',
                    $waktu_jemput, $waktu_selesai,
                    $jenis_pembayaran, $jumlah_dibayar, $sisa_pembayaran, $status_keberangkatan
                ];
            }
            
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
            $pesanan_id = $this->pdo->lastInsertId();
            
            // 🔥 UPDATE RIWAYAT SALDO DENGAN REFERENSI_ID (JIKA SALDO)
            if ($jenis_pembayaran == 'saldo' && $pesanan_id > 0) {
                try {
                    $stmt = $this->pdo->prepare("
                        UPDATE riwayat_saldo 
                        SET referensi_id = ? 
                        WHERE user_id = ? 
                        AND keterangan = ? 
                        AND referensi_id IS NULL
                        ORDER BY id DESC LIMIT 1
                    ");
                    $stmt->execute([
                        $pesanan_id,
                        $user_id,
                        "Pembayaran booking pesanan {$kode_pesanan}"
                    ]);
                } catch (Exception $e) {
                    // Ignore error jika kolom referensi_id tidak ada
                }
            }
            
            if ($this->pdo->inTransaction()) {
                $this->pdo->commit();
            }
            
        } catch (Exception $e) {
            if ($this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            error_log("Booking Error: " . $e->getMessage());
            $_SESSION['flash_error'] = "Gagal memproses pesanan: " . $e->getMessage();
            header("Location: ?page=wisatawan&action=booking&kapal_id=" . $kapal_id);
            exit;
        }
        
        // ================================================================
        // KIRIM NOTIFIKASI
        // ================================================================
        require_once __DIR__ . '/../config/fonnte.php';
        
        $base_url = "http://" . $_SERVER['HTTP_HOST'] . "/reservasi-kapal-wisata";
        
        // ================================================================
        // 🔥 NOTIFIKASI KHUSUS UNTUK BAYAR DENGAN SALDO
        // ================================================================
        if ($jenis_pembayaran == 'saldo') {
            // Notifikasi ke WISATAWAN
            if (!empty($no_hp)) {
                $wa_msg = "
✅ *PEMBAYARAN BERHASIL DENGAN SALDO* ✅

Halo *{$nama_lengkap}*,

Pesanan Anda dengan kode *{$kode_pesanan}* telah berhasil dibayar menggunakan SALDO APLIKASI!

📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Metode: *SALDO APLIKASI*

✅ *PESANAN LANGSUNG DIKONFIRMASI*
Selamat menikmati perjalanan Anda! 🌊⛵

Terima kasih telah menggunakan layanan kami.
";
                sendWhatsApp($no_hp, $wa_msg);
            }
            
            // Notifikasi ke SUPIR
            if ($pemilik && !empty($pemilik['no_hp'])) {
                $wa_msg = "
💰 *PESANAN LUNAS DENGAN SALDO* 💰

📌 Kode Pesanan: *{$kode_pesanan}*
👤 Wisatawan: {$nama_lengkap}
📱 No HP: {$no_hp}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Metode: *SALDO APLIKASI*

✅ *PESANAN LANGSUNG DIKONFIRMASI*
Silakan siapkan kapal dan jemput wisatawan sesuai jadwal.
";
                sendWhatsApp($pemilik['no_hp'], $wa_msg);
            }
            
            // Notifikasi aplikasi
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                    VALUES (?, ?, ?, ?, 0, NOW())
                ");
                $title = "💰 Pembayaran Berhasil dengan Saldo";
                $msg = "Pesanan {$kode_pesanan} berhasil dibayar dengan saldo aplikasi.";
                $stmt->execute([$user_id, $title, $msg, $pesanan_id]);
                
                if (!empty($kapal['pemilik_id'])) {
                    $title = "💰 Pesanan Lunas (Saldo)";
                    $msg = "Wisatawan {$nama_lengkap} telah melunasi pesanan {$kode_pesanan} dengan saldo aplikasi.";
                    $stmt->execute([$kapal['pemilik_id'], $title, $msg, $pesanan_id]);
                }
            } catch (Exception $e) {}
            
            $_SESSION['flash_success'] = "✅ Booking berhasil! Kode: {$kode_pesanan}. Pembayaran menggunakan saldo berhasil.";
            
        } elseif ($jenis_pembayaran == 'cash') {
            // Notifikasi untuk CASH
            if ($pemilik && !empty($pemilik['no_hp'])) {
                $wa_msg = "
💵 *PESANAN BAYAR DI TEMPAT* 💵

📌 Kode Pesanan: *{$kode_pesanan}*
👤 Wisatawan: {$nama_lengkap}
📱 No HP: {$no_hp}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Jenis Bayar: *BAYAR DI TEMPAT*

⏳ Status: Menunggu Verifikasi Supir
Silakan verifikasi pesanan ini di aplikasi Anda.
";
                sendWhatsApp($pemilik['no_hp'], $wa_msg);
            }
            
            if (!empty($no_hp)) {
                $wa_msg = "
✅ *PESANAN DITERIMA - BAYAR DI TEMPAT* ✅

Halo *{$nama_lengkap}*,

Pesanan Anda dengan kode *{$kode_pesanan}* telah kami terima.

📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Jenis Bayar: *BAYAR DI TEMPAT*

📌 Bayar langsung kepada supir saat bertemu!

Terima kasih. 🌊⛵
";
                sendWhatsApp($no_hp, $wa_msg);
            }
            
            $_SESSION['flash_success'] = "✅ Booking berhasil! Kode: {$kode_pesanan}. Bayar di tempat saat bertemu supir.";
            
        } else {
            // Notifikasi untuk FULL / DP
            if ($pemilik && !empty($pemilik['no_hp'])) {
                $verif_link = $base_url . "/?page=supir&action=kelolaPesanan";
                $jenisBayarText = ($jenis_pembayaran == 'dp') ? 'DP 50% (Rp ' . number_format($jumlah_dibayar, 0, ',', '.') . ')' : 'Full';
                $wa_msg = "
🛥️ *PESANAN BARU MENUNGGU VERIFIKASI* 🛥️

📌 Kode Pesanan: *{$kode_pesanan}*
👤 Wisatawan: {$nama_lengkap}
📱 No HP: {$no_hp}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
⏱️ Durasi: {$durasi} hari
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Jenis Bayar: {$jenisBayarText}

🔗 Segera verifikasi: {$verif_link}
⚠️ Pesanan harus diverifikasi dalam 24 jam.
";
                sendWhatsApp($pemilik['no_hp'], $wa_msg);
            }
            
            if (!empty($no_hp)) {
                $jenisBayarText = ($jenis_pembayaran == 'dp') ? 'DP 50% (Rp ' . number_format($jumlah_dibayar, 0, ',', '.') . ')' : 'Full';
                $wa_msg = "
✅ *PESANAN DITERIMA* ✅

Halo *{$nama_lengkap}*,

Pesanan Anda dengan kode *{$kode_pesanan}* telah kami terima.

📅 Tanggal: " . date('d/m/Y', strtotime($tanggal)) . "
🕐 Waktu Jemput: {$waktu_jemput}
🏁 Waktu Selesai: {$waktu_selesai}
⛵ Kapal: {$kapal['nama_kapal']}
🗺️ Rute: {$rute['asal']} → {$rute['tujuan']}
👥 Penumpang: {$jumlah_tiket} orang
💰 Total: Rp " . number_format($total_harga, 0, ',', '.') . "
💳 Jenis Bayar: {$jenisBayarText}

⏳ Status: *MENUNGGU VERIFIKASI SUPIR KAPAL*

Kami akan memberi tahu Anda setelah supir kapal memverifikasi.

Terima kasih. 🌊⛵
";
                sendWhatsApp($no_hp, $wa_msg);
            }
            
            $_SESSION['flash_success'] = "✅ Booking berhasil! Kode: {$kode_pesanan}. Menunggu verifikasi supir kapal.";
        }
        
        header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
        exit;
    }
    
    /**
     * STATUS PESANAN - Detail satu pesanan
     */
    public function status() {
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.foto, k.pelabuhan_asal, k.pelabuhan_tujuan,
                       u.nama as pemilik_nama, u.no_hp as pemilik_no_hp
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                JOIN users u ON k.pemilik_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesanan = null;
        }
        
        if (!$pesanan) {
            $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        $pesanan['durasi_hari'] = ceil(($pesanan['durasi_jam'] ?? 24) / 24);
        
        $this->loadView('status_pesanan', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'pesanan' => $pesanan,
            'activeMenu' => 'riwayatPesanan'
        ]);
    }
    
    /**
     * RIWAYAT PESANAN - Semua pesanan user
     */
    public function riwayat() {
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        // ==============================================
        // CEK APAKAH TABEL CLAIM_PENGEMBALIAN ADA
        // ==============================================
        $claimTableExists = false;
        try {
            $stmt = $this->pdo->query("SHOW TABLES LIKE 'claim_pengembalian'");
            if ($stmt->rowCount() > 0) {
                $claimTableExists = true;
            }
        } catch (Exception $e) {
            $claimTableExists = false;
        }
        
        // ==============================================
        // AMBIL DATA PESANAN
        // ==============================================
        try {
            $selectFields = "p.*, k.nama_kapal, k.foto, k.pelabuhan_asal, k.pelabuhan_tujuan, k.kapasitas";
            
            if ($claimTableExists) {
                $selectFields .= ", c.id as claim_id, c.status_claim, c.alasan_claim as claim_alasan, 
                                  c.tanggal_claim, c.alasan_admin as claim_alasan_admin";
            }
            
            $query = "SELECT $selectFields 
                      FROM pesanan p
                      LEFT JOIN kapal k ON p.kapal_id = k.id";
            
            if ($claimTableExists) {
                $query .= " LEFT JOIN claim_pengembalian c ON p.id = c.pesanan_id";
            }
            
            $query .= " WHERE p.user_id = ?
                        ORDER BY p.created_at DESC";
            
            $stmt = $this->pdo->prepare($query);
            $stmt->execute([$user_id]);
            $pesanan = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesanan = [];
            error_log("Error mengambil data pesanan: " . $e->getMessage());
        }
        
        foreach ($pesanan as &$p) {
            $p['durasi_hari'] = ceil(($p['durasi_jam'] ?? 24) / 24);
            $p['claim_id'] = $p['claim_id'] ?? null;
            $p['status_claim'] = $p['status_claim'] ?? null;
            $p['claim_alasan'] = $p['claim_alasan'] ?? null;
            
            // ==============================================
            // 🔥 KONVERSI STATUS UNTUK VIEW
            // ==============================================
            $statusMap = [
                'tertunda' => 'pending',
                'dikonfirmasi' => 'confirmed',
                'selesai' => 'completed',
                'batalkan' => 'cancelled'
            ];
            
            $originalStatus = $p['status_pesanan'] ?? 'tertunda';
            $p['status_pesanan'] = $statusMap[$originalStatus] ?? $originalStatus;
            $p['original_status'] = $originalStatus;
            
            // ==============================================
            // 🔥 KONVERSI STATUS PEMBAYARAN
            // ==============================================
            $paymentMap = [
                'belum_bayar' => 'belum_bayar',
                'menunggu_konfirmasi' => 'menunggu_konfirmasi',
                'lunas' => 'lunas',
                'gagal' => 'gagal'
            ];
            $originalPayment = $p['status_pembayaran'] ?? 'belum_bayar';
            $p['status_pembayaran'] = $paymentMap[$originalPayment] ?? $originalPayment;
        }
        
        $this->loadView('riwayat_pesanan', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'pesanan' => $pesanan,
            'claimTableExists' => $claimTableExists,
            'activeMenu' => 'riwayatPesanan'
        ]);
    }

    /**
     * RIWAYAT PESANAN - Alias untuk riwayat()
     */
    public function riwayatPesanan() {
        $this->riwayat();
    }
    
    /**
     * UPLOAD BUKTI PEMBAYARAN
     */
    public function uploadPembayaran() {
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.pemilik_id, k.nama_kapal,
                       u.nama as pemilik_nama, u.no_hp as pemilik_no_hp
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                JOIN users u ON k.pemilik_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesanan = null;
        }
        
        if (!$pesanan) {
            $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        $validStatus = $this->getValidStatus('pesanan', 'status_pesanan', 'confirmed');
        if (!in_array($pesanan['status_pesanan'], ['confirmed', 'dikonfirmasi', $validStatus])) {
            $_SESSION['flash_error'] = "Pesanan belum diverifikasi oleh supir kapal. Silakan tunggu verifikasi.";
            header("Location: ?page=wisatawan&action=status&id=" . $id);
            exit;
        }
        
        if (!empty($pesanan['bukti_pembayaran']) && $pesanan['status_pembayaran'] == 'menunggu_konfirmasi') {
            $_SESSION['flash_error'] = "Bukti pembayaran sudah diupload dan menunggu konfirmasi.";
            header("Location: ?page=wisatawan&action=status&id=" . $id);
            exit;
        }
        
        $error = null;
        
        if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['bukti'])) {
            $target = $_SERVER['DOCUMENT_ROOT'] . '/reservasi-kapal-wisata/uploads/bukti/';
            if (!is_dir($target)) mkdir($target, 0777, true);
            
            $file = time() . '_' . basename($_FILES['bukti']['name']);
            if (move_uploaded_file($_FILES['bukti']['tmp_name'], $target . $file)) {
                try {
                    $validPaymentStatus = $this->getValidPaymentStatus('pesanan', 'status_pembayaran', 'menunggu_konfirmasi');
                    $stmt = $this->pdo->prepare("
                        UPDATE pesanan 
                        SET bukti_pembayaran = ?, 
                            status_pembayaran = ?
                        WHERE id = ?
                    ");
                    $stmt->execute([$file, $validPaymentStatus, $id]);
                    
                    require_once __DIR__ . '/../config/fonnte.php';
                    
                    $base_url = "http://" . $_SERVER['HTTP_HOST'] . "/reservasi-kapal-wisata";
                    $nama_wisatawan = $pesanan['nama_lengkap'] ?? $user['nama'];
                    
                    if (!empty($pesanan['pemilik_id'])) {
                        try {
                            $stmt = $this->pdo->prepare("
                                INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                                VALUES (?, ?, ?, ?, 0, NOW())
                            ");
                            $title = "📷 Bukti Pembayaran";
                            $msg = "Wisatawan {$nama_wisatawan} telah mengupload bukti pembayaran untuk pesanan {$pesanan['kode_pesanan']}.";
                            $stmt->execute([$pesanan['pemilik_id'], $title, $msg, $id]);
                        } catch (Exception $e) {
                            // Ignore
                        }
                    }
                    
                    if (!empty($pesanan['pemilik_no_hp'])) {
                        $wa_msg = "
📷 *BUKTI PEMBAYARAN DIUPLOAD* 📷

Wisatawan: {$nama_wisatawan}
Kode Pesanan: *{$pesanan['kode_pesanan']}*
Total: Rp " . number_format($pesanan['total_harga'], 0, ',', '.') . "
Kapal: {$pesanan['nama_kapal']}

🔗 Segera konfirmasi pembayaran:
" . $base_url . "/?page=supir&action=konfirmasiPembayaran&id=" . $id . "
";
                        sendWhatsApp($pesanan['pemilik_no_hp'], $wa_msg);
                    }
                    
                    $_SESSION['flash_success'] = "Bukti pembayaran berhasil diupload! Menunggu konfirmasi supir kapal.";
                    header("Location: ?page=wisatawan&action=status&id=" . $id);
                    exit;
                } catch (Exception $e) {
                    $error = "Gagal menyimpan data: " . $e->getMessage();
                }
            } else {
                $error = "Gagal upload bukti pembayaran.";
            }
        }
        
        $pesanan['durasi_hari'] = ceil(($pesanan['durasi_jam'] ?? 24) / 24);
        
        $this->loadView('upload_pembayaran', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'pesanan' => $pesanan,
            'error' => $error,
            'activeMenu' => 'riwayatPesanan'
        ]);
    }
    
    /**
     * PROFIL SAYA - Edit profil wisatawan
     */
    public function profil() {
        $user_id = $_SESSION['user_id'] ?? 0;
        if (!$user_id) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $user = $this->getUserData($user_id);
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        // Update session dengan data terbaru
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        // Proses update profil
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $nama = trim($_POST['nama'] ?? '');
            $no_hp = trim($_POST['no_hp'] ?? '');
            $email = trim($_POST['email'] ?? '');
            $alamat = trim($_POST['alamat'] ?? '');
            $errors = [];
            
            // Validasi
            if (empty($nama)) $errors[] = "Nama tidak boleh kosong.";
            if (empty($no_hp)) $errors[] = "Nomor HP tidak boleh kosong.";
            if (empty($email)) $errors[] = "Email tidak boleh kosong.";
            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = "Format email tidak valid.";
            
            // Validasi no_hp (minimal 10 digit)
            $cleanNoHp = preg_replace('/[^0-9]/', '', $no_hp);
            if (!empty($no_hp) && (strlen($cleanNoHp) < 10 || strlen($cleanNoHp) > 15)) {
                $errors[] = "Nomor HP harus 10-15 digit angka.";
            }
            
            // Proses upload foto
            $foto = $user['foto_profil'] ?? null;
            if (isset($_FILES['foto_profil']) && $_FILES['foto_profil']['error'] == 0) {
                $file = $_FILES['foto_profil'];
                $allowed = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif', 'image/webp'];
                $maxSize = 2 * 1024 * 1024; // 2MB
                
                if (!in_array($file['type'], $allowed)) {
                    $errors[] = "Format foto harus JPG, PNG, GIF, atau WebP.";
                } elseif ($file['size'] > $maxSize) {
                    $errors[] = "Ukuran foto maksimal 2MB.";
                } else {
                    $target_dir = $_SERVER['DOCUMENT_ROOT'] . '/reservasi-kapal-wisata/uploads/profil/';
                    if (!is_dir($target_dir)) {
                        mkdir($target_dir, 0777, true);
                    }
                    
                    // Hapus foto lama jika ada
                    if (!empty($user['foto_profil']) && file_exists($target_dir . $user['foto_profil'])) {
                        unlink($target_dir . $user['foto_profil']);
                    }
                    
                    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
                    $foto = 'profile_' . $user_id . '_' . time() . '.' . $ext;
                    
                    if (!move_uploaded_file($file['tmp_name'], $target_dir . $foto)) {
                        $errors[] = "Gagal upload foto. Silakan coba lagi.";
                    }
                }
            }
            
            // Proses update password
            $password_update = '';
            if (!empty($_POST['password'])) {
                $password = $_POST['password'];
                if (strlen($password) < 6) {
                    $errors[] = "Password minimal 6 karakter.";
                } else {
                    $password_update = ", password = '" . password_hash($password, PASSWORD_DEFAULT) . "'";
                }
            }
            
            // Jika tidak ada error, update database
            if (empty($errors)) {
                try {
                    // Cek struktur tabel users
                    $columns = $this->getTableColumns('users');
                    
                    $sql = "UPDATE users SET 
                            nama = ?, 
                            no_hp = ?, 
                            email = ?";
                    
                    $params = [$nama, $cleanNoHp, $email];
                    
                    // Tambahkan alamat jika kolom ada
                    if (in_array('alamat', $columns)) {
                        $sql .= ", alamat = ?";
                        $params[] = $alamat;
                    }
                    
                    // Tambahkan foto jika ada perubahan
                    if ($foto !== null && $foto !== $user['foto_profil']) {
                        $sql .= ", foto_profil = ?";
                        $params[] = $foto;
                    }
                    
                    // Tambahkan password jika ada perubahan
                    if (!empty($password_update)) {
                        $sql .= $password_update;
                    }
                    
                    $sql .= " WHERE id = ?";
                    $params[] = $user_id;
                    
                    $stmt = $this->pdo->prepare($sql);
                    $stmt->execute($params);
                    
                    // Update session dengan data baru
                    $_SESSION['nama'] = $nama;
                    $_SESSION['no_hp'] = $cleanNoHp;
                    $_SESSION['email'] = $email;
                    if ($foto !== null && $foto !== $user['foto_profil']) {
                        $_SESSION['foto_profil'] = $foto;
                    }
                    
                    $_SESSION['flash_success'] = "✅ Profil berhasil diperbarui!";
                } catch (Exception $e) {
                    $_SESSION['flash_error'] = "❌ Gagal update profil: " . $e->getMessage();
                }
            } else {
                $_SESSION['flash_error'] = implode(' ', $errors);
            }
            
            header("Location: ?page=wisatawan&action=profil");
            exit;
        }
        
        // Ambil data terbaru setelah update
        $user = $this->getUserData($user_id);
        
        $this->loadView('profil', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'activeMenu' => 'profil'
        ]);
    }
    
    /**
     * SEND NOTIFICATION - Kirim notifikasi ke database
     */
    private function sendNotification($kapal_id, $pesanan_id, $title, $message) {
        try {
            // Ambil pemilik kapal (supir)
            $stmt = $this->pdo->prepare("SELECT pemilik_id FROM kapal WHERE id = ?");
            $stmt->execute([$kapal_id]);
            $kapal = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($kapal) {
                // Notifikasi untuk supir
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, type, booking_id, is_read, created_at) 
                    VALUES (?, ?, ?, 'booking', ?, 0, NOW())
                ");
                $stmt->execute([$kapal['pemilik_id'], $title, $message, $pesanan_id]);
            }
            
            // Notifikasi untuk admin (user_id = 1)
            $stmt = $this->pdo->prepare("
                INSERT INTO notifications (user_id, title, message, type, booking_id, is_read, created_at) 
                VALUES (1, ?, ?, 'booking', ?, 0, NOW())
            ");
            $stmt->execute([$title, $message, $pesanan_id]);
            
        } catch (Exception $e) {
            error_log("Error sending notification: " . $e->getMessage());
        }
    }
    
    // ================================================================
    // 🔥 NOTIFICATION METHODS - AJAX & VIEW
    // ================================================================
    
    /**
     * NOTIFICATIONS - Menampilkan semua notifikasi wisatawan
     * URL: ?page=wisatawan&action=notifikasi
     */
    public function notifikasi() {
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        
        $unreadCount = $this->getUnreadCount($user_id);
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT * FROM notifications 
                WHERE user_id = ? 
                ORDER BY created_at DESC
                LIMIT 50
            ");
            $stmt->execute([$user_id]);
            $notifikasi = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $notifikasi = [];
            error_log("Error getting notifications: " . $e->getMessage());
        }
        
        $this->loadView('notifikasi', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'notifikasi' => $notifikasi,
            'activeMenu' => 'notifikasi'
        ]);
    }
    
    /**
     * NOTIFICATIONS - Alias untuk notifikasi()
     */
    public function notifications() {
        $this->notifikasi();
    }
    
    /**
     * MARK AS READ - Tandai satu notifikasi sebagai dibaca (AJAX)
     * URL: ?page=ajax&action=markAsRead
     * Method: POST
     */
    public function markAsRead() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized - Silakan login sebagai wisatawan'
            ]);
            exit;
        }
        
        $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        $user_id = $_SESSION['user_id'];
        
        if ($id <= 0) {
            echo json_encode([
                'success' => false, 
                'message' => 'ID notifikasi tidak valid'
            ]);
            exit;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                UPDATE notifications 
                SET is_read = 1 
                WHERE id = ? AND user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            
            // Update unread count di session
            $_SESSION['unreadCount'] = $this->getUnreadCount($user_id);
            
            echo json_encode([
                'success' => true, 
                'message' => 'Notifikasi ditandai sebagai dibaca'
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false, 
                'message' => 'Error: ' . $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * MARK ALL AS READ - Tandai semua notifikasi sebagai dibaca (AJAX)
     * URL: ?page=ajax&action=markAllAsRead
     * Method: POST
     */
    public function markAllAsRead() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized - Silakan login sebagai wisatawan'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        
        try {
            $stmt = $this->pdo->prepare("
                UPDATE notifications 
                SET is_read = 1 
                WHERE user_id = ? AND is_read = 0
            ");
            $stmt->execute([$user_id]);
            
            // Update unread count di session
            $_SESSION['unreadCount'] = 0;
            
            echo json_encode([
                'success' => true, 
                'message' => 'Semua notifikasi ditandai sebagai dibaca',
                'affected' => $stmt->rowCount()
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false, 
                'message' => 'Error: ' . $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * DELETE NOTIFICATION - Hapus notifikasi (AJAX)
     * URL: ?page=ajax&action=deleteNotification
     * Method: POST
     */
    public function deleteNotification() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized - Silakan login sebagai wisatawan'
            ]);
            exit;
        }
        
        $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        $user_id = $_SESSION['user_id'];
        
        if ($id <= 0) {
            echo json_encode([
                'success' => false, 
                'message' => 'ID notifikasi tidak valid'
            ]);
            exit;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                DELETE FROM notifications 
                WHERE id = ? AND user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            
            // Update unread count di session
            $_SESSION['unreadCount'] = $this->getUnreadCount($user_id);
            
            echo json_encode([
                'success' => true, 
                'message' => 'Notifikasi dihapus'
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false, 
                'message' => 'Error: ' . $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * GET UNREAD COUNT - Ambil jumlah notifikasi belum dibaca (AJAX)
     * URL: ?page=ajax&action=getUnreadCount
     * Method: GET
     */
    public function getUnreadCountAjax() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'count' => 0, 
                'success' => false,
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        
        try {
            $count = $this->getUnreadCount($user_id);
            $_SESSION['unreadCount'] = $count;
            
            echo json_encode([
                'count' => $count,
                'success' => true
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'count' => 0,
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * NOTIFICATION COUNT - Alias untuk getUnreadCountAjax (AJAX)
     */
    public function notificationCount() {
        $this->getUnreadCountAjax();
    }
    
    /**
     * GET NOTIFICATIONS - Ambil daftar notifikasi dengan pagination (AJAX)
     * URL: ?page=ajax&action=getNotifications
     * Method: GET
     * Parameters: limit, offset
     */
    public function getNotifications() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
        $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
        
        try {
            // Get notifications
            $stmt = $this->pdo->prepare("
                SELECT * FROM notifications 
                WHERE user_id = ? 
                ORDER BY created_at DESC 
                LIMIT ? OFFSET ?
            ");
            $stmt->execute([$user_id, $limit, $offset]);
            $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Get total count
            $stmt = $this->pdo->prepare("SELECT COUNT(*) as total FROM notifications WHERE user_id = ?");
            $stmt->execute([$user_id]);
            $total = $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?? 0;
            
            echo json_encode([
                'success' => true,
                'data' => $notifications,
                'total' => (int)$total,
                'limit' => $limit,
                'offset' => $offset,
                'hasMore' => ($offset + $limit) < $total
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * LOAD MORE NOTIFICATIONS - Load notifikasi lebih banyak (AJAX)
     * URL: ?page=ajax&action=loadMoreNotifications
     * Method: GET
     * Parameters: page, limit
     */
    public function loadMoreNotifications() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
        $offset = ($page - 1) * $limit;
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT * FROM notifications 
                WHERE user_id = ? 
                ORDER BY created_at DESC 
                LIMIT ? OFFSET ?
            ");
            $stmt->execute([$user_id, $limit, $offset]);
            $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Get total count
            $stmt = $this->pdo->prepare("SELECT COUNT(*) as total FROM notifications WHERE user_id = ?");
            $stmt->execute([$user_id]);
            $total = $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?? 0;
            
            echo json_encode([
                'success' => true,
                'data' => $notifications,
                'page' => $page,
                'limit' => $limit,
                'total' => (int)$total,
                'hasMore' => ($offset + $limit) < $total
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * BACA NOTIFIKASI - Tandai satu notifikasi sebagai dibaca (via GET)
     * URL: ?page=wisatawan&action=bacaNotifikasi&id=XXX
     */
    public function bacaNotifikasi() {
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        
        if ($id > 0) {
            try {
                $stmt = $this->pdo->prepare("
                    UPDATE notifications 
                    SET is_read = 1 
                    WHERE id = ? AND user_id = ?
                ");
                $stmt->execute([$id, $user_id]);
                $_SESSION['flash_success'] = "✅ Notifikasi ditandai sebagai dibaca.";
            } catch (Exception $e) {
                $_SESSION['flash_error'] = "❌ Gagal menandai notifikasi.";
            }
        }
        
        header("Location: ?page=wisatawan&action=notifikasi");
        exit;
    }
    
    /**
     * BACA SEMUA NOTIFIKASI - Tandai semua sebagai dibaca (via GET)
     * URL: ?page=wisatawan&action=bacaSemuaNotifikasi
     */
    public function bacaSemuaNotifikasi() {
        $user_id = $_SESSION['user_id'];
        
        try {
            $stmt = $this->pdo->prepare("
                UPDATE notifications 
                SET is_read = 1 
                WHERE user_id = ? AND is_read = 0
            ");
            $stmt->execute([$user_id]);
            $_SESSION['unreadCount'] = 0;
            $_SESSION['flash_success'] = "✅ Semua notifikasi telah ditandai sebagai dibaca.";
        } catch (Exception $e) {
            $_SESSION['flash_error'] = "❌ Gagal menandai notifikasi: " . $e->getMessage();
        }
        
        header("Location: ?page=wisatawan&action=notifikasi");
        exit;
    }
    
    /**
     * CLEAR ALL NOTIFICATIONS - Hapus semua notifikasi yang sudah dibaca (AJAX)
     * URL: ?page=ajax&action=clearAllNotifications
     * Method: POST
     */
    public function clearAllNotifications() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        
        try {
            $stmt = $this->pdo->prepare("
                DELETE FROM notifications 
                WHERE user_id = ? AND is_read = 1
            ");
            $stmt->execute([$user_id]);
            
            echo json_encode([
                'success' => true,
                'message' => 'Semua notifikasi yang sudah dibaca dihapus',
                'deleted' => $stmt->rowCount()
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * UPDATE SESSION FOTO - Update foto profil di session (AJAX)
     * URL: ?page=ajax&action=updateSessionFoto
     * Method: POST
     */
    public function updateSessionFoto() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $foto = isset($_POST['foto']) ? trim($_POST['foto']) : '';
        $user_id = $_SESSION['user_id'];
        
        if (empty($foto)) {
            echo json_encode([
                'success' => false,
                'message' => 'Foto tidak ditemukan'
            ]);
            exit;
        }
        
        try {
            $stmt = $this->pdo->prepare("UPDATE users SET foto_profil = ? WHERE id = ?");
            $stmt->execute([$foto, $user_id]);
            $_SESSION['foto_profil'] = $foto;
            
            echo json_encode([
                'success' => true,
                'message' => 'Foto profil berhasil diperbarui'
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    /**
     * GET USER DATA - Ambil data user (AJAX)
     * URL: ?page=ajax&action=getUserData
     * Method: GET
     */
    public function getUserDataAjax() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT id, nama, email, no_hp, foto_profil, role, created_at 
                FROM users 
                WHERE id = ?
            ");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user) {
                echo json_encode([
                    'success' => false,
                    'message' => 'User tidak ditemukan'
                ]);
                exit;
            }
            
            echo json_encode([
                'success' => true,
                'data' => $user
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
    
    // ================================================================
    // 🔥 SALDO WISATAWAN - DITAMBAHKAN
    // ================================================================
    
    /**
     * SALDO SAYA - Menampilkan saldo dan riwayat
     * URL: ?page=wisatawan&action=saldo
     */
    public function saldo() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        // Ambil saldo
        $saldo = $this->getSaldo($user_id);
        
        // Ambil riwayat saldo
        $riwayat = [];
        try {
            $stmt = $this->pdo->prepare("
                SELECT * FROM riwayat_saldo 
                WHERE user_id = ? 
                ORDER BY created_at DESC 
                LIMIT 50
            ");
            $stmt->execute([$user_id]);
            $riwayat = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $riwayat = [];
            error_log("Error get riwayat saldo: " . $e->getMessage());
        }
        
        $this->loadView('saldo', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'saldo' => $saldo,
            'riwayat' => $riwayat,
            'activeMenu' => 'saldo'
        ]);
    }
    
    /**
     * CEK SALDO AJAX - Untuk cek saldo via AJAX
     * URL: ?page=ajax&action=getSaldo
     * Method: GET
     */
    public function getSaldoAjax() {
        header('Content-Type: application/json');
        header('Cache-Control: no-cache, must-revalidate');
        
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            echo json_encode([
                'success' => false, 
                'message' => 'Unauthorized'
            ]);
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $saldo = $this->getSaldo($user_id);
        
        echo json_encode([
            'success' => true,
            'saldo' => $saldo,
            'formatted' => 'Rp ' . number_format($saldo, 0, ',', '.')
        ]);
        exit;
    }
    
    /**
     * TAMBAH SALDO - Top up saldo wisatawan (untuk admin/sistem)
     * Helper method
     */
    private function tambahSaldo($user_id, $jumlah, $keterangan, $referensi_id = null) {
        try {
            $this->pdo->beginTransaction();
            
            // Ambil saldo saat ini
            $stmt = $this->pdo->prepare("SELECT saldo FROM saldo_wisatawan WHERE user_id = ?");
            $stmt->execute([$user_id]);
            $saldo_sekarang = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($saldo_sekarang) {
                // Update saldo
                $saldo_baru = $saldo_sekarang['saldo'] + $jumlah;
                $stmt = $this->pdo->prepare("UPDATE saldo_wisatawan SET saldo = ? WHERE user_id = ?");
                $stmt->execute([$saldo_baru, $user_id]);
            } else {
                // Buat saldo baru
                $saldo_baru = $jumlah;
                $stmt = $this->pdo->prepare("INSERT INTO saldo_wisatawan (user_id, saldo) VALUES (?, ?)");
                $stmt->execute([$user_id, $saldo_baru]);
            }
            
            // Simpan riwayat
            $stmt = $this->pdo->prepare("
                INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, referensi_id) 
                VALUES (?, 'masuk', ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $user_id,
                $jumlah,
                $saldo_sekarang ? $saldo_sekarang['saldo'] : 0,
                $saldo_baru,
                $keterangan,
                $referensi_id
            ]);
            
            $this->pdo->commit();
            return true;
            
        } catch (Exception $e) {
            $this->pdo->rollBack();
            error_log("Error tambahSaldo: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * KURANGI SALDO - Kurangi saldo wisatawan
     * Helper method
     */
    private function kurangiSaldo($user_id, $jumlah, $keterangan, $referensi_id = null) {
        try {
            $this->pdo->beginTransaction();
            
            // Ambil saldo saat ini
            $stmt = $this->pdo->prepare("SELECT saldo FROM saldo_wisatawan WHERE user_id = ?");
            $stmt->execute([$user_id]);
            $saldo_sekarang = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$saldo_sekarang) {
                throw new Exception('Saldo tidak ditemukan.');
            }
            
            if ($saldo_sekarang['saldo'] < $jumlah) {
                throw new Exception('Saldo tidak mencukupi.');
            }
            
            // Update saldo
            $saldo_baru = $saldo_sekarang['saldo'] - $jumlah;
            $stmt = $this->pdo->prepare("UPDATE saldo_wisatawan SET saldo = ? WHERE user_id = ?");
            $stmt->execute([$saldo_baru, $user_id]);
            
            // Simpan riwayat
            $stmt = $this->pdo->prepare("
                INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, referensi_id) 
                VALUES (?, 'keluar', ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $user_id,
                $jumlah,
                $saldo_sekarang['saldo'],
                $saldo_baru,
                $keterangan,
                $referensi_id
            ]);
            
            $this->pdo->commit();
            return true;
            
        } catch (Exception $e) {
            $this->pdo->rollBack();
            error_log("Error kurangiSaldo: " . $e->getMessage());
            return false;
        }
    }
    
    // ================================================================
    // 🔥 BATALKAN PESANAN - WISATAWAN
    // ================================================================
    
    /**
     * HALAMAN FORM BATAL PESANAN
     * URL: ?page=wisatawan&action=formBatalPesanan&id=XXX
     */
    public function formBatalPesanan() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        if ($id <= 0) {
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal 
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
                header("Location: ?page=wisatawan&action=riwayat");
                exit;
            }
            
            // ==============================================
            // 🔥 CEK APAKAH BISA BATALKAN - LOGIKA YANG BENAR
            // ==============================================
            $canCancel = false;
            $isCompleted = ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai');
            $isConfirmed = ($pesanan['status_pesanan'] == 'confirmed' || $pesanan['status_pesanan'] == 'dikonfirmasi');
            $isPaid = ($pesanan['status_pembayaran'] == 'lunas');
            $isCancelled = ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan');
            $isPending = ($pesanan['status_pesanan'] == 'pending' || $pesanan['status_pesanan'] == 'menunggu');
            $isDijemput = !empty($pesanan['waktu_jemput_aktual']);
            
            // 1. Cek sudah selesai
            if ($isCompleted) {
                $canCancel = false;
            } 
            // 2. Cek sudah dibatalkan
            elseif ($isCancelled) {
                $canCancel = false;
            } 
            // 3. Cek pending - BISA batalkan
            elseif ($isPending) {
                $canCancel = true;
            } 
            // 4. Cek confirmed - cek telat
            elseif ($isConfirmed && $isPaid) {
                if ($isDijemput) {
                    $canCancel = false;
                } else {
                    $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
                    $now = new DateTime();
                    
                    $waktuJemputRencana = !empty($pesanan['waktu_jemput_rencana']) 
                        ? DateTime::createFromFormat('H:i:s', $pesanan['waktu_jemput_rencana']) 
                        : new DateTime('08:00:00');
                    
                    $batasWaktuJemput = clone $tanggalBerangkat;
                    $batasWaktuJemput->setTime(
                        $waktuJemputRencana->format('H'),
                        $waktuJemputRencana->format('i'),
                        $waktuJemputRencana->format('s')
                    );
                    $batasWaktuJemput->modify('+2 hours');
                    
                    $isTerlambat = ($now > $batasWaktuJemput);
                    $isTanggalLewat = ($tanggalBerangkat < $now);
                    
                    // 🔥 BISA BATALKAN JIKA TERLAMBAT > 2 JAM ATAU TANGGAL LEWAT
                    if ($isTerlambat || $isTanggalLewat) {
                        $canCancel = true;
                    } else {
                        $canCancel = false;
                    }
                }
            } else {
                $canCancel = false;
            }
            
            // ==============================================
            // CEK APAKAH BISA CLAIM (SETELAH BATAL)
            // ==============================================
            $canClaim = false;
            $claimStatus = $pesanan['status_claim'] ?? 'tidak';
            
            if ($isCancelled && $claimStatus == 'tidak' && !$isCompleted) {
                // Pesanan sudah dibatalkan, belum ada claim
                $canClaim = true;
            } elseif ($isCancelled && $claimStatus == 'menunggu') {
                $canClaim = false;
            } elseif ($isCancelled && $claimStatus == 'diterima') {
                $canClaim = false;
            } elseif ($isCancelled && $claimStatus == 'ditolak') {
                $canClaim = false;
            }
            
            // ==============================================
            // KIRIM KE VIEW
            // ==============================================
            $this->loadView('form_batal_pesanan', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'canCancel' => $canCancel,
                'canClaim' => $canClaim,
                'activeMenu' => 'riwayatPesanan'
            ]);
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = 'Error: ' . $e->getMessage();
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
    }
    
    /**
     * PROSES BATAL PESANAN - Proses pembatalan pesanan
     * DIPERBAIKI - Bisa batalkan confirmed jika telat > 2 jam
     * URL: ?page=wisatawan&action=prosesBatalPesanan
     * Method: GET (dari link) atau POST
     */
    public function prosesBatalPesanan() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        // Support GET dan POST
        $pesanan_id = (int) ($_GET['id'] ?? $_POST['pesanan_id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        try {
            // Cek pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.pemilik_id, u.nama as wisatawan_nama, u.no_hp as wisatawan_hp
                FROM pesanan p
                JOIN kapal k ON p.kapal_id = k.id
                JOIN users u ON p.user_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // ==============================================
            // 🔥 CEK APAKAH BISA BATALKAN - LOGIKA YANG BENAR
            // ==============================================
            $isCompleted = ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai');
            $isConfirmed = ($pesanan['status_pesanan'] == 'confirmed' || $pesanan['status_pesanan'] == 'dikonfirmasi');
            $isPaid = ($pesanan['status_pembayaran'] == 'lunas');
            $isCancelled = ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan');
            $isPending = ($pesanan['status_pesanan'] == 'pending' || $pesanan['status_pesanan'] == 'menunggu');
            $isDijemput = !empty($pesanan['waktu_jemput_aktual']);
            
            // 1. Cek sudah selesai
            if ($isCompleted) {
                throw new Exception('Pesanan sudah selesai. Tidak dapat dibatalkan.');
            }
            
            // 2. Cek sudah dibatalkan
            if ($isCancelled) {
                throw new Exception('Pesanan sudah dibatalkan sebelumnya.');
            }
            
            // 3. Cek pending - BISA batalkan
            if ($isPending) {
                // Lanjutkan
            }
            // 4. Cek confirmed - cek telat
            elseif ($isConfirmed && $isPaid) {
                if ($isDijemput) {
                    throw new Exception('Anda sudah dijemput oleh supir. Tidak dapat membatalkan.');
                }
                
                $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
                $now = new DateTime();
                
                $waktuJemputRencana = !empty($pesanan['waktu_jemput_rencana']) 
                    ? DateTime::createFromFormat('H:i:s', $pesanan['waktu_jemput_rencana']) 
                    : new DateTime('08:00:00');
                
                $batasWaktuJemput = clone $tanggalBerangkat;
                $batasWaktuJemput->setTime(
                    $waktuJemputRencana->format('H'),
                    $waktuJemputRencana->format('i'),
                    $waktuJemputRencana->format('s')
                );
                $batasWaktuJemput->modify('+2 hours');
                
                $isTerlambat = ($now > $batasWaktuJemput);
                $isTanggalLewat = ($tanggalBerangkat < $now);
                
                if (!$isTerlambat && !$isTanggalLewat) {
                    throw new Exception('Belum melewati batas waktu 2 jam. Silakan tunggu atau hubungi supir.');
                }
            } else {
                throw new Exception('Pesanan tidak dapat dibatalkan. Status saat ini: ' . $pesanan['status_pesanan']);
            }
            
            // ==============================================
            // 🔥 UPDATE STATUS PESANAN MENJADI CANCELLED
            // ==============================================
            $this->pdo->beginTransaction();
            
            $alasan = "Pesanan dibatalkan oleh wisatawan karena supir tidak menjemput sesuai jadwal (terlambat > 2 jam).";
            
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET status_pesanan = 'cancelled',
                    status_pembatalan = 'dibatalkan',
                    tanggal_pembatalan = NOW(),
                    alasan_penolakan = ?
                WHERE id = ?
            ");
            $stmt->execute([$alasan, $pesanan_id]);
            
            $this->pdo->commit();
            
            // ================================================================
            // KIRIM NOTIFIKASI
            // ================================================================
            require_once __DIR__ . '/../config/fonnte.php';
            
            $base_url = "http://" . $_SERVER['HTTP_HOST'] . "/reservasi-kapal-wisata";
            
            // Notifikasi ke supir
            if (!empty($pesanan['pemilik_id'])) {
                try {
                    $stmt = $this->pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                        VALUES (?, '❌ Pesanan Dibatalkan', ?, ?, 0, NOW())
                    ");
                    $msg = "Wisatawan {$pesanan['wisatawan_nama']} membatalkan pesanan {$pesanan['kode_pesanan']} karena supir tidak menjemput.";
                    $stmt->execute([$pesanan['pemilik_id'], $msg, $pesanan_id]);
                } catch (Exception $e) {}
            }
            
            // WhatsApp ke wisatawan
            if (!empty($pesanan['wisatawan_hp'])) {
                $wa_msg = "
❌ *PESANAN DIBATALKAN* ❌

Halo *{$pesanan['wisatawan_nama']}*,

Pesanan Anda dengan kode *{$pesanan['kode_pesanan']}* telah berhasil dibatalkan.

📅 Tanggal: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "
⛵ Kapal: {$pesanan['nama_kapal']}
📝 Alasan: Supir tidak menjemput sesuai jadwal

💰 Status pembayaran: Lunas

📌 *Anda sekarang bisa mengajukan Claim Pengembalian Dana!*

Terima kasih. 🌊
";
                sendWhatsApp($pesanan['wisatawan_hp'], $wa_msg);
            }
            
            $_SESSION['flash_success'] = "✅ Pesanan berhasil dibatalkan! Silakan ajukan claim pengembalian dana.";
            header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
            exit;
            
        } catch (Exception $e) {
            if (isset($this->pdo) && $this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            $_SESSION['flash_error'] = "❌ " . $e->getMessage();
            header("Location: ?page=wisatawan&action=formBatalPesanan&id=" . $pesanan_id);
            exit;
        }
    }
    
    // ================================================================
    // 🔥 CLAIM PENGEMBALIAN DANA - WISATAWAN
    // ================================================================
    
    /**
     * AJUKAN CLAIM - Halaman form claim (handle GET dan POST)
     * URL: ?page=wisatawan&action=ajukanClaim&pesanan_id=XXX
     */
    public function ajukanClaim() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $pesanan_id = (int) ($_GET['pesanan_id'] ?? $_POST['pesanan_id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        // 🔥 VARIABEL UNTUK NOTIFIKASI
        $result = null;
        
        // 🔥 CEK APAKAH ADA SUBMIT CLAIM (POST)
        if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['submit_claim'])) {
            $pesanan_id = (int) ($_POST['pesanan_id'] ?? 0);
            $alasan = trim($_POST['alasan'] ?? '');
            $deskripsi = trim($_POST['deskripsi'] ?? '');
            
            error_log("=== POST CLAIM DARI HALAMAN SAMA ===");
            error_log("pesanan_id: " . $pesanan_id);
            error_log("alasan: " . $alasan);
            error_log("deskripsi: " . $deskripsi);
            
            // VALIDASI
            if ($pesanan_id <= 0) {
                $result = ['success' => false, 'title' => 'Gagal!', 'message' => 'ID pesanan tidak valid.'];
            } elseif (empty($alasan)) {
                $result = ['success' => false, 'title' => 'Gagal!', 'message' => 'Silakan pilih alasan claim.'];
            } elseif (empty($deskripsi) || strlen($deskripsi) < 10) {
                $result = ['success' => false, 'title' => 'Gagal!', 'message' => 'Deskripsi minimal 10 karakter.'];
            } else {
                try {
                    // CEK PESANAN
                    $stmt = $this->pdo->prepare("
                        SELECT p.*, k.nama_kapal, k.pemilik_id, u.nama as wisatawan_nama, u.no_hp as wisatawan_hp
                        FROM pesanan p
                        JOIN kapal k ON p.kapal_id = k.id
                        JOIN users u ON p.user_id = u.id
                        WHERE p.id = ? AND p.user_id = ?
                    ");
                    $stmt->execute([$pesanan_id, $user_id]);
                    $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
                    
                    if (!$pesanan) {
                        $result = ['success' => false, 'title' => 'Gagal!', 'message' => 'Pesanan tidak ditemukan.'];
                    } else {
                        // CEK SUDAH ADA CLAIM
                        $stmt = $this->pdo->prepare("SELECT id FROM claim_pengembalian WHERE pesanan_id = ?");
                        $stmt->execute([$pesanan_id]);
                        if ($stmt->rowCount() > 0) {
                            $result = ['success' => false, 'title' => 'Gagal!', 'message' => 'Claim sudah diajukan untuk pesanan ini.'];
                        } else {
                            // SIMPAN CLAIM
                            $fullAlasan = $alasan . " - " . $deskripsi;
                            
                            $this->pdo->beginTransaction();
                            
                            $stmt = $this->pdo->prepare("
                                INSERT INTO claim_pengembalian (pesanan_id, wisatawan_id, alasan_claim, status_claim, tanggal_claim) 
                                VALUES (?, ?, ?, 'pending', NOW())
                            ");
                            $stmt->execute([$pesanan_id, $user_id, $fullAlasan]);
                            
                            $claimId = $this->pdo->lastInsertId();
                            
                            $stmt = $this->pdo->prepare("
                                UPDATE pesanan 
                                SET status_claim = 'menunggu', 
                                    tanggal_claim = NOW() 
                                WHERE id = ?
                            ");
                            $stmt->execute([$pesanan_id]);
                            
                            $this->pdo->commit();
                            
                            $result = [
                                'success' => true, 
                                'title' => '✅ Berhasil!', 
                                'message' => 'Claim berhasil diajukan! Menunggu verifikasi admin. ID Claim: #' . $claimId
                            ];
                            
                            error_log("Claim berhasil disimpan dengan ID: " . $claimId);
                        }
                    }
                } catch (Exception $e) {
                    if (isset($this->pdo) && $this->pdo->inTransaction()) {
                        $this->pdo->rollBack();
                    }
                    error_log("ERROR prosesClaim: " . $e->getMessage());
                    $result = ['success' => false, 'title' => 'Error!', 'message' => $e->getMessage()];
                }
            }
        }
        
        // ==============================================
        // AMBIL DATA PESANAN UNTUK DITAMPILKAN
        // ==============================================
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.pemilik_id, u.nama as pemilik_nama, u.no_hp as pemilik_hp
                FROM pesanan p
                JOIN kapal k ON p.kapal_id = k.id
                JOIN users u ON k.pemilik_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
                header("Location: ?page=wisatawan&action=riwayat");
                exit;
            }
            
            // CEK APAKAH SUDAH ADA CLAIM SEBELUMNYA
            try {
                $stmt = $this->pdo->prepare("SELECT id, status_claim FROM claim_pengembalian WHERE pesanan_id = ?");
                $stmt->execute([$pesanan_id]);
                $existingClaim = $stmt->fetch(PDO::FETCH_ASSOC);
            } catch (Exception $e) {
                $existingClaim = null;
            }
            
            if ($existingClaim) {
                if ($existingClaim['status_claim'] == 'pending') {
                    $claimMessage = '⏳ Claim Anda sedang diproses. Mohon tunggu.';
                } elseif ($existingClaim['status_claim'] == 'diterima') {
                    $claimMessage = '✅ Claim Anda sudah diterima. Dana akan dikembalikan.';
                } elseif ($existingClaim['status_claim'] == 'ditolak') {
                    $claimMessage = '❌ Claim Anda ditolak. Silakan hubungi admin.';
                }
                $canClaim = false;
            } else {
                // CEK SYARAT CLAIM
                $canClaim = false;
                $claimMessage = '';
                
                $isCompleted = ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai');
                $isConfirmed = ($pesanan['status_pesanan'] == 'confirmed' || $pesanan['status_pesanan'] == 'dikonfirmasi');
                $isPaid = ($pesanan['status_pembayaran'] == 'lunas');
                $isCancelled = ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan');
                $isDijemput = !empty($pesanan['waktu_jemput_aktual']);
                $claimStatus = $pesanan['status_claim'] ?? 'tidak';
                
                if ($isCompleted) {
                    $claimMessage = '🏁 Pesanan sudah selesai. Tidak dapat mengajukan claim.';
                } elseif ($isCancelled && $claimStatus != 'menunggu' && $claimStatus != 'diterima' && $claimStatus != 'ditolak') {
                    $canClaim = true;
                    $claimMessage = '✅ Pesanan sudah dibatalkan. Anda berhak mengajukan claim pengembalian dana.';
                } elseif ($isConfirmed && $isPaid && !$isDijemput) {
                    $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
                    $now = new DateTime();
                    
                    $waktuJemputRencana = !empty($pesanan['waktu_jemput_rencana']) 
                        ? DateTime::createFromFormat('H:i:s', $pesanan['waktu_jemput_rencana']) 
                        : new DateTime('08:00:00');
                    
                    $batasWaktuJemput = clone $tanggalBerangkat;
                    $batasWaktuJemput->setTime(
                        $waktuJemputRencana->format('H'),
                        $waktuJemputRencana->format('i'),
                        $waktuJemputRencana->format('s')
                    );
                    $batasWaktuJemput->modify('+2 hours');
                    
                    $isTerlambat = ($now > $batasWaktuJemput);
                    $isTanggalLewat = ($tanggalBerangkat < $now);
                    
                    if ($isTerlambat && !$isDijemput) {
                        $canClaim = true;
                        $claimMessage = '✅ Supir terlambat lebih dari 2 jam. Anda berhak mengajukan claim.';
                    } elseif ($isTanggalLewat && !$isDijemput) {
                        $canClaim = true;
                        $claimMessage = '✅ Tanggal keberangkatan sudah lewat dan Anda tidak dijemput.';
                    } else {
                        $claimMessage = '⏳ Menunggu waktu jemput. Jika supir terlambat > 2 jam, Anda bisa claim.';
                    }
                } elseif ($claimStatus == 'menunggu') {
                    $claimMessage = '⏳ Claim Anda sedang diproses. Mohon tunggu.';
                } elseif ($claimStatus == 'diterima') {
                    $claimMessage = '✅ Claim Anda sudah diterima. Dana akan dikembalikan.';
                } elseif ($claimStatus == 'ditolak') {
                    $claimMessage = '❌ Claim Anda ditolak. Silakan hubungi admin.';
                } elseif (!$isConfirmed) {
                    $claimMessage = '⚠️ Pesanan belum dikonfirmasi oleh supir.';
                } elseif (!$isPaid) {
                    $claimMessage = '⚠️ Pembayaran belum lunas.';
                } elseif ($isDijemput) {
                    $claimMessage = '✅ Anda sudah dijemput oleh supir.';
                } else {
                    $claimMessage = '⚠️ Syarat claim belum terpenuhi.';
                }
            }
            
            // LOAD VIEW
            $this->loadView('ajukan_claim', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'canClaim' => $canClaim ?? false,
                'claimMessage' => $claimMessage ?? 'Syarat claim belum terpenuhi.',
                'result' => $result,
                'activeMenu' => 'riwayatPesanan'
            ]);
            
        } catch (Exception $e) {
            error_log("ERROR ajukanClaim: " . $e->getMessage());
            $_SESSION['flash_error'] = 'Error: ' . $e->getMessage();
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
    }
    
    /**
     * PROSES CLAIM - Menyimpan pengajuan claim ke database
     * URL: ?page=wisatawan&action=prosesClaim
     * Method: POST
     * DIPERBAIKI - PASTI TERSIMPAN!
     */
    public function prosesClaim() {
        // 🔥 DEBUG - Tulis ke error log
        error_log("=== PROSES CLAIM DIPANGGIL ===");
        error_log("Method: " . $_SERVER['REQUEST_METHOD']);
        error_log("POST: " . print_r($_POST, true));
        error_log("SESSION user_id: " . ($_SESSION['user_id'] ?? 'TIDAK ADA'));
        
        // 1. CEK LOGIN
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            error_log("ERROR: User tidak login atau bukan wisatawan");
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header("Location: ?page=login");
            exit;
        }
        
        // 2. CEK METHOD POST
        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            error_log("ERROR: Bukan method POST, method: " . $_SERVER['REQUEST_METHOD']);
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        // 3. AMBIL DATA
        $user_id = $_SESSION['user_id'];
        $pesanan_id = (int) ($_POST['pesanan_id'] ?? 0);
        $alasan = trim($_POST['alasan'] ?? '');
        $deskripsi = trim($_POST['deskripsi'] ?? '');
        
        error_log("Data: pesanan_id=$pesanan_id, alasan=$alasan, deskripsi=$deskripsi");
        
        // 4. VALIDASI
        if ($pesanan_id <= 0) {
            error_log("ERROR: ID pesanan tidak valid");
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        if (empty($alasan)) {
            error_log("ERROR: Alasan kosong");
            $_SESSION['flash_error'] = "Silakan pilih alasan claim.";
            header("Location: ?page=wisatawan&action=ajukanClaim&pesanan_id=" . $pesanan_id);
            exit;
        }
        
        if (empty($deskripsi) || strlen($deskripsi) < 10) {
            error_log("ERROR: Deskripsi terlalu pendek: " . strlen($deskripsi));
            $_SESSION['flash_error'] = "Deskripsi minimal 10 karakter.";
            header("Location: ?page=wisatawan&action=ajukanClaim&pesanan_id=" . $pesanan_id);
            exit;
        }
        
        try {
            // 5. CEK PESANAN
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.pemilik_id, u.nama as wisatawan_nama, u.no_hp as wisatawan_hp
                FROM pesanan p
                JOIN kapal k ON p.kapal_id = k.id
                JOIN users u ON p.user_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                error_log("ERROR: Pesanan tidak ditemukan untuk user_id=$user_id, pesanan_id=$pesanan_id");
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            error_log("Pesanan ditemukan: " . $pesanan['kode_pesanan']);
            
            // 6. CEK APAKAH SUDAH ADA CLAIM
            $stmt = $this->pdo->prepare("SELECT id FROM claim_pengembalian WHERE pesanan_id = ?");
            $stmt->execute([$pesanan_id]);
            if ($stmt->rowCount() > 0) {
                error_log("ERROR: Claim sudah ada untuk pesanan_id=$pesanan_id");
                throw new Exception('Claim sudah diajukan untuk pesanan ini.');
            }
            
            // 7. CEK SYARAT CLAIM
            $isCancelled = ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan');
            $isConfirmed = ($pesanan['status_pesanan'] == 'confirmed' || $pesanan['status_pesanan'] == 'dikonfirmasi');
            $isPaid = ($pesanan['status_pembayaran'] == 'lunas');
            $isDijemput = !empty($pesanan['waktu_jemput_aktual']);
            
            $canProceed = false;
            
            if ($isCancelled) {
                $canProceed = true;
                error_log("Claim: Pesanan sudah dibatalkan, proceed");
            } elseif ($isConfirmed && $isPaid && !$isDijemput) {
                $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
                $now = new DateTime();
                
                $waktuJemputRencana = !empty($pesanan['waktu_jemput_rencana']) 
                    ? DateTime::createFromFormat('H:i:s', $pesanan['waktu_jemput_rencana']) 
                    : new DateTime('08:00:00');
                
                $batasWaktuJemput = clone $tanggalBerangkat;
                $batasWaktuJemput->setTime(
                    $waktuJemputRencana->format('H'),
                    $waktuJemputRencana->format('i'),
                    $waktuJemputRencana->format('s')
                );
                $batasWaktuJemput->modify('+2 hours');
                
                $isTerlambat = ($now > $batasWaktuJemput);
                $isTanggalLewat = ($tanggalBerangkat < $now);
                
                if ($isTerlambat || $isTanggalLewat) {
                    $canProceed = true;
                    error_log("Claim: Telat > 2 jam atau tanggal lewat, proceed");
                } else {
                    error_log("Claim: Belum telat, sekarang=" . $now->format('Y-m-d H:i:s') . ", batas=" . $batasWaktuJemput->format('Y-m-d H:i:s'));
                    throw new Exception('Belum melewati batas waktu 2 jam. Silakan tunggu.');
                }
            } else {
                error_log("Claim: Syarat tidak terpenuhi. status_pesanan=" . $pesanan['status_pesanan'] . ", isPaid=" . ($isPaid ? 'yes' : 'no') . ", isDijemput=" . ($isDijemput ? 'yes' : 'no'));
                throw new Exception('Syarat claim tidak terpenuhi.');
            }
            
            if (!$canProceed) {
                throw new Exception('Syarat claim tidak terpenuhi.');
            }
            
            // 8. 🔥 SIMPAN CLAIM KE DATABASE
            $fullAlasan = $alasan . " - " . $deskripsi;
            
            $this->pdo->beginTransaction();
            
            $stmt = $this->pdo->prepare("
                INSERT INTO claim_pengembalian (pesanan_id, wisatawan_id, alasan_claim, status_claim, tanggal_claim) 
                VALUES (?, ?, ?, 'pending', NOW())
            ");
            $result = $stmt->execute([$pesanan_id, $user_id, $fullAlasan]);
            
            if (!$result) {
                $errorInfo = $stmt->errorInfo();
                error_log("ERROR Insert claim: " . print_r($errorInfo, true));
                throw new Exception('Gagal menyimpan claim: ' . $errorInfo[2]);
            }
            
            $claimId = $this->pdo->lastInsertId();
            error_log("Claim berhasil disimpan dengan ID: " . $claimId);
            
            // 9. UPDATE STATUS PESANAN
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET status_claim = 'menunggu', 
                    tanggal_claim = NOW() 
                WHERE id = ?
            ");
            $stmt->execute([$pesanan_id]);
            
            $this->pdo->commit();
            
            error_log("Transaction committed, claim saved!");
            
            // 10. 🔥 REDIRECT KE STATUS PESANAN
            $_SESSION['flash_success'] = "✅ Claim berhasil diajukan! Menunggu verifikasi admin.";
            header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
            exit;
            
        } catch (Exception $e) {
            if (isset($this->pdo) && $this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            error_log("ERROR prosesClaim: " . $e->getMessage());
            error_log("ERROR Trace: " . $e->getTraceAsString());
            $_SESSION['flash_error'] = "❌ " . $e->getMessage();
            header("Location: ?page=wisatawan&action=ajukanClaim&pesanan_id=" . $pesanan_id);
            exit;
        }
    }
    
    // ================================================================
    // 🔥 RESCHEDULE - UBAH JADWAL (HANYA TANGGAL) - DIPERBAIKI
    // ================================================================
    
    /**
     * HALAMAN RESCHEDULE - Tampilan form reschedule
     * URL: ?page=wisatawan&action=reschedule&id=XXX
     */
    public function reschedule() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        $_SESSION['nama'] = $user['nama'];
        $_SESSION['foto_profil'] = $user['foto_profil'];
        $_SESSION['no_hp'] = $user['no_hp'];
        $_SESSION['email'] = $user['email'];
        $unreadCount = $this->getUnreadCount($user_id);
        
        // Ambil data pesanan
        try {
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.pemilik_id,
                       u.nama as supir_nama, u.no_hp as supir_hp
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                JOIN users u ON k.pemilik_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $pesanan = null;
        }
        
        if (!$pesanan) {
            $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        // ==============================================
        // CEK APAKAH BISA RESCHEDULE
        // ==============================================
        $canReschedule = false;
        $errorMessage = '';
        
        // Cek apakah pesanan sudah dikonfirmasi
        if ($pesanan['status_pesanan'] != 'confirmed' && $pesanan['status_pesanan'] != 'dikonfirmasi') {
            $errorMessage = '⚠️ Pesanan belum diverifikasi oleh supir kapal.';
        } 
        // Cek status pembayaran
        elseif ($pesanan['status_pembayaran'] != 'lunas') {
            $errorMessage = '⚠️ Pembayaran belum lunas. Silakan selesaikan pembayaran terlebih dahulu.';
        } 
        // Cek apakah pesanan sudah selesai
        elseif ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai') {
            $errorMessage = '⚠️ Pesanan sudah selesai. Tidak dapat mengubah jadwal.';
        } 
        // Cek apakah pesanan dibatalkan
        elseif ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan') {
            $errorMessage = '⚠️ Pesanan sudah dibatalkan.';
        } 
        // Cek status reschedule
        elseif ($pesanan['reschedule_status'] == 'menunggu' || $pesanan['reschedule_status'] == 'pending') {
            $errorMessage = '⏳ Pengajuan perubahan jadwal sedang diproses. Mohon tunggu.';
        } 
        elseif ($pesanan['reschedule_status'] == 'disetujui' || $pesanan['reschedule_status'] == 'approved') {
            $errorMessage = '✅ Perubahan jadwal sudah disetujui. Silakan cek jadwal baru.';
        } 
        else {
            // Cek tanggal keberangkatan
            $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
            $now = new DateTime();
            $interval = $now->diff($tanggalBerangkat);
            $daysLeft = (int)$interval->format('%r%a');
            
            if ($tanggalBerangkat < $now) {
                $errorMessage = '⚠️ Tanggal keberangkatan sudah lewat. Tidak dapat mengubah jadwal.';
            } elseif ($daysLeft < 1 && $daysLeft >= 0) {
                $errorMessage = '⚠️ Perubahan jadwal harus diajukan minimal 1 hari sebelum keberangkatan.';
            } else {
                $canReschedule = true;
            }
        }
        
        // Ambil daftar rute untuk kapal ini (hanya untuk informasi)
        try {
            $stmt = $this->pdo->prepare("
                SELECT id, tujuan, harga_jual 
                FROM kapal_rute 
                WHERE kapal_id = ? 
                ORDER BY harga_jual ASC
            ");
            $stmt->execute([$pesanan['kapal_id']]);
            $ruteList = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $ruteList = [];
        }
        
        $this->loadView('reschedule', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'pesanan' => $pesanan,
            'ruteList' => $ruteList,
            'canReschedule' => $canReschedule,
            'errorMessage' => $errorMessage,
            'activeMenu' => 'riwayatPesanan'
        ]);
    }
    
    /**
     * PROSES RESCHEDULE - Simpan pengajuan reschedule
     * HANYA MENGUBAH TANGGAL - DESTINASI TIDAK DIUBAH
     * URL: ?page=wisatawan&action=prosesReschedule
     * Method: POST
     */
    public function prosesReschedule() {
        // Cek method POST
        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        
        if (!$user) {
            session_destroy();
            header("Location: ?page=login");
            exit;
        }
        
        // Ambil data POST
        $pesanan_id = (int) ($_POST['pesanan_id'] ?? 0);
        $tanggal_baru = trim($_POST['tanggal_baru'] ?? '');
        $alasan = trim($_POST['alasan'] ?? '');
        
        // ==============================================
        // VALIDASI - HANYA TANGGAL DAN ALASAN
        // DESTINASI TIDAK DIVALIDASI
        // ==============================================
        $errors = [];
        
        // Validasi ID pesanan
        if (empty($pesanan_id) || $pesanan_id <= 0) {
            $errors[] = "ID pesanan tidak valid.";
        }
        
        // Validasi tanggal baru
        if (empty($tanggal_baru)) {
            $errors[] = "Tanggal baru harus diisi.";
        } else {
            // Validasi format tanggal
            $tanggalObj = DateTime::createFromFormat('Y-m-d', $tanggal_baru);
            if (!$tanggalObj) {
                $errors[] = "Format tanggal tidak valid.";
            } else {
                // Validasi tanggal minimal H+2 dan maksimal 30 hari
                $now = new DateTime();
                $minDate = clone $now;
                $minDate->modify('+2 days');
                $maxDate = clone $now;
                $maxDate->modify('+30 days');
                
                if ($tanggalObj < $minDate) {
                    $errors[] = "Tanggal minimal H+2 dari hari ini.";
                } elseif ($tanggalObj > $maxDate) {
                    $errors[] = "Tanggal maksimal 30 hari ke depan.";
                }
            }
        }
        
        // Validasi alasan
        if (empty($alasan)) {
            $errors[] = "Alasan perubahan jadwal wajib diisi.";
        } elseif (strlen($alasan) < 10) {
            $errors[] = "Alasan minimal 10 karakter.";
        }
        
        // TIDAK ADA VALIDASI DESTINASI
        
        // Jika ada error, redirect kembali
        if (!empty($errors)) {
            $_SESSION['flash_error'] = implode(' ', $errors);
            header("Location: ?page=wisatawan&action=reschedule&id=" . $pesanan_id);
            exit;
        }
        
        try {
            // ==============================================
            // CEK PESANAN
            // ==============================================
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, k.pemilik_id,
                       u.nama as supir_nama, u.no_hp as supir_hp
                FROM pesanan p 
                JOIN kapal k ON p.kapal_id = k.id 
                JOIN users u ON k.pemilik_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                $_SESSION['flash_error'] = "Pesanan tidak ditemukan.";
                header("Location: ?page=wisatawan&action=riwayat");
                exit;
            }
            
            // ==============================================
            // CEK APAKAH BISA RESCHEDULE
            // ==============================================
            if ($pesanan['status_pesanan'] != 'confirmed' && $pesanan['status_pesanan'] != 'dikonfirmasi') {
                throw new Exception('Pesanan belum diverifikasi oleh supir kapal.');
            }
            
            if ($pesanan['status_pembayaran'] != 'lunas') {
                throw new Exception('Pembayaran belum lunas.');
            }
            
            if ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai') {
                throw new Exception('Pesanan sudah selesai.');
            }
            
            if ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan') {
                throw new Exception('Pesanan sudah dibatalkan.');
            }
            
            // Cek status reschedule sebelumnya
            if ($pesanan['reschedule_status'] == 'menunggu' || $pesanan['reschedule_status'] == 'pending') {
                throw new Exception('Pengajuan perubahan jadwal sedang diproses.');
            }
            
            if ($pesanan['reschedule_status'] == 'disetujui' || $pesanan['reschedule_status'] == 'approved') {
                throw new Exception('Perubahan jadwal sudah disetujui.');
            }
            
            // Cek tanggal
            $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
            $now = new DateTime();
            $daysLeft = $now->diff($tanggalBerangkat)->days;
            
            if ($tanggalBerangkat < $now) {
                throw new Exception('Tanggal keberangkatan sudah lewat.');
            }
            
            if ($daysLeft < 1) {
                throw new Exception('Perubahan jadwal harus diajukan minimal 1 hari sebelum keberangkatan.');
            }
            
            // ==============================================
            // CEK KETERSEDIAAN KAPAL PADA TANGGAL BARU
            // ==============================================
            $isAvailable = $this->cekKetersediaanKapal($pesanan['kapal_id'], $tanggal_baru);
            if (!$isAvailable) {
                throw new Exception('Kapal sudah dipesan untuk tanggal ' . date('d/m/Y', strtotime($tanggal_baru)) . '. Silakan pilih tanggal lain.');
            }
            
            // ==============================================
            // 🔥 UPDATE PESANAN - HANYA TANGGAL
            // DESTINASI TIDAK DIUBAH
            // ==============================================
            // Cek apakah kolom reschedule_fields ada
            $columns = $this->getTableColumns('pesanan');
            
            // Update reschedule_status
            $sql = "UPDATE pesanan SET 
                    reschedule_status = 'menunggu',
                    reschedule_tanggal_baru = ?,
                    reschedule_alasan = ?
            ";
            
            // Tambahkan reschedule_tanggal_ajuan jika kolom ada
            if (in_array('reschedule_tanggal_ajuan', $columns)) {
                $sql .= ", reschedule_tanggal_ajuan = NOW()";
            }
            
            $sql .= " WHERE id = ?";
            
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([$tanggal_baru, $alasan, $pesanan_id]);
            
            // ================================================================
            // 🔥 SIMPAN KE TABEL RESCHEDULE_REQUESTS (JIKA ADA)
            // ================================================================
            try {
                // Cek apakah tabel reschedule_requests ada
                $stmt = $this->pdo->query("SHOW TABLES LIKE 'reschedule_requests'");
                if ($stmt->rowCount() > 0) {
                    // Cek apakah sudah ada request sebelumnya
                    $stmt = $this->pdo->prepare("
                        SELECT id FROM reschedule_requests 
                        WHERE pesanan_id = ? AND status = 'pending'
                    ");
                    $stmt->execute([$pesanan_id]);
                    
                    if ($stmt->rowCount() == 0) {
                        $stmt = $this->pdo->prepare("
                            INSERT INTO reschedule_requests 
                            (pesanan_id, user_id, tanggal_lama, tanggal_baru, alasan, status, created_at) 
                            VALUES (?, ?, ?, ?, ?, 'pending', NOW())
                        ");
                        $stmt->execute([
                            $pesanan_id,
                            $user_id,
                            $pesanan['tanggal_berangkat'],
                            $tanggal_baru,
                            $alasan
                        ]);
                    }
                }
            } catch (Exception $e) {
                // Tabel tidak ada, lanjutkan
                error_log("Tabel reschedule_requests tidak ada: " . $e->getMessage());
            }
            
            // ================================================================
            // 🔥 KIRIM NOTIFIKASI KE SUPIR
            // ================================================================
            require_once __DIR__ . '/../config/fonnte.php';
            
            $base_url = "http://" . $_SERVER['HTTP_HOST'] . "/reservasi-kapal-wisata";
            
            // Notifikasi WhatsApp ke supir
            if (!empty($pesanan['supir_hp'])) {
                $wa_msg = "
📋 *PENGAJUAN PERUBAHAN JADWAL* 📋

Halo *{$pesanan['supir_nama']}*,

Wisatawan *{$pesanan['nama_lengkap']}* mengajukan perubahan jadwal.

📌 Kode Pesanan: *{$pesanan['kode_pesanan']}*
⛵ Kapal: {$pesanan['nama_kapal']}

📅 Tanggal Lama: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "
📅 Tanggal Baru: " . date('d/m/Y', strtotime($tanggal_baru)) . "

📝 Alasan: {$alasan}

🔗 Segera proses permintaan ini:
" . $base_url . "/?page=supir&action=kelolaPesanan

⚠️ Jika tidak merespon dalam 24 jam, permintaan akan otomatis disetujui.
";
                sendWhatsApp($pesanan['supir_hp'], $wa_msg);
            }
            
            // Notifikasi di aplikasi untuk supir
            if (!empty($pesanan['pemilik_id'])) {
                try {
                    $stmt = $this->pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                        VALUES (?, ?, ?, ?, 0, NOW())
                    ");
                    $title = "📋 Pengajuan Perubahan Jadwal";
                    $msg = "Wisatawan {$pesanan['nama_lengkap']} mengajukan perubahan jadwal untuk pesanan {$pesanan['kode_pesanan']}.";
                    $stmt->execute([$pesanan['pemilik_id'], $title, $msg, $pesanan_id]);
                } catch (Exception $e) {
                    // Ignore
                }
            }
            
            // Notifikasi untuk admin
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                    VALUES (1, ?, ?, ?, 0, NOW())
                ");
                $title = "📋 Pengajuan Perubahan Jadwal";
                $msg = "Wisatawan {$pesanan['nama_lengkap']} mengajukan perubahan jadwal untuk pesanan {$pesanan['kode_pesanan']}.";
                $stmt->execute([$title, $msg, $pesanan_id]);
            } catch (Exception $e) {
                // Ignore
            }
            
            $_SESSION['flash_success'] = "✅ Pengajuan perubahan jadwal berhasil dikirim! Menunggu persetujuan supir kapal.";
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = "❌ Gagal mengajukan perubahan: " . $e->getMessage();
        }
        
        header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
        exit;
    }
    
    // ================================================================
    // 🔥 SELESAIKAN PERJALANAN - OLEH WISATAWAN
    // ================================================================
    
    /**
     * SELESAIKAN PERJALANAN - Wisatawan menyelesaikan perjalanan
     * Dana otomatis dicairkan ke supir
     */
    public function selesaikanPerjalanan() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header('Location: ?page=wisatawan&action=login');
            exit;
        }
        
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
        
        $pesanan_id = (int)$_POST['pesanan_id'];
        $wisatawan_id = (int)$_SESSION['user_id'];
        
        try {
            // 🔥 AMBIL DATA PESANAN
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.pemilik_id, k.nama_kapal, u.nama as wisatawan_nama, u.no_hp as wisatawan_hp
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                LEFT JOIN users u ON p.user_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $wisatawan_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // 🔥 CEK STATUS PESANAN (HARUS CONFIRMED)
            if ($pesanan['status_pesanan'] != 'confirmed' && $pesanan['status_pesanan'] != 'dikonfirmasi') {
                throw new Exception('Pesanan dengan status ' . $pesanan['status_pesanan'] . ' tidak bisa diselesaikan.');
            }
            
            // 🔥 CEK STATUS PEMBAYARAN (HARUS LUNAS)
            if ($pesanan['status_pembayaran'] != 'lunas') {
                throw new Exception('Pembayaran belum lunas. Tidak bisa menyelesaikan perjalanan.');
            }
            
            // 🔥 CEK APAKAH SUDAH DICLAIM
            if ($pesanan['status_claim'] == 'diterima') {
                throw new Exception('Pesanan ini sedang dalam proses claim. Tidak bisa diselesaikan.');
            }
            
            if ($pesanan['status_claim'] == 'menunggu') {
                throw new Exception('Pesanan ini sedang dalam proses claim. Tunggu keputusan admin.');
            }
            
            // 🔥 CEK APAKAH SUDAH CAIR
            if ($pesanan['status_pencairan'] == 'cair') {
                throw new Exception('Dana sudah dicairkan. Perjalanan sudah selesai.');
            }
            
            // ==============================================
            // 🔥 UPDATE STATUS PESANAN
            // ==============================================
            // Cek kolom yang ada
            $columns = $this->getTableColumns('pesanan');
            
            $sql = "UPDATE pesanan SET 
                    status_pesanan = 'completed'";
            
            if (in_array('status_pencairan', $columns)) {
                $sql .= ", status_pencairan = 'proses'";
            }
            
            if (in_array('tanggal_selesai', $columns)) {
                $sql .= ", tanggal_selesai = NOW()";
            }
            
            $sql .= " WHERE id = ?";
            
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([$pesanan_id]);
            
            // ==============================================
            // 🔥 HITUNG KOMISI DAN DANA SUPIR (JIKA BELUM ADA)
            // ==============================================
            if ($pesanan['komisi_admin'] == 0 && $pesanan['nominal_diterima_supir'] == 0) {
                $persen_komisi = 10; // 10% default
                $komisi = round($pesanan['total_harga'] * $persen_komisi / 100);
                $diterima_supir = $pesanan['total_harga'] - $komisi;
                
                $stmt = $this->pdo->prepare("
                    UPDATE pesanan
                    SET komisi_admin = ?,
                        nominal_diterima_supir = ?
                    WHERE id = ?
                ");
                $stmt->execute([$komisi, $diterima_supir, $pesanan_id]);
            }
            
            // ==============================================
            // 🔥 KIRIM NOTIFIKASI KE SUPIR (SUPIR KAPAL)
            // ==============================================
            if ($pesanan['pemilik_id']) {
                try {
                    $message = "✅ Perjalanan telah diselesaikan oleh wisatawan!\n\n" .
                               "📌 Kode Pesanan: {$pesanan['kode_pesanan']}\n" .
                               "👤 Wisatawan: {$pesanan['wisatawan_nama']}\n" .
                               "⛵ Kapal: {$pesanan['nama_kapal']}\n" .
                               "📅 Tanggal: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "\n" .
                               "💰 Total: Rp " . number_format($pesanan['total_harga'], 0, ',', '.') . "\n" .
                               "💳 Diterima Supir: Rp " . number_format($pesanan['nominal_diterima_supir'] ?? 0, 0, ',', '.') . "\n\n" .
                               "📌 Dana akan dicairkan.";
                    
                    $stmt = $this->pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, booking_id) 
                        VALUES (?, '✅ Perjalanan Selesai - Dana Siap Cair', ?, ?)
                    ");
                    $stmt->execute([$pesanan['pemilik_id'], $message, $pesanan_id]);
                } catch (Exception $e) {
                    // Ignore
                }
            }
            
            // ==============================================
            // 🔥 KIRIM NOTIFIKASI KE WISATAWAN
            // ==============================================
            try {
                $message_wisatawan = "✅ Perjalanan Anda telah diselesaikan!\n\n" .
                                     "📌 Kode Pesanan: {$pesanan['kode_pesanan']}\n" .
                                     "⛵ Kapal: {$pesanan['nama_kapal']}\n" .
                                     "📅 Tanggal: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "\n\n" .
                                     "📌 Terima kasih telah menggunakan layanan kami!";
                
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id) 
                    VALUES (?, '✅ Perjalanan Selesai - Terima Kasih!', ?, ?)
                ");
                $stmt->execute([$wisatawan_id, $message_wisatawan, $pesanan_id]);
            } catch (Exception $e) {
                // Ignore
            }
            
            // ==============================================
            // 🔥 KIRIM WHATSAPP KE SUPIR
            // ==============================================
            try {
                require_once __DIR__ . '/../config/fonnte.php';
                
                // Ambil no HP supir
                $stmt = $this->pdo->prepare("SELECT no_hp FROM users WHERE id = ?");
                $stmt->execute([$pesanan['pemilik_id']]);
                $supir = $stmt->fetch(PDO::FETCH_ASSOC);
                
                if ($supir && !empty($supir['no_hp'])) {
                    $wa_msg = "
🛳️ *PERJALANAN SELESAI* 🛳️

Halo,

Perjalanan untuk pesanan *{$pesanan['kode_pesanan']}* telah diselesaikan oleh wisatawan.

👤 Wisatawan: {$pesanan['wisatawan_nama']}
⛵ Kapal: {$pesanan['nama_kapal']}
📅 Tanggal: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "
💰 Total: Rp " . number_format($pesanan['total_harga'], 0, ',', '.') . "
💳 Diterima: Rp " . number_format($pesanan['nominal_diterima_supir'] ?? 0, 0, ',', '.') . "

📌 Dana akan dicairkan dalam 1-3 hari kerja.

Terima kasih! 🌊
";
                    sendWhatsApp($supir['no_hp'], $wa_msg);
                }
            } catch (Exception $e) {
                // Ignore
            }
            
            $_SESSION['flash_success'] = '✅ Perjalanan berhasil diselesaikan!';
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = '❌ Gagal menyelesaikan perjalanan: ' . $e->getMessage();
        }
        
        header('Location: ?page=wisatawan&action=status&id=' . $pesanan_id);
        exit;
    }
    
    /**
     * BATAL OTOMATIS - Wisatawan membatalkan karena supir tidak datang
     * URL: ?page=wisatawan&action=batalOtomatis
     * Method: POST
     */
    public function batalOtomatis() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        $pesanan_id = (int) ($_POST['pesanan_id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=riwayat");
            exit;
        }
        
        try {
            // Cek pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.pemilik_id, k.nama_kapal, u.nama as wisatawan_nama, u.no_hp as wisatawan_hp
                FROM pesanan p
                JOIN kapal k ON p.kapal_id = k.id
                JOIN users u ON p.user_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // Cek apakah pesanan sudah selesai
            if ($pesanan['status_pesanan'] == 'completed' || $pesanan['status_pesanan'] == 'selesai') {
                throw new Exception('Pesanan sudah selesai. Tidak dapat dibatalkan.');
            }
            
            // Cek apakah sudah dicancel
            if ($pesanan['status_pesanan'] == 'cancelled' || $pesanan['status_pesanan'] == 'dibatalkan') {
                throw new Exception('Pesanan sudah dibatalkan.');
            }
            
            // Cek apakah sudah dijemput
            if (!empty($pesanan['waktu_jemput_aktual'])) {
                throw new Exception('Anda sudah dijemput oleh supir. Tidak dapat membatalkan.');
            }
            
            // Cek apakah sudah lewat 2 jam
            $tanggalBerangkat = new DateTime($pesanan['tanggal_berangkat']);
            $now = new DateTime();
            
            $waktuJemputRencana = !empty($pesanan['waktu_jemput_rencana']) 
                ? DateTime::createFromFormat('H:i:s', $pesanan['waktu_jemput_rencana']) 
                : new DateTime('08:00:00');
            
            $batasWaktuJemput = clone $tanggalBerangkat;
            $batasWaktuJemput->setTime(
                $waktuJemputRencana->format('H'),
                $waktuJemputRencana->format('i'),
                $waktuJemputRencana->format('s')
            );
            $batasWaktuJemput->modify('+2 hours');
            
            if ($now < $batasWaktuJemput) {
                throw new Exception('Belum melewati batas waktu 2 jam. Silakan tunggu atau hubungi supir.');
            }
            
            // ==============================================
            // UPDATE STATUS PESANAN MENJADI CANCELLED
            // ==============================================
            $alasan = "Pesanan dibatalkan otomatis karena supir tidak menjemput sesuai jadwal (terlambat > 2 jam).";
            
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET status_pesanan = 'cancelled',
                    status_pembatalan = 'dibatalkan_otomatis',
                    tanggal_pembatalan = NOW(),
                    alasan_batal_otomatis = ?,
                    status_claim = 'menunggu'
                WHERE id = ?
            ");
            $stmt->execute([$alasan, $pesanan_id]);
            
            // ==============================================
            // INSERT CLAIM PENGEMBALIAN DANA OTOMATIS
            // ==============================================
            $stmt = $this->pdo->prepare("
                INSERT INTO claim_pengembalian 
                (pesanan_id, wisatawan_id, alasan_claim, status_claim, tanggal_claim) 
                VALUES (?, ?, ?, 'pending', NOW())
            ");
            $stmt->execute([
                $pesanan_id,
                $user_id,
                'Supir tidak menjemput sesuai jadwal (terlambat > 2 jam)'
            ]);
            
            // ==============================================
            // KIRIM NOTIFIKASI
            // ==============================================
            require_once __DIR__ . '/../config/fonnte.php';
            
            $base_url = "http://" . $_SERVER['HTTP_HOST'] . "/reservasi-kapal-wisata";
            
            // Notifikasi ke admin
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                    VALUES (1, '⚠️ Pembatalan Otomatis - Supir Tidak Datang', ?, ?, 0, NOW())
                ");
                $msg = "Pesanan {$pesanan['kode_pesanan']} dibatalkan otomatis karena supir tidak menjemput. Claim dana diajukan.";
                $stmt->execute([$msg, $pesanan_id]);
            } catch (Exception $e) {
                // Ignore
            }
            
            // Notifikasi ke wisatawan
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                    VALUES (?, '✅ Pesanan Dibatalkan - Claim Dana Diajukan', ?, ?, 0, NOW())
                ");
                $msg = "Pesanan {$pesanan['kode_pesanan']} dibatalkan karena supir tidak datang. Claim pengembalian dana sudah diajukan.";
                $stmt->execute([$user_id, $msg, $pesanan_id]);
            } catch (Exception $e) {
                // Ignore
            }
            
            // WhatsApp ke admin
            try {
                $stmt = $this->pdo->query("SELECT no_hp FROM users WHERE role = 'admin' LIMIT 1");
                $admin = $stmt->fetch(PDO::FETCH_ASSOC);
                
                if ($admin && !empty($admin['no_hp'])) {
                    $wa_msg = "
⚠️ *PEMBATALAN OTOMATIS* ⚠️

Pesanan *{$pesanan['kode_pesanan']}* dibatalkan otomatis.

👤 Wisatawan: {$pesanan['wisatawan_nama']}
⛵ Kapal: {$pesanan['nama_kapal']}
📅 Tanggal: " . date('d/m/Y', strtotime($pesanan['tanggal_berangkat'])) . "

📝 Alasan: Supir tidak menjemput sesuai jadwal (terlambat > 2 jam)

💰 Claim pengembalian dana telah diajukan.
🔗 Segera proses claim:
" . $base_url . "/?page=admin&action=claimPengembalian
";
                    sendWhatsApp($admin['no_hp'], $wa_msg);
                }
            } catch (Exception $e) {
                // Ignore
            }
            
            $_SESSION['flash_success'] = "✅ Pesanan berhasil dibatalkan dan claim pengembalian dana telah diajukan. Menunggu verifikasi admin.";
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = "❌ " . $e->getMessage();
        }
        
        header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
        exit;
    }
    
    // ================================================================
    // 🔥 PEMBAYARAN MIDTRANS (menggunakan file pembayaran.php)
    // ================================================================
    
    /**
     * PROSES PEMBAYARAN - Redirect ke Midtrans
     * DIPERBAIKI - Mengirim jumlah yang sesuai (Full atau DP)
     * URL: ?page=wisatawan&action=prosesPembayaran&id=XXX
     */
    public function prosesPembayaran() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header('Location: ?page=wisatawan&action=login');
            exit;
        }
        
        $pesanan_id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = 'Data pesanan tidak valid.';
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
        
        try {
            // Load Midtrans helper
            require_once __DIR__ . '/../helpers/midtrans_helper.php';
            
            // Ambil data pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal, u.nama as wisatawan_nama, u.email, u.no_hp
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                LEFT JOIN users u ON p.user_id = u.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // Cek status pesanan
            if ($pesanan['status_pembayaran'] == 'lunas') {
                $_SESSION['flash_success'] = '✅ Pesanan ini sudah lunas.';
                header('Location: ?page=wisatawan&action=status&id=' . $pesanan_id);
                exit;
            }
            
            // Cek apakah sudah ada token pembayaran
            if (!empty($pesanan['snap_token'])) {
                header('Location: ?page=wisatawan&action=pembayaran&id=' . $pesanan_id);
                exit;
            }
            
            // ==============================================
            // 🔥 TENTUKAN JUMLAH YANG HARUS DIBAYAR
            // ==============================================
            $jenisPembayaran = $pesanan['jenis_pembayaran'] ?? 'full';
            $totalHarga = (int) $pesanan['total_harga'];
            
            // Jika DP, kirim jumlah DP, jika Full kirim total
            if ($jenisPembayaran == 'dp') {
                $jumlahDibayar = (int) ($pesanan['jumlah_dibayar'] ?? ceil($totalHarga * 0.5));
                $grossAmount = $jumlahDibayar;
                $itemName = 'DP 50% Booking Kapal ' . $pesanan['nama_kapal'];
                $sisaPembayaran = (int) ($pesanan['sisa_pembayaran'] ?? ($totalHarga - $jumlahDibayar));
            } else {
                $grossAmount = $totalHarga;
                $itemName = 'Booking Kapal ' . $pesanan['nama_kapal'];
                $sisaPembayaran = 0;
            }
            
            // ==============================================
            // 🔥 BUILD ITEM DETAILS
            // ==============================================
            $itemDetails = [
                [
                    'id' => $pesanan['id'],
                    'price' => $grossAmount,
                    'quantity' => 1,
                    'name' => $itemName
                ]
            ];
            
            // Jika DP, tambahkan info sisa pembayaran sebagai item terpisah (tidak ditagih)
            if ($jenisPembayaran == 'dp' && $sisaPembayaran > 0) {
                $itemDetails[] = [
                    'id' => $pesanan['id'] . '-sisa',
                    'price' => $sisaPembayaran,
                    'quantity' => 1,
                    'name' => 'Sisa Pembayaran (akan dibayar nanti)'
                ];
            }
            
            // Siapkan data untuk Midtrans
            $orderData = [
                'order_id' => $pesanan['kode_pesanan'] . '-' . time(),
                'gross_amount' => $grossAmount,
                'customer_name' => $pesanan['wisatawan_nama'] ?? $pesanan['nama_lengkap'],
                'customer_email' => $pesanan['email'] ?? $_SESSION['email'],
                'customer_phone' => $pesanan['no_hp'] ?? $_SESSION['no_hp'],
                'pesanan_id' => $pesanan_id,
                'kapal_nama' => $pesanan['nama_kapal'],
                'jenis_pembayaran' => $jenisPembayaran,
                'sisa_pembayaran' => $sisaPembayaran,
                'item_details' => $itemDetails
            ];
            
            // Buat transaksi di Midtrans
            $result = createMidtransTransaction($orderData);
            
            if (!$result['success']) {
                throw new Exception($result['error']);
            }
            
            // Simpan snap_token ke database
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET snap_token = ?, 
                    snap_url = ?,
                    metode_pembayaran = 'midtrans',
                    payment_gross_amount = ?
                WHERE id = ?
            ");
            $stmt->execute([
                $result['token'],
                $result['redirect_url'],
                $grossAmount,
                $pesanan_id
            ]);
            
            // Redirect ke halaman pembayaran
            $_SESSION['payment_token'] = $result['token'];
            $_SESSION['payment_order_id'] = $orderData['order_id'];
            $_SESSION['payment_amount'] = $grossAmount;
            
            header('Location: ?page=wisatawan&action=pembayaran&id=' . $pesanan_id);
            exit;
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = 'Gagal memproses pembayaran: ' . $e->getMessage();
            header('Location: ?page=wisatawan&action=status&id=' . $pesanan_id);
            exit;
        }
    }
    
    /**
     * HALAMAN PEMBAYARAN - Tampilkan Snap Midtrans
     * URL: ?page=wisatawan&action=pembayaran&id=XXX
     * FILE: views/wisatawan/pembayaran.php
     */
    public function pembayaran() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header('Location: ?page=wisatawan&action=login');
            exit;
        }
        
        $pesanan_id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = 'Data pesanan tidak valid.';
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
        
        try {
            // Load Midtrans helper untuk setup config
            require_once __DIR__ . '/../helpers/midtrans_helper.php';
            setupMidtrans();
            
            // Ambil data pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal 
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // Cek apakah sudah lunas
            if ($pesanan['status_pembayaran'] == 'lunas') {
                $_SESSION['flash_success'] = '✅ Pembayaran sudah lunas. Terima kasih!';
                header('Location: ?page=wisatawan&action=status&id=' . $pesanan_id);
                exit;
            }
            
            // Cek apakah ada snap_token
            if (empty($pesanan['snap_token'])) {
                // Redirect ke proses pembayaran untuk membuat token
                header('Location: ?page=wisatawan&action=prosesPembayaran&id=' . $pesanan_id);
                exit;
            }
            
            // Load view pembayaran
            $this->loadView('pembayaran', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'snap_token' => $pesanan['snap_token'],
                'client_key' => \Midtrans\Config::$clientKey,
                'activeMenu' => 'riwayatPesanan'
            ]);
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = $e->getMessage();
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
    }
    
    /**
     * PEMBAYARAN SUKSES - Halaman setelah pembayaran berhasil
     * URL: ?page=wisatawan&action=pembayaranSukses&id=XXX
     * FILE: views/wisatawan/pembayaran_sukses.php
     */
    public function pembayaranSukses() {
        $pesanan_id = (int) ($_GET['id'] ?? 0);
        $order_id = $_GET['order_id'] ?? '';
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        // 🔥 UPDATE STATUS JADI LUNAS!
        try {
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET 
                    status_pembayaran = 'lunas',
                    status_pembayaran_admin = 'dikonfirmasi',
                    status_pesanan = 'confirmed',
                    tanggal_bayar = NOW(),
                    tanggal_konfirmasi_pembayaran = NOW()
                WHERE id = ? AND status_pembayaran != 'lunas'
            ");
            $stmt->execute([$pesanan_id]);
            
            if ($stmt->rowCount() > 0) {
                // 🔥 KIRIM NOTIFIKASI KE WISATAWAN
                try {
                    $stmtNotif = $this->pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                        SELECT user_id, '✅ Pembayaran LUNAS', 
                               CONCAT('Pembayaran untuk pesanan ', kode_pesanan, ' telah LUNAS. Perjalanan dikonfirmasi.'),
                               id, 0, NOW()
                        FROM pesanan 
                        WHERE id = ?
                    ");
                    $stmtNotif->execute([$pesanan_id]);
                } catch (Exception $e) {
                    // Notifikasi gagal, lanjutkan
                }
            }
        } catch (Exception $e) {
            // Log error
            error_log("Error update status: " . $e->getMessage());
        }

        try {
            // Ambil data pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }

            $this->loadView('pembayaran_sukses', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'activeMenu' => 'riwayatPesanan'
            ]);

        } catch (Exception $e) {
            $_SESSION['flash_error'] = $e->getMessage();
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
    }
    
    /**
     * PEMBAYARAN PENDING - Halaman pembayaran pending
     * URL: ?page=wisatawan&action=pembayaranPending&id=XXX
     * FILE: views/wisatawan/pembayaran_pending.php
     */
    public function pembayaranPending() {
        $pesanan_id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        try {
            // Ambil data pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.nama_kapal 
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            $this->loadView('pembayaran_pending', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'activeMenu' => 'riwayatPesanan'
            ]);
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = $e->getMessage();
            header('Location: ?page=wisatawan&action=pesananSaya');
            exit;
        }
    }
    
    // ================================================================
    // 🔥 FITUR WITHDRAW (TARIK SALDO)
    // ================================================================
    
    /**
     * HALAMAN TARIK SALDO
     * URL: ?page=wisatawan&action=tarikSaldo
     */
    public function tarikSaldo() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            header("Location: ?page=login");
            exit;
        }
        
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        // Ambil saldo
        $saldo = $this->getSaldo($user_id);
        
        // Ambil riwayat penarikan
        try {
            $stmt = $this->pdo->prepare("
                SELECT * FROM withdraw_saldo 
                WHERE user_id = ? 
                ORDER BY created_at DESC 
                LIMIT 20
            ");
            $stmt->execute([$user_id]);
            $riwayatWithdraw = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $riwayatWithdraw = [];
        }
        
        // Proses withdraw
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $jumlah = (int) ($_POST['jumlah'] ?? 0);
            $bank = trim($_POST['bank'] ?? '');
            $nomor_rekening = trim($_POST['nomor_rekening'] ?? '');
            $nama_pemilik = trim($_POST['nama_pemilik'] ?? '');
            $metode = $_POST['metode'] ?? 'bank';
            
            $errors = [];
            
            if ($jumlah <= 0) {
                $errors[] = "Jumlah penarikan harus lebih dari 0.";
            }
            if ($jumlah > $saldo) {
                $errors[] = "Saldo tidak mencukupi. Saldo Anda: Rp " . number_format($saldo, 0, ',', '.');
            }
            if ($jumlah < 50000) {
                $errors[] = "Minimal penarikan Rp 50.000";
            }
            if (empty($bank)) {
                $errors[] = "Nama bank harus diisi.";
            }
            if (empty($nomor_rekening) || !is_numeric($nomor_rekening) || strlen($nomor_rekening) < 5) {
                $errors[] = "Nomor rekening tidak valid.";
            }
            if (empty($nama_pemilik)) {
                $errors[] = "Nama pemilik rekening harus diisi.";
            }
            
            if (empty($errors)) {
                try {
                    // Cek apakah tabel withdraw_saldo ada
                    try {
                        $stmt = $this->pdo->query("SHOW TABLES LIKE 'withdraw_saldo'");
                        if ($stmt->rowCount() == 0) {
                            // Buat tabel
                            $this->pdo->exec("
                                CREATE TABLE IF NOT EXISTS withdraw_saldo (
                                    id INT AUTO_INCREMENT PRIMARY KEY,
                                    user_id INT NOT NULL,
                                    jumlah INT NOT NULL,
                                    metode ENUM('bank', 'ewallet') DEFAULT 'bank',
                                    bank VARCHAR(50) NULL,
                                    nomor_rekening VARCHAR(50) NULL,
                                    nama_pemilik VARCHAR(100) NULL,
                                    status ENUM('pending', 'proses', 'selesai', 'gagal') DEFAULT 'pending',
                                    bukti_transfer VARCHAR(255) NULL,
                                    alasan_penolakan TEXT NULL,
                                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                                    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
                                    INDEX idx_user (user_id),
                                    INDEX idx_status (status)
                                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
                            ");
                        }
                    } catch (Exception $e) {
                        // Tabel mungkin sudah ada
                    }
                    
                    $this->pdo->beginTransaction();
                    
                    // Insert request withdraw
                    $stmt = $this->pdo->prepare("
                        INSERT INTO withdraw_saldo (user_id, jumlah, metode, bank, nomor_rekening, nama_pemilik, status, created_at) 
                        VALUES (?, ?, ?, ?, ?, ?, 'pending', NOW())
                    ");
                    $stmt->execute([$user_id, $jumlah, $metode, $bank, $nomor_rekening, $nama_pemilik]);
                    
                    // 🔥 KURANGI SALDO (hold sementara)
                    $saldoBaru = $saldo - $jumlah;
                    $stmt = $this->pdo->prepare("UPDATE saldo_wisatawan SET saldo = ? WHERE user_id = ?");
                    $stmt->execute([$saldoBaru, $user_id]);
                    
                    // Simpan riwayat saldo (keluar)
                    try {
                        // Cek apakah kolom tipe ada
                        $stmt = $this->pdo->query("SHOW COLUMNS FROM riwayat_saldo LIKE 'tipe'");
                        $hasTipe = $stmt->rowCount() > 0;
                        
                        if ($hasTipe) {
                            $sql = "INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, tipe, referensi_id) 
                                    VALUES (?, 'keluar', ?, ?, ?, ?, 'withdraw', ?)";
                        } else {
                            $sql = "INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, referensi_id) 
                                    VALUES (?, 'keluar', ?, ?, ?, ?, ?)";
                        }
                        
                        $stmt = $this->pdo->prepare($sql);
                        if ($hasTipe) {
                            $stmt->execute([
                                $user_id,
                                $jumlah,
                                $saldo,
                                $saldoBaru,
                                "Penarikan saldo ke rekening {$bank} - {$nomor_rekening}",
                                $this->pdo->lastInsertId()
                            ]);
                        } else {
                            $stmt->execute([
                                $user_id,
                                $jumlah,
                                $saldo,
                                $saldoBaru,
                                "Penarikan saldo ke rekening {$bank} - {$nomor_rekening}",
                                $this->pdo->lastInsertId()
                            ]);
                        }
                    } catch (Exception $e) {
                        error_log("Error saving riwayat: " . $e->getMessage());
                    }
                    
                    $this->pdo->commit();
                    
                    // Kirim notifikasi ke admin
                    try {
                        $stmt = $this->pdo->prepare("
                            INSERT INTO notifications (user_id, title, message, is_read, created_at) 
                            VALUES (1, '💰 Permintaan Penarikan Saldo', 
                                    'Wisatawan {$user['nama']} meminta penarikan saldo sebesar Rp ' . number_format($jumlah, 0, ',', '.') . ' ke rekening {$bank} - {$nomor_rekening}', 
                                    0, NOW())
                        ");
                        $stmt->execute();
                    } catch (Exception $e) {}
                    
                    $_SESSION['flash_success'] = "✅ Permintaan penarikan saldo berhasil diajukan! Menunggu verifikasi admin.";
                    header("Location: ?page=wisatawan&action=saldo");
                    exit;
                    
                } catch (Exception $e) {
                    if ($this->pdo->inTransaction()) {
                        $this->pdo->rollBack();
                    }
                    error_log("Error tarikSaldo: " . $e->getMessage());
                    $_SESSION['flash_error'] = "❌ Gagal memproses: " . $e->getMessage();
                }
            } else {
                $_SESSION['flash_error'] = implode("<br>", $errors);
            }
            
            header("Location: ?page=wisatawan&action=tarikSaldo");
            exit;
        }
        
        $this->loadView('tarik_saldo', [
            'user_id' => $user_id,
            'user' => $user,
            'unreadCount' => $unreadCount,
            'saldo' => $saldo,
            'riwayatWithdraw' => $riwayatWithdraw,
            'activeMenu' => 'saldo'
        ]);
    }
    
    /**
     * PROSES PEMBAYARAN DENGAN SALDO
     * URL: ?page=wisatawan&action=prosesPembayaranSaldo
     * Method: POST
     */
    public function prosesPembayaranSaldo() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] != 'wisatawan') {
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header("Location: ?page=login");
            exit;
        }
        
        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
            header("Location: ?page=wisatawan&action=pesananSaya");
            exit;
        }
        
        $pesanan_id = (int) ($_POST['pesanan_id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        
        if ($pesanan_id <= 0) {
            $_SESSION['flash_error'] = "ID pesanan tidak valid.";
            header("Location: ?page=wisatawan&action=pesananSaya");
            exit;
        }
        
        try {
            // Ambil data pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, k.pemilik_id, k.nama_kapal
                FROM pesanan p
                JOIN kapal k ON p.kapal_id = k.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$pesanan_id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                throw new Exception('Pesanan tidak ditemukan.');
            }
            
            // Cek status
            if ($pesanan['status_pembayaran'] == 'lunas') {
                throw new Exception('Pesanan sudah lunas.');
            }
            
            // Ambil saldo
            $saldo = $this->getSaldo($user_id);
            $total_harga = (int) $pesanan['total_harga'];
            
            // Cek saldo cukup
            if ($saldo < $total_harga) {
                throw new Exception('Saldo tidak mencukupi. Saldo Anda: Rp ' . number_format($saldo, 0, ',', '.'));
            }
            
            $this->pdo->beginTransaction();
            
            // 🔥 KURANGI SALDO
            $saldoBaru = $saldo - $total_harga;
            $stmt = $this->pdo->prepare("UPDATE saldo_wisatawan SET saldo = ? WHERE user_id = ?");
            $stmt->execute([$saldoBaru, $user_id]);
            
            // Simpan riwayat saldo
            try {
                $stmt = $this->pdo->query("SHOW COLUMNS FROM riwayat_saldo LIKE 'tipe'");
                $hasTipe = $stmt->rowCount() > 0;
                
                if ($hasTipe) {
                    $sql = "INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, tipe, referensi_id) 
                            VALUES (?, 'keluar', ?, ?, ?, ?, 'booking', ?)";
                } else {
                    $sql = "INSERT INTO riwayat_saldo (user_id, jenis, jumlah, saldo_sebelum, saldo_sesudah, keterangan, referensi_id) 
                            VALUES (?, 'keluar', ?, ?, ?, ?, ?)";
                }
                
                $stmt = $this->pdo->prepare($sql);
                if ($hasTipe) {
                    $stmt->execute([
                        $user_id,
                        $total_harga,
                        $saldo,
                        $saldoBaru,
                        "Pembayaran booking pesanan {$pesanan['kode_pesanan']}",
                        $pesanan_id
                    ]);
                } else {
                    $stmt->execute([
                        $user_id,
                        $total_harga,
                        $saldo,
                        $saldoBaru,
                        "Pembayaran booking pesanan {$pesanan['kode_pesanan']}",
                        $pesanan_id
                    ]);
                }
            } catch (Exception $e) {
                error_log("Error saving riwayat: " . $e->getMessage());
            }
            
            // 🔥 UPDATE STATUS PEMBAYARAN
            $stmt = $this->pdo->prepare("
                UPDATE pesanan 
                SET status_pembayaran = 'lunas',
                    status_pesanan = 'confirmed',
                    bayar_dengan_saldo = 'ya',
                    tanggal_bayar = NOW(),
                    tanggal_konfirmasi_pembayaran = NOW(),
                    metode_pembayaran = 'Saldo Aplikasi'
                WHERE id = ?
            ");
            $stmt->execute([$pesanan_id]);
            
            $this->pdo->commit();
            
            // Kirim notifikasi
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                    VALUES (?, '✅ Pembayaran Berhasil', 
                            'Pembayaran dengan saldo sebesar Rp ' . number_format($total_harga, 0, ',', '.') . ' untuk pesanan {$pesanan['kode_pesanan']} berhasil.',
                            ?, 0, NOW())
                ");
                $stmt->execute([$user_id, $pesanan_id]);
                
                // Notifikasi ke supir
                if (!empty($pesanan['pemilik_id'])) {
                    $stmt = $this->pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, booking_id, is_read, created_at) 
                        VALUES (?, '💰 Pembayaran Lunas', 
                                'Wisatawan telah melunasi pesanan {$pesanan['kode_pesanan']} menggunakan saldo aplikasi.',
                                ?, 0, NOW())
                    ");
                    $stmt->execute([$pesanan['pemilik_id'], $pesanan_id]);
                }
            } catch (Exception $e) {}
            
            $_SESSION['flash_success'] = "✅ Pembayaran berhasil menggunakan saldo! Saldo tersisa: Rp " . number_format($saldoBaru, 0, ',', '.');
            header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
            exit;
            
        } catch (Exception $e) {
            if ($this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            $_SESSION['flash_error'] = "❌ " . $e->getMessage();
            header("Location: ?page=wisatawan&action=status&id=" . $pesanan_id);
            exit;
        }
    }
    
    // ================================================================
    // 🔥 DETAIL PESANAN - DITAMBAHKAN
    // ================================================================
    
    /**
     * DETAIL PESANAN - Menampilkan detail satu pesanan
     * URL: ?page=wisatawan&action=detailPesanan&id=XXX
     */
    public function detailPesanan() {
        // Cek login
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'wisatawan') {
            $_SESSION['flash_error'] = 'Anda harus login sebagai wisatawan.';
            header('Location: ?page=wisatawan&action=login');
            exit;
        }
        
        $id = (int) ($_GET['id'] ?? 0);
        $user_id = $_SESSION['user_id'];
        $user = $this->getUserData($user_id);
        $unreadCount = $this->getUnreadCount($user_id);
        
        if ($id <= 0) {
            $_SESSION['flash_error'] = 'ID pesanan tidak valid.';
            header('Location: ?page=wisatawan&action=riwayat');
            exit;
        }
        
        try {
            // Ambil detail pesanan
            $stmt = $this->pdo->prepare("
                SELECT p.*, 
                       u.nama as wisatawan_nama, 
                       u.no_hp as wisatawan_hp,
                       u.email as wisatawan_email,
                       k.nama_kapal,
                       k.pelabuhan_asal,
                       k.pelabuhan_tujuan,
                       k.fasilitas,
                       kr.asal as route_asal,
                       kr.tujuan as route_tujuan,
                       kr.harga_jual as route_harga,
                       u2.nama as pemilik_nama, 
                       u2.no_hp as pemilik_hp
                FROM pesanan p
                LEFT JOIN kapal k ON p.kapal_id = k.id
                LEFT JOIN users u ON p.user_id = u.id
                LEFT JOIN kapal_rute kr ON p.route_id = kr.id
                LEFT JOIN users u2 ON k.pemilik_id = u2.id
                WHERE p.id = ? AND p.user_id = ?
            ");
            $stmt->execute([$id, $user_id]);
            $pesanan = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$pesanan) {
                $_SESSION['flash_error'] = 'Pesanan tidak ditemukan.';
                header('Location: ?page=wisatawan&action=riwayat');
                exit;
            }
            
            // Ambil riwayat notifikasi untuk pesanan ini
            $stmt = $this->pdo->prepare("
                SELECT * FROM notifications 
                WHERE booking_id = ? 
                ORDER BY created_at DESC 
                LIMIT 10
            ");
            $stmt->execute([$id]);
            $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Kirim ke view
            $this->loadView('detail_pesanan', [
                'user_id' => $user_id,
                'user' => $user,
                'unreadCount' => $unreadCount,
                'pesanan' => $pesanan,
                'notifications' => $notifications,
                'activeMenu' => 'riwayatPesanan'
            ]);
            
        } catch (Exception $e) {
            $_SESSION['flash_error'] = 'Error: ' . $e->getMessage();
            header('Location: ?page=wisatawan&action=riwayat');
            exit;
        }
    }
}
?>