<?php
/**
 * customer_booking.php
 * Allows customers to look up, view, and edit their booking by confirmation number + email.
 * Bookings are stored as JSON files in /limo-booking-plugin/bookings/{confirmationNumber}.json
 *
 * Actions handled (POST via fetch):
 *   action=lookup   – find booking by confirmation number + email
 *   action=update   – save edited booking fields
 *   action=cancel   – mark booking as cancelled
 */

define('BOOKINGS_DIR', __DIR__ . '/data/bookings/');

// ---------- PRICING API ----------
if (isset($_GET['price'])) {
    header('Content-Type: application/json');

    $raw  = file_get_contents('php://input');
    $body = json_decode($raw, true);
    if (!$body) { echo json_encode(['error' => 'Invalid request']); exit; }

    $pickup    = trim((string)($body['pickup'] ?? ''));
    $dropoff   = trim((string)($body['dropoff'] ?? ''));
    $stops     = is_array($body['stops'] ?? null) ? array_filter(array_map('trim', $body['stops'])) : [];
    $vehicle   = trim((string)($body['vehicle'] ?? ''));
    $gratuityType  = trim((string)($body['gratuityType'] ?? 'percent'));
    $gratuityValue = (float)($body['gratuityValue'] ?? 20);
    $apiKey    = 'AIzaSyAkGBtQQV3LFrypWxnSl1EutmgyheSwWUc';

    if ($pickup === '' || $dropoff === '') {
        echo json_encode(['error' => 'Pickup and dropoff are required.']); exit;
    }

    // Load vehicle record
    $vehicleRecord = null;
    $vFile = __DIR__ . '/data/vehicles.json';
    if (file_exists($vFile)) {
        $vData = json_decode(file_get_contents($vFile), true);
        if (is_array($vData)) {
            foreach ($vData as $v) {
                if (strtolower(trim($v['name'] ?? '')) === strtolower($vehicle)) {
                    $vehicleRecord = $v; break;
                }
            }
        }
    }
    if (!$vehicleRecord) { echo json_encode(['error' => 'Vehicle not found.']); exit; }

    // Load pricing settings
    $pFile = __DIR__ . '/data/pricing_settings.json';
    $pSettings = ['flat_rate_requires_no_stops' => true, 'stop_fee_enabled' => true, 'stop_fee_amount' => 25, 'stop_fee_type' => 'per_stop'];
    if (file_exists($pFile)) {
        $pd = json_decode(file_get_contents($pFile), true);
        if (is_array($pd)) $pSettings = array_merge($pSettings, $pd);
    }

    // Load flat rates
    $flatRates = [];
    $fFile = __DIR__ . '/data/flat_rates.json';
    if (file_exists($fFile)) {
        $fd = json_decode(file_get_contents($fFile), true);
        if (is_array($fd)) $flatRates = $fd;
    }

    // Helper: call Google Routes API for one leg
    function cb_route_quote($origin, $destination, $apiKey) {
        $payload = [
            'origin'             => ['address' => $origin],
            'destination'        => ['address' => $destination],
            'travelMode'         => 'DRIVE',
            'routingPreference'  => 'TRAFFIC_AWARE',
            'extraComputations'  => ['TOLLS'],
            'routeModifiers'     => ['tollPasses' => ['US_NY_EZPASSNY', 'US_NJ_EZPASSNJ']],
            'languageCode'       => 'en-US',
            'units'              => 'IMPERIAL'
        ];
        $ch = curl_init('https://routes.googleapis.com/directions/v2:computeRoutes');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-Goog-Api-Key: ' . $apiKey,
            'X-Goog-FieldMask: routes.distanceMeters,routes.duration,routes.travelAdvisory.tollInfo'
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if (!$response || $code !== 200) return null;
        $result = json_decode($response, true);
        if (empty($result['routes'][0])) return null;
        $route = $result['routes'][0];
        $dist  = (int)($route['distanceMeters'] ?? 0);
        preg_match('/(\d+)s$/', $route['duration'] ?? '0s', $m);
        $dur   = isset($m[1]) ? (int)$m[1] : 0;
        $tolls = 0.0;
        foreach (($route['travelAdvisory']['tollInfo']['estimatedPrice'] ?? []) as $p) {
            $tolls += (float)($p['units'] ?? 0) + ((float)($p['nanos'] ?? 0) / 1e9);
        }
        return [
            'distanceMiles'   => round($dist / 1609.34, 1),
            'durationMinutes' => round($dur / 60),
            'tollAmount'      => round($tolls, 2),
        ];
    }

    // Helper: check flat rate
    function cb_find_flat_rate($pickup, $dropoff, $vehicleName, $flatRates) {
        $pn = strtolower(trim($pickup));
        $dn = strtolower(trim($dropoff));
        $vn = strtolower(trim($vehicleName));
        foreach ($flatRates as $r) {
            if (isset($r['enabled']) && !$r['enabled']) continue;
            $rv = strtolower(trim($r['vehicle'] ?? ''));
            if ($rv !== '' && $rv !== $vn) continue;
            $from = strtolower(trim($r['from'] ?? ($r['origin'] ?? '')));
            $to   = strtolower(trim($r['to'] ?? ($r['destination'] ?? '')));
            $direct  = (strpos($pn, $from) !== false && strpos($dn, $to) !== false);
            $reverse = !empty($r['allowReverse']) && (strpos($pn, $to) !== false && strpos($dn, $from) !== false);
            if ($direct || $reverse) return (float)($r['amount'] ?? 0);
        }
        return null;
    }

    // Build legs (pickup → stop1 → ... → dropoff)
    $points = array_merge([$pickup], array_values($stops), [$dropoff]);
    $totalMiles = 0; $totalMins = 0; $totalTolls = 0.0;
    foreach (array_keys($points) as $i) {
        if ($i === count($points) - 1) break;
        $leg = cb_route_quote($points[$i], $points[$i + 1], $apiKey);
        if (!$leg) { echo json_encode(['error' => 'Could not calculate route. Please check addresses.']); exit; }
        $totalMiles += $leg['distanceMiles'];
        $totalMins  += $leg['durationMinutes'];
        $totalTolls += $leg['tollAmount'];
    }

    $stopCount = count($stops);

    // Helper: calculate price for one leg
    $calcLegPrice = function($miles, $mins, $legStopCount, $legPickup, $legDropoff) use ($vehicleRecord, $pSettings, $flatRates, $vehicle) {
        $flatRate = null;
        if (!(!empty($pSettings['flat_rate_requires_no_stops']) && $legStopCount > 0)) {
            $flatRate = cb_find_flat_rate($legPickup, $legDropoff, $vehicle, $flatRates);
        }
        if ($flatRate !== null) {
            $price = (float)$flatRate;
            $mode  = 'flat_rate';
        } else {
            $base    = (float)($vehicleRecord['base'] ?? 0);
            $perMile = (float)($vehicleRecord['perMile'] ?? 0);
            $perMin  = (float)($vehicleRecord['perMin'] ?? 0);
            $price   = $base + ($perMile * $miles) + ($perMin * $mins);
            $mode    = 'per_mile';
        }
        $stopFee = 0.0;
        if (!empty($pSettings['stop_fee_enabled']) && $legStopCount > 0) {
            $stopFeeAmt = (float)($pSettings['stop_fee_amount'] ?? 0);
            $stopFee = ($pSettings['stop_fee_type'] === 'per_stop') ? $stopFeeAmt * $legStopCount : $stopFeeAmt;
        }
        return ['price' => round($price, 2), 'stopFee' => round($stopFee, 2), 'mode' => $mode];
    };

    // Trip 1 price
    $trip1 = $calcLegPrice($totalMiles, $totalMins, $stopCount, $pickup, $dropoff);
    $basePrice = $trip1['price'];
    $stopFee   = $trip1['stopFee'];
    $priceMode = $trip1['mode'];

    // ---- ZONE DETECTION (full version with all NYC zones + business rules) ----
    function cb_detect_zone($text) {
        $t = strtolower(trim((string)$text));
        $t = str_replace(['.', ','], ' ', $t);
        $t = preg_replace('/\s+/', ' ', $t);
        if (strpos($t, 'jfk') !== false || strpos($t, 'john f kennedy') !== false || strpos($t, 'kennedy airport') !== false) return 'jfk';
        if (strpos($t, 'lga') !== false || strpos($t, 'laguardia') !== false || strpos($t, 'la guardia') !== false) return 'lga';
        if (strpos($t, 'ewr') !== false || strpos($t, 'newark liberty') !== false || strpos($t, 'newark airport') !== false) return 'ewr';
        if (strpos($t, 'connecticut') !== false || strpos($t, ' ct ') !== false || strpos($t, ', ct') !== false || strpos($t, 'greenwich') !== false || strpos($t, 'stamford') !== false || strpos($t, 'norwalk') !== false || strpos($t, 'bridgeport') !== false || strpos($t, 'fairfield') !== false || strpos($t, 'westport') !== false || strpos($t, 'danbury') !== false || strpos($t, 'new canaan') !== false || strpos($t, 'darien') !== false || strpos($t, 'wilton') !== false || strpos($t, 'milford') !== false || strpos($t, 'trumbull') !== false || preg_match('/\b06\d{3}\b/', $t)) return 'connecticut';
        if (strpos($t, 'new jersey') !== false || strpos($t, ' nj ') !== false || strpos($t, ', nj') !== false || strpos($t, 'newark') !== false || strpos($t, 'jersey city') !== false || strpos($t, 'hoboken') !== false || strpos($t, 'weehawken') !== false || strpos($t, 'union city') !== false || strpos($t, 'bayonne') !== false || strpos($t, 'secaucus') !== false || strpos($t, 'edgewater') !== false || strpos($t, 'fort lee') !== false || strpos($t, 'hackensack') !== false || strpos($t, 'paramus') !== false || strpos($t, 'teaneck') !== false || strpos($t, 'englewood') !== false || strpos($t, 'princeton') !== false || strpos($t, 'trenton') !== false || preg_match('/\b0[67]\d{3}\b/', $t)) return 'new_jersey';
        if (strpos($t, 'westchester') !== false || strpos($t, 'white plains') !== false || strpos($t, 'yonkers') !== false || strpos($t, 'scarsdale') !== false || strpos($t, 'new rochelle') !== false || strpos($t, 'mamaroneck') !== false || strpos($t, 'larchmont') !== false || strpos($t, 'rye') !== false || strpos($t, 'tarrytown') !== false || strpos($t, 'harrison') !== false || strpos($t, 'purchase') !== false || strpos($t, 'armonk') !== false || strpos($t, 'chappaqua') !== false || strpos($t, 'mount vernon') !== false || strpos($t, 'port chester') !== false || strpos($t, 'ossining') !== false || strpos($t, 'peekskill') !== false || preg_match('/\b10(5|6|7|8|9)\d{2}\b/', $t)) return 'westchester';
        if (strpos($t, 'long island') !== false || strpos($t, 'nassau') !== false || strpos($t, 'suffolk') !== false || strpos($t, 'hempstead') !== false || strpos($t, 'garden city') !== false || strpos($t, 'great neck') !== false || strpos($t, 'manhasset') !== false || strpos($t, 'mineola') !== false || strpos($t, 'hicksville') !== false || strpos($t, 'levittown') !== false || strpos($t, 'huntington') !== false || strpos($t, 'commack') !== false || strpos($t, 'smithtown') !== false || strpos($t, 'hauppauge') !== false || strpos($t, 'bay shore') !== false || strpos($t, 'islip') !== false || strpos($t, 'babylon') !== false || strpos($t, 'patchogue') !== false || strpos($t, 'southampton') !== false || strpos($t, 'east hampton') !== false || strpos($t, 'montauk') !== false || preg_match('/\b11[5-9]\d{2}\b/', $t)) return 'long_island';
        if (strpos($t, 'brooklyn') !== false || strpos($t, 'williamsburg') !== false || strpos($t, 'bushwick') !== false || strpos($t, 'crown heights') !== false || strpos($t, 'flatbush') !== false || strpos($t, 'bay ridge') !== false || strpos($t, 'bensonhurst') !== false || strpos($t, 'canarsie') !== false || strpos($t, 'coney island') !== false || strpos($t, 'brighton beach') !== false || strpos($t, 'park slope') !== false || strpos($t, 'cobble hill') !== false || strpos($t, 'dumbo') !== false || strpos($t, 'red hook') !== false || strpos($t, 'sunset park') !== false || strpos($t, 'sheepshead bay') !== false || preg_match('/\b112\d{2}\b/', $t)) return 'brooklyn';
        if (strpos($t, 'queens') !== false || strpos($t, 'flushing') !== false || strpos($t, 'jamaica') !== false || strpos($t, 'astoria') !== false || strpos($t, 'long island city') !== false || strpos($t, 'forest hills') !== false || strpos($t, 'rego park') !== false || strpos($t, 'jackson heights') !== false || strpos($t, 'corona') !== false || strpos($t, 'elmhurst') !== false || strpos($t, 'woodside') !== false || strpos($t, 'bayside') !== false || strpos($t, 'fresh meadows') !== false || strpos($t, 'howard beach') !== false || strpos($t, 'ozone park') !== false || strpos($t, 'richmond hill') !== false || strpos($t, 'kew gardens') !== false || strpos($t, 'rockaway') !== false || preg_match('/\b114\d{2}\b/', $t)) return 'queens';
        if (strpos($t, 'bronx') !== false || strpos($t, 'riverdale') !== false || strpos($t, 'fordham') !== false || strpos($t, 'pelham') !== false || strpos($t, 'mott haven') !== false || strpos($t, 'hunts point') !== false || preg_match('/\b104\d{2}\b/', $t)) return 'bronx';
        if (strpos($t, 'manhattan') !== false || strpos($t, 'new york, ny') !== false || strpos($t, 'new york ny') !== false || strpos($t, ', ny 10') !== false || preg_match('/\b100\d{2}\b/', $t) || preg_match('/\b101\d{2}\b/', $t) || strpos($t, 'midtown') !== false || strpos($t, 'upper east side') !== false || strpos($t, 'upper west side') !== false || strpos($t, 'harlem') !== false || strpos($t, 'tribeca') !== false || strpos($t, 'soho') !== false || strpos($t, 'chelsea') !== false || strpos($t, 'financial district') !== false || strpos($t, 'times square') !== false || strpos($t, 'central park') !== false) return 'manhattan';
        return 'other';
    }

    // Business rule: vehicles based in NYC — outer zone rides always need return tolls
    function cb_determine_toll_mode($originZone, $destZone) {
        // These zones always trigger round-trip tolls — vehicle must return to NYC base
        $alwaysRoundTrip = ['westchester', 'connecticut', 'new_jersey', 'long_island', 'brooklyn', 'queens', 'bronx', 'ewr'];
        // If EITHER endpoint is in an always-round-trip zone, charge both ways
        if (in_array($originZone, $alwaysRoundTrip, true) || in_array($destZone, $alwaysRoundTrip, true)) {
            return 'round_trip';
        }
        return 'one_way';
    }

    // Apply toll rules to outbound trip
    $outOriginZone = cb_detect_zone($pickup);
    $outDestZone   = cb_detect_zone($dropoff);
    $outTollMode   = cb_determine_toll_mode($outOriginZone, $outDestZone);

    if ($outTollMode === 'round_trip') {
        $reverseOut = cb_route_quote($dropoff, $pickup, $apiKey);
        $reverseToll = ($reverseOut && $reverseOut['tollAmount'] > 0) ? $reverseOut['tollAmount'] : $totalTolls;
        $totalTolls = $totalTolls + $reverseToll;
    }

    // Trip 2 (return) price
    $hasReturn       = !empty($body['hasReturn']) && !empty($body['returnPickup']) && !empty($body['returnDropoff']);
    $returnBasePrice = 0.0; $returnStopFee = 0.0; $returnTolls = 0.0;
    $returnMiles = 0.0; $returnMins = 0; $returnPriceMode = 'per_mile';

    if ($hasReturn) {
        $retPickup  = trim((string)($body['returnPickup'] ?? ''));
        $retDropoff = trim((string)($body['returnDropoff'] ?? ''));
        $retStops   = is_array($body['returnStops'] ?? null) ? array_filter(array_map('trim', $body['returnStops'])) : [];

        $retPoints = array_merge([$retPickup], array_values($retStops), [$retDropoff]);
        foreach (array_keys($retPoints) as $i) {
            if ($i === count($retPoints) - 1) break;
            $leg = cb_route_quote($retPoints[$i], $retPoints[$i + 1], $apiKey);
            if ($leg) {
                $returnMiles += $leg['distanceMiles'];
                $returnMins  += $leg['durationMinutes'];
                $returnTolls += $leg['tollAmount'];
            }
        }

        $retOriginZone = cb_detect_zone($retPickup);
        $retDestZone   = cb_detect_zone($retDropoff);
        $retTollMode   = cb_determine_toll_mode($retOriginZone, $retDestZone);

        if ($retTollMode === 'round_trip') {
            $reverseRet = cb_route_quote($retDropoff, $retPickup, $apiKey);
            $retReverseToll = ($reverseRet && $reverseRet['tollAmount'] > 0) ? $reverseRet['tollAmount'] : $returnTolls;
            $returnTolls = $returnTolls + $retReverseToll;
        }

        $trip2 = $calcLegPrice($returnMiles, $returnMins, count($retStops), $retPickup, $retDropoff);
        $returnBasePrice = $trip2['price'];
        $returnStopFee   = $trip2['stopFee'];
        $returnPriceMode = $trip2['mode'];
    }

    $combinedBase = $basePrice + $stopFee + $returnBasePrice + $returnStopFee;
    $combinedTolls = $totalTolls + $returnTolls;

    // Gratuity on combined subtotal
    $gratuityAmount = 0.0;
    if ($gratuityType === 'percent') {
        $gratuityAmount = round($combinedBase * ($gratuityValue / 100), 2);
    } elseif ($gratuityType === 'fixed') {
        $gratuityAmount = round($gratuityValue, 2);
    }

    $total = round($combinedBase + $gratuityAmount + $combinedTolls, 2);

    echo json_encode([
        'ok'                  => true,
        'distanceMiles'       => $totalMiles,
        'durationMins'        => $totalMins,
        'basePrice'           => $basePrice,
        'stopFee'             => $stopFee,
        'tolls'               => round($totalTolls, 2),
        'priceMode'           => $priceMode,
        'hasReturn'           => $hasReturn,
        'returnDistanceMiles' => $returnMiles,
        'returnDurationMins'  => $returnMins,
        'returnBasePrice'     => $returnBasePrice,
        'returnStopFee'       => $returnStopFee,
        'returnTolls'         => round($returnTolls, 2),
        'returnPriceMode'     => $returnPriceMode,
        'gratuityAmount'      => $gratuityAmount,
        'total'               => $total,
        'vehicle'             => $vehicle,
    ]);
    exit;
}

// ---------- VEHICLES API ----------
if (isset($_GET['vehicles'])) {
    header('Content-Type: application/json');
    $file = __DIR__ . '/data/vehicles.json';
    $vehicles = [];
    if (file_exists($file)) {
        $data = json_decode(file_get_contents($file), true);
        if (is_array($data)) {
            foreach ($data as $v) {
                if (!is_array($v)) continue;
                if (array_key_exists('active', $v) && empty($v['active'])) continue;
                $vehicles[] = [
                    'name'          => $v['name'] ?? '',
                    'base'          => (float)($v['base'] ?? 0),
                    'perMile'       => (float)($v['perMile'] ?? 0),
                    'perMin'        => (float)($v['perMin'] ?? 0),
                    'hourly'        => (float)($v['hourly'] ?? 0),
                    'maxPassengers' => (int)($v['maxPassengers'] ?? 0),
                ];
            }
        }
    }
    echo json_encode(['vehicles' => $vehicles]);
    exit;
}

// ---------- JSON API HANDLER ----------
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    header('Content-Type: application/json');

    $raw  = file_get_contents('php://input');
    $body = json_decode($raw, true);

    if (!$body || !isset($body['action'])) {
        http_response_code(400);
        echo json_encode(['error' => 'Missing action']);
        exit;
    }

    $action = $body['action'];

    // ---- LOOKUP ----
    if ($action === 'lookup') {
        $confirmationNumber = trim($body['confirmationNumber'] ?? '');
        $email              = strtolower(trim($body['email'] ?? ''));

        if (!$confirmationNumber || !$email) {
            echo json_encode(['error' => 'Confirmation number and email are required.']);
            exit;
        }

        $booking = loadBooking($confirmationNumber);

        if (!$booking) {
            echo json_encode(['error' => 'Booking not found. Please check your confirmation number.']);
            exit;
        }

        if (strtolower(trim($booking['email'] ?? '')) !== $email) {
            echo json_encode(['error' => 'Email does not match. Please try again.']);
            exit;
        }

        echo json_encode(['success' => true, 'booking' => sanitizeForClient($booking)]);
        exit;
    }

    // ---- UPDATE ----
    if ($action === 'update') {
        $confirmationNumber = trim($body['confirmationNumber'] ?? '');
        $email              = strtolower(trim($body['email'] ?? ''));

        if (!$confirmationNumber || !$email) {
            echo json_encode(['error' => 'Missing confirmation number or email.']);
            exit;
        }

        $booking = loadBooking($confirmationNumber);

        if (!$booking) {
            echo json_encode(['error' => 'Booking not found.']);
            exit;
        }

        if (strtolower(trim($booking['email'] ?? '')) !== $email) {
            echo json_encode(['error' => 'Unauthorized.']);
            exit;
        }

        if (($booking['paymentStatus'] ?? '') === 'Cancelled') {
            echo json_encode(['error' => 'This booking has been cancelled and cannot be edited.']);
            exit;
        }

        // Capture original before changes for diff
        $original = $booking;

        // Allowed editable fields — never overwrite financial/payment fields from client
        $editableFields = [
            'pickup', 'dropoff',
            'trip1Stops', 'trip2Stops',
            'tripDate', 'tripTime',
            'flightNumber',
            'returnPickup', 'returnDropoff',
            'returnTripDate', 'returnTripTime',
            'returnFlightNumber',
            'numPassengers', 'numLuggage',
            'specialInstructions',
            'serviceType', 'serviceTypeLabel',
            'trip1Vehicle', 'trip1Passengers',
            'trip2Vehicle', 'trip2Passengers',
        ];

        foreach ($editableFields as $field) {
            if (array_key_exists($field, $body)) {
                $booking[$field] = $body[$field];
            }
        }

        // If customer is adding a return trip, set serviceType accordingly
        if (!empty($body['returnPickup']) && !empty($body['returnDropoff'])) {
            $booking['serviceType']      = 'roundtrip';
            $booking['serviceTypeLabel'] = 'Round Trip';
        }

        $booking['lastEditedAt'] = date('c');

        // Save any new pricing fields sent from the client (from calculatePrice result)
        $priceFields = ['basePrice','outboundPrice','tolls','gratuityAmount','gratuityDisplay',
                        'gratuityType','gratuityValue','total','totalAmount','trip1Distance',
                        'trip1Duration','priceMode'];
        foreach ($priceFields as $pf) {
            if (array_key_exists($pf, $body)) {
                $booking[$pf] = $body[$pf];
            }
        }

        if (!saveBooking($confirmationNumber, $booking)) {
            http_response_code(500);
            echo json_encode(['error' => 'Failed to save booking. Please try again.']);
            exit;
        }

        // Send confirmation emails to customer and admin
        sendUpdateEmails($booking, 'updated', $original);

        echo json_encode(['success' => true, 'booking' => sanitizeForClient($booking)]);
        exit;
    }

    // ---- CANCEL ----
    if ($action === 'cancel') {
        $confirmationNumber = trim($body['confirmationNumber'] ?? '');
        $email              = strtolower(trim($body['email'] ?? ''));

        if (!$confirmationNumber || !$email) {
            echo json_encode(['error' => 'Missing confirmation number or email.']);
            exit;
        }

        $booking = loadBooking($confirmationNumber);

        if (!$booking) {
            echo json_encode(['error' => 'Booking not found.']);
            exit;
        }

        if (strtolower(trim($booking['email'] ?? '')) !== $email) {
            echo json_encode(['error' => 'Unauthorized.']);
            exit;
        }

        if (($booking['paymentStatus'] ?? '') === 'Cancelled') {
            echo json_encode(['error' => 'This booking is already cancelled.']);
            exit;
        }

        $booking['paymentStatus'] = 'Cancelled';
        $booking['cancelledAt']   = date('c');

        if (!saveBooking($confirmationNumber, $booking)) {
            http_response_code(500);
            echo json_encode(['error' => 'Failed to cancel booking. Please try again.']);
            exit;
        }

        // Send cancellation emails to customer and admin
        sendUpdateEmails($booking, 'cancelled');

        echo json_encode(['success' => true, 'message' => 'Your booking has been cancelled.']);
        exit;
        exit;
    }

    echo json_encode(['error' => 'Unknown action.']);
    exit;
}

// ---------- FILE HELPERS ----------

function loadBooking(string $confirmationNumber): ?array {
    $confirmationNumber = preg_replace('/[^A-Za-z0-9\-_]/', '', $confirmationNumber);
    $file = BOOKINGS_DIR . $confirmationNumber . '.json';
    if (!file_exists($file)) return null;
    $json = file_get_contents($file);
    $data = json_decode($json, true);
    return is_array($data) ? $data : null;
}

function saveBooking(string $confirmationNumber, array $data): bool {
    $confirmationNumber = preg_replace('/[^A-Za-z0-9\-_]/', '', $confirmationNumber);
    if (!is_dir(BOOKINGS_DIR)) {
        mkdir(BOOKINGS_DIR, 0755, true);
    }
    $file = BOOKINGS_DIR . $confirmationNumber . '.json';
    $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    return file_put_contents($file, $json, LOCK_EX) !== false;
}

// Strip sensitive server-side fields before sending to browser
function sanitizeForClient(array $booking): array {
    $remove = ['paymentIntentId', 'stripeSessionId'];
    foreach ($remove as $key) {
        unset($booking[$key]);
    }
    return $booking;
}

// Load active vehicles from vehicles.json
function loadVehicles(): array {
    $file = __DIR__ . '/data/vehicles.json';
    if (!file_exists($file)) return [];
    $data = json_decode(file_get_contents($file), true);
    if (!is_array($data)) return [];
    return array_values(array_filter($data, function($v) {
        return is_array($v) && (!array_key_exists('active', $v) || !empty($v['active']));
    }));
}

// Build plain-text booking summary for emails
function buildEmailSummary(array $b): string {
    $conf    = $b['confirmationNumber'] ?? 'N/A';
    $t1stops = is_array($b['trip1Stops'] ?? null) ? implode(', ', array_filter($b['trip1Stops'])) : '';
    $t2stops = is_array($b['trip2Stops'] ?? null) ? implode(', ', array_filter($b['trip2Stops'])) : '';
    $total   = $b['total'] ?? ($b['totalAmount'] ?? '');
    $hasRet  = !empty($b['returnPickup']) || !empty($b['returnTripDate']);

    $lines = [
        '================================',
        'BOOKING CONFIRMATION — ' . $conf,
        '================================',
        'Customer:    ' . trim(($b['firstName'] ?? '') . ' ' . ($b['lastName'] ?? '')),
        'Email:       ' . ($b['email'] ?? '—'),
        'Phone:       ' . ($b['phone'] ?? '—'),
        '',
        '--- OUTBOUND TRIP ---',
        'Date:        ' . ($b['tripDate'] ?? '—'),
        'Time:        ' . ($b['tripTime'] ?? '—'),
        'Pickup:      ' . ($b['pickup'] ?? '—'),
        'Stops:       ' . ($t1stops ?: 'None'),
        'Dropoff:     ' . ($b['dropoff'] ?? '—'),
        'Vehicle:     ' . ($b['trip1Vehicle'] ?? ($b['vehicle'] ?? '—')),
        'Passengers:  ' . ($b['trip1Passengers'] ?? ($b['numPassengers'] ?? '—')),
        'Luggage:     ' . ($b['numLuggage'] ?? '—'),
        'Flight #:    ' . ($b['flightNumber'] ?? '—'),
    ];

    if ($hasRet) {
        $lines = array_merge($lines, [
            '', '--- RETURN TRIP ---',
            'Date:        ' . ($b['returnTripDate'] ?? '—'),
            'Time:        ' . ($b['returnTripTime'] ?? '—'),
            'Pickup:      ' . ($b['returnPickup'] ?? '—'),
            'Stops:       ' . ($t2stops ?: 'None'),
            'Dropoff:     ' . ($b['returnDropoff'] ?? '—'),
            'Vehicle:     ' . ($b['trip2Vehicle'] ?? ($b['trip1Vehicle'] ?? '—')),
            'Flight #:    ' . ($b['returnFlightNumber'] ?? '—'),
        ]);
    }

    $lines = array_merge($lines, [
        '', '--- PRICING ---',
        'Base Price:  $' . number_format((float)($b['outboundPrice'] ?? ($b['basePrice'] ?? 0)), 2),
        'Stop Fee:    $' . number_format((float)($b['stopFee'] ?? 0), 2),
        'Gratuity:    $' . number_format((float)($b['gratuityAmount'] ?? 0), 2),
        'Tolls:       $' . number_format((float)($b['tolls'] ?? 0), 2),
        'Total:       $' . number_format((float)($b['total'] ?? ($b['totalAmount'] ?? 0)), 2),
        '', 'Special Instructions: ' . ($b['specialInstructions'] ?? 'None'),
        '================================',
    ]);

    return implode("\n", $lines);
}

// Send a plain-text email
function cb_build_changes(array $original, array $updated): string {
    $h = function($v) { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); };

    $watchFields = [
        'pickup'             => 'Pickup',
        'dropoff'            => 'Dropoff',
        'tripDate'           => 'Date',
        'tripTime'           => 'Time',
        'trip1Vehicle'       => 'Vehicle',
        'trip1Passengers'    => 'Passengers',
        'numPassengers'      => 'Passengers',
        'numLuggage'         => 'Luggage',
        'flightNumber'       => 'Flight #',
        'specialInstructions'=> 'Notes',
        'returnPickup'       => 'Return Pickup',
        'returnDropoff'      => 'Return Dropoff',
        'returnTripDate'     => 'Return Date',
        'returnTripTime'     => 'Return Time',
        'returnFlightNumber' => 'Return Flight #',
        'serviceTypeLabel'   => 'Service Type',
        'total'              => 'Total Price',
    ];

    $seen  = [];
    $rows  = '';
    $count = 0;

    foreach ($watchFields as $field => $label) {
        if (in_array($label, $seen, true)) continue; // skip duplicates like numPassengers/trip1Passengers
        $seen[] = $label;

        $oldVal = trim((string)($original[$field] ?? ''));
        $newVal = trim((string)($updated[$field] ?? ''));

        // Normalize total (might be cents or dollars)
        if ($field === 'total') {
            $oldVal = $oldVal !== '' ? '$' . number_format((float)$oldVal, 2) : '—';
            $newVal = $newVal !== '' ? '$' . number_format((float)$newVal, 2) : '—';
        }

        if ($oldVal === $newVal) continue;

        $rows .= '<tr>'
               . '<td style="padding:6px 8px;color:#d4af37;font-weight:bold;width:150px;vertical-align:top;">' . $h($label) . '</td>'
               . '<td style="padding:6px 8px;color:#aaaaaa;text-decoration:line-through;vertical-align:top;">' . $h($oldVal ?: '—') . '</td>'
               . '<td style="padding:6px 8px;color:#ffffff;vertical-align:top;">&#8594; ' . $h($newVal ?: '—') . '</td>'
               . '</tr>';
        $count++;
    }

    // Check stops separately
    $oldStops = is_array($original['trip1Stops'] ?? null) ? implode(', ', array_filter($original['trip1Stops'])) : '';
    $newStops = is_array($updated['trip1Stops'] ?? null)  ? implode(', ', array_filter($updated['trip1Stops']))  : '';
    if ($oldStops !== $newStops) {
        $rows .= '<tr>'
               . '<td style="padding:6px 8px;color:#d4af37;font-weight:bold;vertical-align:top;">Stops</td>'
               . '<td style="padding:6px 8px;color:#aaaaaa;text-decoration:line-through;vertical-align:top;">' . $h($oldStops ?: '—') . '</td>'
               . '<td style="padding:6px 8px;color:#ffffff;vertical-align:top;">&#8594; ' . $h($newStops ?: '—') . '</td>'
               . '</tr>';
        $count++;
    }

    if ($count === 0) return '';

    return '<tr><td colspan="2" style="padding:14px 0 4px;color:#d4af37;font-weight:bold;border-top:1px solid rgba(212,175,55,0.3);font-size:13px;">WHAT CHANGED</td></tr>'
         . '<tr><td colspan="2" style="padding:0 0 8px;">'
         . '<table role="presentation" cellspacing="0" cellpadding="0" border="0" style="width:100%;border-collapse:collapse;background:rgba(212,175,55,0.07);border-radius:8px;">'
         . '<tr>'
         . '<th style="padding:6px 8px;color:#d4af37;font-size:12px;text-align:left;width:150px;">Field</th>'
         . '<th style="padding:6px 8px;color:#888;font-size:12px;text-align:left;">Before</th>'
         . '<th style="padding:6px 8px;color:#888;font-size:12px;text-align:left;">After</th>'
         . '</tr>'
         . $rows
         . '</table></td></tr>';
}

function cb_html_email(array $b, string $heading, string $intro, string $headingColor = '#d4af37', array $original = []): string {
    $h = function($v) { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); };

    // Plain value row — white text
    $row = function($label, $val) use ($h) {
        return '<tr>'
             . '<td style="padding:8px 0;color:#d4af37;font-weight:bold;width:170px;vertical-align:top;">' . $h($label) . ':</td>'
             . '<td style="padding:8px 0;color:#ffffff;">' . $h($val) . '</td>'
             . '</tr>';
    };

    // Address row — white text + clickable Google Maps link
    $addrRow = function($label, $addr) use ($h) {
        if (trim($addr) === '' || $addr === '—') {
            return '<tr>'
                 . '<td style="padding:8px 0;color:#d4af37;font-weight:bold;width:170px;vertical-align:top;">' . $h($label) . ':</td>'
                 . '<td style="padding:8px 0;color:#ffffff;">—</td>'
                 . '</tr>';
        }
        $mapsUrl = 'https://www.google.com/maps/search/?api=1&query=' . urlencode($addr);
        return '<tr>'
             . '<td style="padding:8px 0;color:#d4af37;font-weight:bold;width:170px;vertical-align:top;">' . $h($label) . ':</td>'
             . '<td style="padding:8px 0;"><a href="' . $h($mapsUrl) . '" style="color:#7eb8f7;text-decoration:underline;">' . $h($addr) . '</a></td>'
             . '</tr>';
    };

    $conf    = $b['confirmationNumber'] ?? 'N/A';
    $t1stops = is_array($b['trip1Stops'] ?? null) ? array_filter($b['trip1Stops']) : [];
    $t2stops = is_array($b['trip2Stops'] ?? null) ? array_filter($b['trip2Stops']) : [];
    $hasRet  = !empty($b['returnPickup']) || !empty($b['returnTripDate']);
    $name    = trim(($b['firstName'] ?? '') . ' ' . ($b['lastName'] ?? ''));

    $rows  = $row('Confirmation #', $conf);
    $rows .= $row('Service Type',   $b['serviceTypeLabel'] ?? ($b['serviceType'] ?? '—'));
    $rows .= $row('Name',           $name ?: '—');
    $rows .= $row('Email',          $b['email'] ?? '—');
    $rows .= $row('Phone',          $b['phone'] ?? '—');
    $rows .= '<tr><td colspan="2" style="padding:10px 0 2px;color:#d4af37;font-weight:bold;border-top:1px solid rgba(212,175,55,0.3);font-size:13px;">OUTBOUND TRIP</td></tr>';
    $rows .= $row('Date',           $b['tripDate'] ?? '—');
    $rows .= $row('Time',           $b['tripTime'] ?? '—');
    $rows .= $addrRow('Pickup',     $b['pickup'] ?? '—');
    foreach ($t1stops as $i => $s) { $rows .= $addrRow('Stop ' . ($i+1), $s); }
    $rows .= $addrRow('Dropoff',    $b['dropoff'] ?? '—');
    $rows .= $row('Vehicle',        $b['trip1Vehicle'] ?? ($b['vehicle'] ?? '—'));
    $rows .= $row('Passengers',     (string)($b['trip1Passengers'] ?? ($b['numPassengers'] ?? '—')));
    $rows .= $row('Luggage',        (string)($b['numLuggage'] ?? '—'));
    if (!empty($b['flightNumber']))        $rows .= $row('Flight #', $b['flightNumber']);
    if (!empty($b['specialInstructions'])) $rows .= $row('Notes',    $b['specialInstructions']);

    if ($hasRet) {
        $rows .= '<tr><td colspan="2" style="padding:10px 0 2px;color:#d4af37;font-weight:bold;border-top:1px solid rgba(212,175,55,0.3);font-size:13px;">RETURN TRIP</td></tr>';
        $rows .= $row('Return Date',      $b['returnTripDate'] ?? '—');
        $rows .= $row('Return Time',      $b['returnTripTime'] ?? '—');
        $rows .= $addrRow('Return Pickup', $b['returnPickup'] ?? '—');
        foreach ($t2stops as $i => $s) { $rows .= $addrRow('Return Stop ' . ($i+1), $s); }
        $rows .= $addrRow('Return Dropoff', $b['returnDropoff'] ?? '—');
        if (!empty($b['returnFlightNumber'])) $rows .= $row('Return Flight #', $b['returnFlightNumber']);
    }

    // Show what changed (only when original is provided)
    if (!empty($original)) {
        $rows .= cb_build_changes($original, $b);
    }

    $rows .= '<tr><td colspan="2" style="padding:10px 0 2px;color:#d4af37;font-weight:bold;border-top:1px solid rgba(212,175,55,0.3);font-size:13px;">PRICING</td></tr>';
    $rows .= $row('Base Price', '$' . number_format((float)($b['basePrice'] ?? ($b['outboundPrice'] ?? 0)), 2));
    if ((float)($b['stopFee'] ?? 0) > 0)  $rows .= $row('Stop Fee', '$' . number_format((float)$b['stopFee'], 2));
    if ((float)($b['tolls'] ?? 0) > 0)    $rows .= $row('Tolls',    '$' . number_format((float)$b['tolls'], 2));
    $rows .= $row('Gratuity', '$' . number_format((float)($b['gratuityAmount'] ?? 0), 2));
    $rows .= $row('Total',    '$' . number_format((float)($b['total'] ?? ($b['totalAmount'] ?? 0)), 2));

    return '<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body style="margin:0;padding:0;background:#111111;font-family:Arial,Helvetica,sans-serif;color:#f5f1e8;">
  <div style="max-width:640px;margin:0 auto;padding:24px;">
    <div style="background:#1a1a1a;border:1px solid rgba(212,175,55,0.35);border-radius:14px;padding:32px 24px;">
      <h1 style="margin:0 0 8px;color:' . $headingColor . ';font-size:30px;line-height:1.2;">' . $h($heading) . '</h1>
      <p style="margin:0 0 20px;font-size:15px;color:#cfc7b2;">' . $h($intro) . '</p>
      <table role="presentation" cellspacing="0" cellpadding="0" border="0" style="width:100%;border-collapse:collapse;">
        ' . $rows . '
      </table>
      <p style="margin:24px 0 0;font-size:13px;color:#888;">MyNYSUV &nbsp;|&nbsp; reserve@mynysuv.com</p>
    </div>
  </div>
</body></html>';
}

function sendEmail(string $to, string $subject, string $body): bool {
    $to = trim($to);
    if ($to === '') return false;

    $headers = implode("\r\n", [
        'MIME-Version: 1.0',
        'Content-Type: text/html; charset=UTF-8',
        'From: MyNYSUV Reservations <reservations@mynysuv.com>',
        'Reply-To: reservations@mynysuv.com',
        'X-Mailer: PHP/' . phpversion(),
    ]);

    $encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
    $result = mail($to, $encodedSubject, $body, $headers);

    $logFile = __DIR__ . '/mail_error_log.txt';
    $logLine = date('Y-m-d H:i:s') . ' | ' . ($result ? 'SENT' : 'FAILED') . ' | To: ' . $to . ' | Subject: ' . $subject . "\n";
    file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);

    return $result;
}

function sendEmailAdmin(string $to, string $subject, string $body, string $fromEmail = ''): bool {
    $to = trim($to);
    if ($to === '') return false;

    $headers = implode("\r\n", [
        'MIME-Version: 1.0',
        'Content-Type: text/html; charset=UTF-8',
        'From: MyNYSUV Reservations <reservations@mynysuv.com>',
        'Reply-To: reservations@mynysuv.com',
        'X-Mailer: PHP/' . phpversion(),
    ]);

    $encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
    $result = mail($to, $encodedSubject, $body, $headers);

    $logFile = __DIR__ . '/mail_error_log.txt';
    $logLine = date('Y-m-d H:i:s') . ' | ADMIN | ' . ($result ? 'SENT' : 'FAILED') . ' | To: ' . $to . ' | Subject: ' . $subject . "\n";
    file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);

    return $result;
}

// Notify customer + admin after update or cancel
function sendUpdateEmails(array $booking, string $type = 'updated', array $original = []): void {
    $conf      = $booking['confirmationNumber'] ?? 'N/A';
    $custEmail = trim($booking['email'] ?? '');
    $admin     = 'reserve@mynysuv.com';
    $name      = trim(($booking['firstName'] ?? '') . ' ' . ($booking['lastName'] ?? ''));
    if ($name === '') $name = $custEmail;

    if ($type === 'cancelled') {
        if ($custEmail !== '') {
            sendEmail(
                $custEmail,
                'Your Booking Has Been Cancelled — ' . $conf,
                cb_html_email($booking,
                    'Booking Cancelled',
                    'Hello ' . $name . ', your booking ' . $conf . ' has been cancelled. If this was a mistake please contact us immediately at reserve@mynysuv.com.',
                    '#e07070'
                )
            );
        }
        sendEmailAdmin(
            $admin,
            '[CANCELLATION] ' . $conf . ' cancelled by customer',
            cb_html_email($booking,
                'Booking Cancelled by Customer',
                'Customer ' . $name . ' (' . $custEmail . ') has cancelled their booking.',
                '#e07070'
            ),
            $custEmail
        );
    } else {
        if ($custEmail !== '') {
            sendEmail(
                $custEmail,
                'Your Booking Has Been Updated — ' . $conf,
                cb_html_email($booking,
                    'Booking Updated',
                    'Hello ' . $name . ', your booking has been successfully updated. Here is your full updated summary.',
                    '#d4af37',
                    $original
                )
            );
        }
        sendEmailAdmin(
            $admin,
            '[BOOKING MODIFIED] ' . $conf . ' updated by customer',
            cb_html_email($booking,
                'Booking Modified by Customer',
                'Customer ' . $name . ' (' . $custEmail . ') has updated their booking.',
                '#d4af37'
            ),
            $custEmail
        );
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Manage My Booking</title>

  <!-- Replace YOUR_GOOGLE_API_KEY with your actual key -->
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAkGBtQQV3LFrypWxnSl1EutmgyheSwWUc&libraries=places" async defer
    onload="initAutocomplete()"></script>

  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: #f5f5f0;
      color: #1a1a1a;
      min-height: 100vh;
      padding: 2rem 1rem;
    }

    .page-wrap {
      max-width: 600px;
      margin: 0 auto;
    }

    .logo-area {
      text-align: center;
      margin-bottom: 2rem;
    }

    .logo-area h1 {
      font-size: 1.4rem;
      font-weight: 600;
      color: #1a1a1a;
    }

    .logo-area p {
      font-size: 0.9rem;
      color: #666;
      margin-top: 4px;
    }

    /* Cards */
    .card {
      background: #fff;
      border-radius: 12px;
      border: 1px solid #e8e8e8;
      padding: 1.5rem;
      margin-bottom: 1rem;
    }

    .card-title {
      font-size: 0.7rem;
      font-weight: 600;
      color: #999;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      margin-bottom: 1rem;
    }

    /* Form fields */
    label {
      display: block;
      font-size: 0.8rem;
      color: #555;
      margin-bottom: 4px;
      margin-top: 12px;
    }

    label:first-child { margin-top: 0; }

    input[type="text"],
    input[type="email"],
    input[type="date"],
    input[type="time"],
    select,
    textarea {
      width: 100%;
      padding: 10px 12px;
      border: 1px solid #ddd;
      border-radius: 8px;
      font-size: 0.95rem;
      font-family: inherit;
      color: #1a1a1a;
      background: #fff;
      transition: border-color 0.2s;
    }

    input:focus, select:focus, textarea:focus {
      outline: none;
      border-color: #d4af37;
      box-shadow: 0 0 0 3px rgba(212,175,55,0.12);
    }

    input.error { border-color: #c0392b; }

    textarea { resize: vertical; min-height: 70px; }

    /* Buttons */
    .btn {
      width: 100%;
      padding: 12px;
      border-radius: 8px;
      font-size: 0.95rem;
      font-weight: 600;
      cursor: pointer;
      font-family: inherit;
      transition: all 0.2s;
      border: none;
    }

    .btn-gold {
      background: #d4af37;
      color: #fff;
    }

    .btn-gold:hover { background: #b8962e; }

    .btn-outline {
      background: none;
      border: 1px solid #ddd;
      color: #555;
      margin-top: 10px;
    }

    .btn-outline:hover { background: #f5f5f5; }

    .btn-danger {
      background: none;
      border: 1px solid #e0c0c0;
      color: #c0392b;
      margin-top: 10px;
    }

    .btn-danger:hover { background: #fdf0f0; }

    .btn:disabled {
      opacity: 0.6;
      cursor: not-allowed;
    }

    /* Stop rows */
    .stops-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }

    .stop-row-edit {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .stop-row-edit input { flex: 1; }

    .stop-remove-btn {
      width: 36px; height: 36px;
      min-width: 36px;
      border: 1px solid #ddd;
      border-radius: 8px;
      background: none;
      cursor: pointer;
      font-size: 16px;
      color: #999;
      display: flex; align-items: center; justify-content: center;
    }

    .stop-remove-btn:hover { border-color: #c0392b; color: #c0392b; background: #fdf0f0; }

    .add-stop-link {
      display: inline-block;
      margin-top: 8px;
      color: #d4af37;
      font-size: 0.85rem;
      font-weight: 600;
      cursor: pointer;
      user-select: none;
    }

    .add-stop-link:hover { text-decoration: underline; }

    /* Return trip toggle */
    .toggle-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .toggle-label { font-size: 0.95rem; color: #1a1a1a; }

    .toggle-switch { position: relative; width: 44px; height: 24px; }
    .toggle-switch input { opacity: 0; width: 0; height: 0; }
    .toggle-track {
      position: absolute; inset: 0;
      background: #ddd;
      border-radius: 24px;
      cursor: pointer;
      transition: background 0.2s;
    }
    .toggle-switch input:checked + .toggle-track { background: #d4af37; }
    .toggle-track::before {
      content: '';
      position: absolute;
      width: 18px; height: 18px;
      left: 3px; top: 3px;
      background: white;
      border-radius: 50%;
      transition: transform 0.2s;
    }
    .toggle-switch input:checked + .toggle-track::before { transform: translateX(20px); }

    .return-fields { display: none; margin-top: 14px; }
    .return-fields.visible { display: block; }

    /* Status badge */
    .status-badge {
      display: inline-block;
      padding: 3px 10px;
      border-radius: 6px;
      font-size: 0.75rem;
      font-weight: 600;
    }

    .status-confirmed { background: #eaf3de; color: #3b6d11; }
    .status-cancelled { background: #fdf0f0; color: #c0392b; }
    .status-authorized { background: #e6f1fb; color: #185fa5; }

    /* Sections */
    .hidden { display: none !important; }

    /* Alert messages */
    .alert {
      padding: 12px 14px;
      border-radius: 8px;
      font-size: 0.9rem;
      margin-bottom: 1rem;
    }

    .alert-error { background: #fdf0f0; color: #c0392b; border: 1px solid #f5c0c0; }
    .alert-success { background: #eaf3de; color: #3b6d11; border: 1px solid #c0dd97; }

    /* Booking summary view */
    .summary-row {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      padding: 8px 0;
      border-bottom: 1px solid #f0f0f0;
      font-size: 0.9rem;
      gap: 12px;
    }

    .summary-row:last-child { border-bottom: none; }

    .summary-key { color: #666; flex-shrink: 0; }
    .summary-val { text-align: right; font-weight: 500; }

    .booking-header-row {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 4px;
    }

    .confirm-num { font-size: 0.8rem; color: #999; }

    .section-heading {
      font-size: 0.85rem;
      font-weight: 600;
      color: #d4af37;
      margin: 14px 0 8px;
      padding-bottom: 4px;
      border-bottom: 1px solid #f5f0e0;
    }
  </style>
</head>
<body>
<div class="page-wrap">

  <div class="logo-area">
    <h1>Manage My Booking</h1>
    <p>Look up your reservation to view or make changes</p>
  </div>

  <!-- ======== LOOKUP FORM ======== -->
  <div id="lookupSection">
    <div class="card">
      <div class="card-title">Find your booking</div>

      <div id="lookupError" class="alert alert-error hidden"></div>

      <label for="lookupConfNum">Confirmation number</label>
      <input type="text" id="lookupConfNum" placeholder="e.g. BR-260409-123456-7890" />

      <label for="lookupEmail">Email address used at booking</label>
      <input type="email" id="lookupEmail" placeholder="you@example.com" />

      <button class="btn btn-gold" style="margin-top:16px;" id="lookupBtn" onclick="lookupBooking()">
        Find my booking
      </button>
    </div>
  </div>

  <!-- ======== BOOKING VIEW + EDIT ======== -->
  <div id="bookingSection" class="hidden">

    <!-- Summary card -->
    <div class="card" id="summaryCard">
      <div class="booking-header-row">
        <div>
          <div class="confirm-num" id="summaryConfNum"></div>
          <div style="font-size:1.1rem; font-weight:600; margin-top:2px;">Your reservation</div>
        </div>
        <span class="status-badge" id="summaryStatus"></span>
      </div>

      <div id="summaryBody" style="margin-top:12px;"></div>

      <div style="margin-top:16px; display:flex; flex-direction:column; gap:8px;" id="actionButtons">
        <button class="btn btn-gold" id="editBtn" onclick="showEditForm()">Edit this booking</button>
        <button class="btn btn-danger" id="cancelBookingBtn" onclick="confirmCancel()">Cancel this booking</button>
        <button class="btn btn-outline" id="closeBtn" onclick="closeBooking()" style="border:1px solid #ccc; background:transparent; color:#666;">Close</button>
      </div>

      <div id="cancelledNotice" class="hidden" style="margin-top:12px; text-align:center; color:#999; font-size:0.85rem;">
        This booking has been cancelled.
      </div>
    </div>

    <!-- Edit form -->
    <div id="editSection" class="hidden">

      <div id="editError" class="alert alert-error hidden"></div>
      <div id="editSuccess" class="alert alert-success hidden"></div>

      <!-- Pickup / Dropoff / Stops — unified sortable route list -->
      <div class="card">
        <div class="card-title">Route</div>
        <p style="font-size:0.8rem;color:#999;margin-bottom:10px;">Drag ☰ to reorder. The first row is pickup, the last is dropoff — everything in between is a stop.</p>

        <div id="routeList" style="display:flex;flex-direction:column;gap:8px;"></div>

        <div style="margin-top:10px;">
          <span class="add-stop-link" onclick="addRouteStop()">+ Add a stop</span>
        </div>

        <!-- Hidden fields read by saveEdits() -->
        <input type="hidden" id="editPickup" />
        <input type="hidden" id="editDropoff" />
        <div id="trip1StopsList" style="display:none;"></div>
      </div>

      <!-- Date & Time -->
      <div class="card">
        <div class="card-title">Date &amp; time</div>

        <label>Pickup date</label>
        <input type="date" id="editTripDate" />

        <label>Pickup time</label>
        <input type="time" id="editTripTime" />

        <label>Flight number (optional)</label>
        <input type="text" id="editFlightNumber" placeholder="e.g. AA 123" />
      </div>

      <!-- Return trip -->
      <div class="card">
        <div class="card-title">Return trip</div>
        <div class="toggle-row">
          <span class="toggle-label">Add / include a return trip</span>
          <label class="toggle-switch">
            <input type="checkbox" id="returnToggle" onchange="toggleReturnFields(this)" />
            <span class="toggle-track"></span>
          </label>
        </div>

        <div class="return-fields" id="returnFields">
          <label>Return pickup location</label>
          <input type="text" id="editReturnPickup" placeholder="Return pickup address" />

          <div style="margin-top:12px;">
            <div id="trip2StopsList" class="stops-list"></div>
            <span class="add-stop-link" onclick="addEditStop('trip2')">+ Add a stop</span>
          </div>

          <label style="margin-top:14px;">Return dropoff location</label>
          <input type="text" id="editReturnDropoff" placeholder="Return dropoff address" />

          <label>Return date</label>
          <input type="date" id="editReturnDate" />

          <label>Return time</label>
          <input type="time" id="editReturnTime" />

          <label>Return flight number (optional)</label>
          <input type="text" id="editReturnFlightNumber" placeholder="e.g. AA 456" />
        </div>
      </div>

      <!-- Vehicle selection -->
      <div class="card">
        <div class="card-title">Vehicle</div>
        <label>Vehicle type</label>
        <select id="editVehicle" onchange="showVehiclePricing()"><option value="">Loading vehicles…</option></select>
        <div id="vehiclePriceNote" style="margin-top:8px;font-size:0.8rem;color:#d4af37;min-height:18px;"></div>
      </div>

      <!-- Passengers &amp; luggage -->
      <div class="card">
        <div class="card-title">Passengers &amp; luggage</div>
        <label>Number of passengers</label>
        <input type="text" id="editPassengers" placeholder="e.g. 2" />
        <label>Number of luggage pieces</label>
        <input type="text" id="editLuggage" placeholder="e.g. 3" />
      </div>

      <!-- Special instructions -->
      <div class="card">
        <div class="card-title">Special instructions</div>
        <textarea id="editInstructions" placeholder="Any special requests or notes for your driver…"></textarea>
      </div>

      <!-- Price estimate -->
      <div class="card" id="priceCard" style="display:none;">
        <div class="card-title">Price estimate</div>
        <div id="priceError" class="alert alert-error" style="display:none;"></div>
        <div id="priceBreakdown"></div>
      </div>

      <!-- Save / back -->
      <button class="btn btn-gold" id="calcPriceBtn" onclick="calculatePrice()" style="margin-bottom:10px;">Calculate Price</button>
      <button class="btn btn-gold" id="saveBtn" onclick="saveEdits()" style="display:none;">Confirm &amp; Save</button>
      <button class="btn btn-outline" onclick="showSummary()">Back to summary</button>
    </div>

  </div><!-- /bookingSection -->

</div><!-- /page-wrap -->

<script>
  // ---- STATE ----
  let currentBooking = null;
  let trip1EditStops = [];
  let trip2EditStops = [];
  let googleReady = false;
  let allVehicles = [];
  let lastPriceData = null; // stores result from calculatePrice

  // ---- GOOGLE PLACES ----
  function initAutocomplete() {
    googleReady = true;
    // editPickup/editDropoff are now hidden — autocomplete bound per route row
    bindAutocomplete('editReturnPickup');
    bindAutocomplete('editReturnDropoff');
  }

  function bindAutocomplete(inputId) {
    const el = document.getElementById(inputId);
    if (!el || !googleReady || !window.google) return;
    new google.maps.places.Autocomplete(el);
  }

  function bindStopAutocomplete(input) {
    if (!input || !googleReady || !window.google) return;
    new google.maps.places.Autocomplete(input);
  }

  // ---- LOOKUP ----
  async function lookupBooking() {
    const confNum = document.getElementById('lookupConfNum').value.trim();
    const email   = document.getElementById('lookupEmail').value.trim();
    const errEl   = document.getElementById('lookupError');

    errEl.classList.add('hidden');

    if (!confNum || !email) {
      showLookupError('Please enter your confirmation number and email.');
      return;
    }

    const btn = document.getElementById('lookupBtn');
    btn.disabled = true;
    btn.textContent = 'Looking up…';

    try {
      const res  = await fetch('customer-booking.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ action: 'lookup', confirmationNumber: confNum, email })
      });
      const data = await res.json();

      if (data.error) {
        showLookupError(data.error);
        return;
      }

      currentBooking = data.booking;
      renderSummary(currentBooking);
      document.getElementById('lookupSection').classList.add('hidden');
      document.getElementById('bookingSection').classList.remove('hidden');

    } catch (err) {
      showLookupError('Could not connect. Please try again.');
    } finally {
      btn.disabled = false;
      btn.textContent = 'Find my booking';
    }
  }

  function showLookupError(msg) {
    const el = document.getElementById('lookupError');
    el.textContent = msg;
    el.classList.remove('hidden');
  }

  // ---- SUMMARY RENDER ----
  function renderSummary(b) {
    document.getElementById('summaryConfNum').textContent = b.confirmationNumber || '';

    const statusEl = document.getElementById('summaryStatus');
    const status   = b.paymentStatus || 'Confirmed';
    statusEl.textContent = status;
    statusEl.className   = 'status-badge ' + getStatusClass(status);

    const isCancelled = status === 'Cancelled';
    document.getElementById('actionButtons').classList.toggle('hidden', isCancelled);
    document.getElementById('cancelledNotice').classList.toggle('hidden', !isCancelled);

    let html = '';

    html += '<div class="section-heading">Service</div>';
    html += row('Type', b.serviceTypeLabel || b.serviceType || '—');
    html += row('Vehicle', b.trip1Vehicle || b.vehicle || '—');
    html += row('Passengers', b.numPassengers || b.trip1Passengers || '—');
    html += row('Luggage', b.numLuggage || '—');

    html += '<div class="section-heading">Outbound trip</div>';
    html += row('Pickup', b.pickup || '—');
    if (Array.isArray(b.trip1Stops) && b.trip1Stops.length) {
      b.trip1Stops.forEach((s, i) => { html += row('Stop ' + (i + 1), s); });
    }
    html += row('Dropoff', b.dropoff || '—');
    html += row('Date', b.tripDate || '—');
    html += row('Time', b.tripTime || '—');
    if (b.flightNumber) html += row('Flight', b.flightNumber);

    if (b.serviceType === 'roundtrip' && b.returnPickup) {
      html += '<div class="section-heading">Return trip</div>';
      html += row('Pickup', b.returnPickup || '—');
      if (Array.isArray(b.trip2Stops) && b.trip2Stops.length) {
        b.trip2Stops.forEach((s, i) => { html += row('Stop ' + (i + 1), s); });
      }
      html += row('Dropoff', b.returnDropoff || '—');
      html += row('Date', b.returnTripDate || '—');
      html += row('Time', b.returnTripTime || '—');
      if (b.returnFlightNumber) html += row('Flight', b.returnFlightNumber);
    }

    html += '<div class="section-heading">Pricing</div>';
    html += row('Base price', '$' + (b.outboundPrice || b.total_display || '—'));
    if (b.tolls > 0) html += row('Tolls', '$' + parseFloat(b.tolls).toFixed(2));
    html += row('Gratuity', b.gratuityDisplay || '—');

    if (b.specialInstructions) {
      html += '<div class="section-heading">Notes</div>';
      html += row('Instructions', b.specialInstructions);
    }

    if (b.lastEditedAt) {
      html += '<div class="section-heading">History</div>';
      html += row('Last edited', formatDate(b.lastEditedAt));
    }

    document.getElementById('summaryBody').innerHTML = html;
  }

  function row(key, val) {
    return `<div class="summary-row"><span class="summary-key">${key}</span><span class="summary-val">${val}</span></div>`;
  }

  function getStatusClass(status) {
    if (status === 'Cancelled') return 'status-cancelled';
    if (status === 'Authorized') return 'status-authorized';
    return 'status-confirmed';
  }

  function formatDate(iso) {
    try { return new Date(iso).toLocaleString(); } catch { return iso; }
  }

  // ---- EDIT FORM ----
  function showEditForm() {
    const b = currentBooking;

    document.getElementById('editPickup').value       = b.pickup || '';
    document.getElementById('editDropoff').value      = b.dropoff || '';
    document.getElementById('editTripDate').value     = b.tripDate || '';
    document.getElementById('editTripTime').value     = b.tripTime || '';
    document.getElementById('editFlightNumber').value = b.flightNumber || '';
    document.getElementById('editPassengers').value   = b.numPassengers || b.trip1Passengers || '';
    document.getElementById('editLuggage').value      = b.numLuggage || '';
    document.getElementById('editInstructions').value = b.specialInstructions || '';

    // Populate vehicle dropdown
    loadVehiclesIntoSelect(b.trip1Vehicle || b.vehicle || '');

    // Reset price card when form opens
    document.getElementById('priceCard').style.display = 'none';
    document.getElementById('saveBtn').style.display = 'none';
    document.getElementById('calcPriceBtn').style.display = 'block';

    // Build unified sortable route list
    const allPoints = [b.pickup || ''];
    if (Array.isArray(b.trip1Stops)) b.trip1Stops.filter(Boolean).forEach(s => allPoints.push(s));
    allPoints.push(b.dropoff || '');
    buildRouteList(allPoints);

    // Return trip
    const hasReturn = b.serviceType === 'roundtrip' && b.returnPickup;
    const toggle = document.getElementById('returnToggle');
    toggle.checked = !!hasReturn;
    toggleReturnFields(toggle);

    if (hasReturn) {
      document.getElementById('editReturnPickup').value      = b.returnPickup || '';
      document.getElementById('editReturnDropoff').value     = b.returnDropoff || '';
      document.getElementById('editReturnDate').value        = b.returnTripDate || '';
      document.getElementById('editReturnTime').value        = b.returnTripTime || '';
      document.getElementById('editReturnFlightNumber').value = b.returnFlightNumber || '';
      trip2EditStops = [];
      document.getElementById('trip2StopsList').innerHTML = '';
      if (Array.isArray(b.trip2Stops)) {
        b.trip2Stops.forEach(s => addEditStop('trip2', s));
      }
    }

    document.getElementById('summaryCard').classList.add('hidden');
    document.getElementById('editSection').classList.remove('hidden');
    document.getElementById('editError').classList.add('hidden');
    document.getElementById('editSuccess').classList.add('hidden');
  }

  function showSummary() {
    document.getElementById('editSection').classList.add('hidden');
    document.getElementById('summaryCard').classList.remove('hidden');
  }

  function toggleReturnFields(cb) {
    document.getElementById('returnFields').classList.toggle('visible', cb.checked);
  }

  // ---- UNIFIED ROUTE LIST (sortable, pickup/stops/dropoff in one list) ----
  let routeSortable = null;

  function buildRouteList(points) {
    const list = document.getElementById('routeList');
    list.innerHTML = '';

    points.forEach((val, idx) => {
      list.appendChild(createRouteRow(val, idx, points.length));
    });

    // Init SortableJS
    if (window.Sortable) {
      initRouteSortable();
    } else {
      const s = document.createElement('script');
      s.src = 'https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js';
      s.onload = initRouteSortable;
      document.head.appendChild(s);
    }
  }

  function initRouteSortable() {
    const list = document.getElementById('routeList');
    if (routeSortable) routeSortable.destroy();
    routeSortable = Sortable.create(list, {
      handle: '.route-drag',
      animation: 150,
      onEnd: refreshRouteLabels
    });
    refreshRouteLabels();
  }

  function createRouteRow(value, idx, total) {
    const row = document.createElement('div');
    row.className = 'stop-row-edit';
    row.style.cssText = 'display:flex;align-items:center;gap:8px;';

    // Drag handle
    const drag = document.createElement('span');
    drag.className = 'route-drag';
    drag.textContent = '☰';
    drag.style.cssText = 'width:32px;min-width:32px;text-align:center;cursor:grab;color:#d4af37;font-size:16px;user-select:none;';

    // Label badge
    const label = document.createElement('span');
    label.className = 'route-label';
    label.style.cssText = 'min-width:60px;font-size:0.72rem;font-weight:700;padding:3px 7px;border-radius:6px;text-align:center;';

    // Input
    const input = document.createElement('input');
    input.type        = 'text';
    input.placeholder = 'Address';
    input.value       = value || '';
    input.style.flex  = '1';
    bindStopAutocomplete(input);

    // Remove button (only for stops, not pickup/dropoff — but allow if >2 rows)
    const removeBtn = document.createElement('button');
    removeBtn.type      = 'button';
    removeBtn.className = 'stop-remove-btn';
    removeBtn.textContent = '✕';
    removeBtn.style.cssText = 'width:32px;min-width:32px;height:36px;border:1px solid #ddd;border-radius:8px;background:none;cursor:pointer;font-size:14px;color:#999;';
    removeBtn.onclick = () => {
      const allRows = document.getElementById('routeList').querySelectorAll('.stop-row-edit');
      if (allRows.length <= 2) { alert('You need at least a pickup and a dropoff.'); return; }
      row.remove();
      refreshRouteLabels();
    };

    row.appendChild(drag);
    row.appendChild(label);
    row.appendChild(input);
    row.appendChild(removeBtn);
    return row;
  }

  function refreshRouteLabels() {
    const rows = document.getElementById('routeList').querySelectorAll('.stop-row-edit');
    const total = rows.length;
    rows.forEach((row, idx) => {
      const label = row.querySelector('.route-label');
      if (!label) return;
      if (idx === 0) {
        label.textContent = 'Pickup';
        label.style.background = '#e6f1fb';
        label.style.color = '#185fa5';
      } else if (idx === total - 1) {
        label.textContent = 'Dropoff';
        label.style.background = '#fcebeb';
        label.style.color = '#a32d2d';
      } else {
        label.textContent = 'Stop ' + idx;
        label.style.background = '#f5f5f0';
        label.style.color = '#666';
      }
    });
  }

  function addRouteStop() {
    const list = document.getElementById('routeList');
    const rows = list.querySelectorAll('.stop-row-edit');
    const total = rows.length;
    // Insert before last row (before dropoff)
    const newRow = createRouteRow('', total - 1, total + 1);
    if (total >= 1) {
      list.insertBefore(newRow, rows[total - 1]);
    } else {
      list.appendChild(newRow);
    }
    refreshRouteLabels();
    newRow.querySelector('input').focus();
  }

  function getRouteValues() {
    const rows = document.getElementById('routeList').querySelectorAll('.stop-row-edit');
    const vals = Array.from(rows).map(r => (r.querySelector('input') || {}).value || '').map(v => v.trim());
    const pickup  = vals[0] || '';
    const dropoff = vals.length > 1 ? vals[vals.length - 1] : '';
    const stops   = vals.length > 2 ? vals.slice(1, -1).filter(Boolean) : [];
    return { pickup, dropoff, stops };
  }

  function getStopValues(prefix) {
    // Legacy fallback — now unused for trip1, but kept for trip2 (return)
    const list = document.getElementById(prefix + 'StopsList');
    if (!list) return [];
    return Array.from(list.querySelectorAll('input'))
      .map(i => i.value.trim())
      .filter(Boolean);
  }

  // ---- PRICE CALCULATION ----
  async function calculatePrice() {
    const route   = getRouteValues();
    const vehicle = document.getElementById('editVehicle').value.trim();
    const errEl   = document.getElementById('priceError');
    const breakEl = document.getElementById('priceBreakdown');
    const card    = document.getElementById('priceCard');
    const saveBtn = document.getElementById('saveBtn');
    const calcBtn = document.getElementById('calcPriceBtn');

    errEl.style.display  = 'none';
    card.style.display   = 'none';
    saveBtn.style.display = 'none';

    if (!route.pickup || !route.dropoff) {
      alert('Please enter a pickup and dropoff location first.');
      return;
    }
    if (!vehicle) {
      alert('Please select a vehicle first.');
      return;
    }

    calcBtn.disabled    = true;
    calcBtn.textContent = 'Calculating…';

    // Collect return trip fields
    const hasReturnTrip = document.getElementById('returnToggle').checked;
    const retPickup  = hasReturnTrip ? document.getElementById('editReturnPickup').value.trim()  : '';
    const retDropoff = hasReturnTrip ? document.getElementById('editReturnDropoff').value.trim() : '';
    const retStops   = hasReturnTrip ? getStopValues('trip2') : [];

    try {
      const res  = await fetch('customer-booking.php?price=1', {
        method:  'POST',
        headers: { 'Content-Type': 'application/json' },
        body:    JSON.stringify({
          pickup:        route.pickup,
          dropoff:       route.dropoff,
          stops:         route.stops,
          vehicle:       vehicle,
          gratuityType:  currentBooking.gratuityType  || 'percent',
          gratuityValue: currentBooking.gratuityValue || 20,
          hasReturn:     hasReturnTrip,
          returnPickup:  retPickup,
          returnDropoff: retDropoff,
          returnStops:   retStops,
        })
      });
      const data = await res.json();

      if (data.error) {
        errEl.textContent   = data.error;
        errEl.style.display = 'block';
        card.style.display  = 'block';
        return;
      }

      // Build breakdown HTML
      let rows = '';
      const addRow = (label, val) => {
        rows += `<div class="summary-row"><span class="summary-key">${label}</span><span class="summary-val">${val}</span></div>`;
      };
      const addSection = (label) => {
        rows += `<div class="summary-row" style="font-weight:700;font-size:0.8rem;color:#d4af37;border-top:1px solid #e8e8e8;padding-top:8px;margin-top:4px;"><span class="summary-key" style="color:#d4af37;">${label}</span><span class="summary-val"></span></div>`;
      };

      addSection('Outbound trip');
      addRow('Vehicle',    data.vehicle);
      addRow('Distance',   data.distanceMiles + ' miles');
      addRow('Duration',   data.durationMins + ' mins');
      addRow('Base price', '$' + data.basePrice.toFixed(2) + (data.priceMode === 'flat_rate' ? ' <span style="font-size:0.75rem;color:#d4af37;">(flat rate)</span>' : ''));
      if (data.stopFee > 0) addRow('Stop fee', '$' + data.stopFee.toFixed(2));
      if (data.tolls > 0)   addRow('Tolls',    '$' + data.tolls.toFixed(2));

      if (data.hasReturn) {
        addSection('Return trip');
        addRow('Distance',    data.returnDistanceMiles + ' miles');
        addRow('Duration',    data.returnDurationMins + ' mins');
        addRow('Return price','$' + data.returnBasePrice.toFixed(2) + (data.returnPriceMode === 'flat_rate' ? ' <span style="font-size:0.75rem;color:#d4af37;">(flat rate)</span>' : ''));
        if (data.returnStopFee > 0) addRow('Stop fee', '$' + data.returnStopFee.toFixed(2));
        addRow('Tolls', '$' + (data.returnTolls || 0).toFixed(2));
      }

      addSection('Total');
      if (data.gratuityAmount > 0) addRow('Gratuity', '$' + data.gratuityAmount.toFixed(2));
      rows += `<div class="summary-row" style="font-weight:700;font-size:1rem;border-top:2px solid #f0f0f0;margin-top:4px;padding-top:10px;">
        <span class="summary-key">Estimated total</span>
        <span class="summary-val" style="color:#d4af37;">$${data.total.toFixed(2)}</span>
      </div>`;
      rows += '<p style="font-size:0.75rem;color:#999;margin-top:10px;">This is an estimate. Final price may vary based on actual route and tolls.</p>';

      lastPriceData = data; // store for save payload
      breakEl.innerHTML  = rows;
      card.style.display = 'block';
      saveBtn.style.display = 'block';
      card.scrollIntoView({ behavior: 'smooth', block: 'start' });

    } catch(e) {
      errEl.textContent   = 'Could not calculate price. Please try again.';
      errEl.style.display = 'block';
      card.style.display  = 'block';
    } finally {
      calcBtn.disabled    = false;
      calcBtn.textContent = 'Calculate Price';
    }
  }

  // ---- VEHICLES ----
  async function loadVehiclesIntoSelect(currentVehicle) {
    const sel = document.getElementById('editVehicle');
    const note = document.getElementById('vehiclePriceNote');
    try {
      const res  = await fetch('customer-booking.php?vehicles=1');
      const data = await res.json();
      allVehicles = data.vehicles || [];

      sel.innerHTML = '';
      allVehicles.forEach(v => {
        const opt = document.createElement('option');
        opt.value = v.name;
        opt.textContent = v.name + ' (max ' + v.maxPassengers + ' passengers)';
        if (v.name.toLowerCase() === (currentVehicle || '').toLowerCase()) opt.selected = true;
        sel.appendChild(opt);
      });

      showVehiclePricing();
    } catch(e) {
      sel.innerHTML = '<option value="">Could not load vehicles</option>';
    }
  }

  function showVehiclePricing() {
    const sel  = document.getElementById('editVehicle');
    const note = document.getElementById('vehiclePriceNote');
    if (!sel || !note) return;
    const name = sel.value.toLowerCase();
    const v    = allVehicles.find(x => x.name.toLowerCase() === name);
    if (!v) { note.textContent = ''; return; }
    const parts = [];
    if (v.base)     parts.push('Base $' + parseFloat(v.base).toFixed(2));
    if (v.perMile)  parts.push('$' + parseFloat(v.perMile).toFixed(2) + '/mile');
    if (v.hourly)   parts.push('Hourly $' + parseFloat(v.hourly).toFixed(2));
    note.textContent = parts.length ? parts.join(' · ') : '';
  }

  // ---- SAVE ----
  async function saveEdits() {
    const errEl = document.getElementById('editError');
    const sucEl = document.getElementById('editSuccess');
    errEl.classList.add('hidden');
    sucEl.classList.add('hidden');

    const route   = getRouteValues();
    const pickup  = route.pickup;
    const dropoff = route.dropoff;
    const date    = document.getElementById('editTripDate').value.trim();
    const time    = document.getElementById('editTripTime').value.trim();

    if (!pickup || !dropoff || !date || !time) {
      errEl.textContent = 'Pickup, dropoff, date and time are required.';
      errEl.classList.remove('hidden');
      return;
    }

    const hasReturn = document.getElementById('returnToggle').checked;

    const payload = {
      action:             'update',
      confirmationNumber: currentBooking.confirmationNumber,
      email:              currentBooking.email,

      pickup,
      dropoff,
      trip1Stops:  route.stops,
      tripDate:    date,
      tripTime:    time,
      flightNumber: document.getElementById('editFlightNumber').value.trim(),

      trip1Vehicle:  document.getElementById('editVehicle').value.trim(),
      numPassengers: document.getElementById('editPassengers').value.trim(),
      numLuggage:    document.getElementById('editLuggage').value.trim(),
      specialInstructions: document.getElementById('editInstructions').value.trim(),

      // Include recalculated price if customer used Calculate Price
      ...(lastPriceData ? {
        basePrice:      lastPriceData.basePrice,
        outboundPrice:  lastPriceData.basePrice,
        stopFee:        lastPriceData.stopFee,
        tolls:          lastPriceData.tolls,
        gratuityAmount: lastPriceData.gratuityAmount,
        gratuityDisplay:'$' + lastPriceData.gratuityAmount.toFixed(2),
        total:          lastPriceData.total,
        totalAmount:    lastPriceData.total,
        trip1Distance:  lastPriceData.distanceMiles + ' miles',
        trip1Duration:  lastPriceData.durationMins + ' mins',
        priceMode:      lastPriceData.priceMode,
      } : {}),
    };

    if (hasReturn) {
      payload.returnPickup       = document.getElementById('editReturnPickup').value.trim();
      payload.returnDropoff      = document.getElementById('editReturnDropoff').value.trim();
      payload.trip2Stops         = getStopValues('trip2');
      payload.returnTripDate     = document.getElementById('editReturnDate').value.trim();
      payload.returnTripTime     = document.getElementById('editReturnTime').value.trim();
      payload.returnFlightNumber = document.getElementById('editReturnFlightNumber').value.trim();
    } else {
      payload.returnPickup   = '';
      payload.returnDropoff  = '';
      payload.trip2Stops     = [];
      payload.returnTripDate = '';
      payload.returnTripTime = '';
    }

    const btn = document.getElementById('saveBtn');
    btn.disabled    = true;
    btn.textContent = 'Saving…';

    try {
      const res  = await fetch('customer-booking.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      const data = await res.json();

      if (data.error) {
        errEl.textContent = data.error;
        errEl.classList.remove('hidden');
        return;
      }

      currentBooking = data.booking;
      renderSummary(currentBooking);

      sucEl.textContent = 'Your booking has been updated successfully!';
      sucEl.classList.remove('hidden');

      setTimeout(() => showSummary(), 1800);

    } catch (err) {
      errEl.textContent = 'Could not save. Please try again.';
      errEl.classList.remove('hidden');
    } finally {
      btn.disabled    = false;
      btn.textContent = 'Save changes';
    }
  }

  // ---- CANCEL ----
  function closeBooking() {
    // Go back to the lookup form
    document.getElementById('bookingSection').classList.add('hidden');
    document.getElementById('lookupSection').classList.remove('hidden');
    document.getElementById('lookupConfNum').value = '';
    document.getElementById('lookupEmail').value = '';
    currentBooking = null;
  }

  function confirmCancel() {
    if (!confirm('Are you sure you want to cancel this booking? This cannot be undone.')) return;
    cancelBooking();
  }

  async function cancelBooking() {
    try {
      const res  = await fetch('customer-booking.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          action:             'cancel',
          confirmationNumber: currentBooking.confirmationNumber,
          email:              currentBooking.email
        })
      });
      const data = await res.json();

      if (data.error) {
        alert(data.error);
        return;
      }

      currentBooking.paymentStatus = 'Cancelled';
      renderSummary(currentBooking);

    } catch (err) {
      alert('Could not cancel. Please try again or call the office.');
    }
  }

  // Lookup on Enter key
  document.addEventListener('keydown', e => {
    if (e.key === 'Enter' && !document.getElementById('lookupSection').classList.contains('hidden')) {
      lookupBooking();
    }
  });
</script>
</body>
</html>