// Mock data — Bali Drive Rentcar (BDR)
// Rental mobil menengah, 3 cabang di Bali, ±60 armada, dengan GPS tracking live.

const TENANT = {
  name: 'Bali Drive Rentcar',
  legal: 'PT Bali Drive Nusantara',
  short: 'BDR',
  npwp: '02.876.543.2-901.000',
  hq: 'Jl. Imam Bonjol No. 312, Denpasar, Bali',
  phone: '0361-485-7700',
  wa: '+62 812-3899-7700',
  email: 'reservasi@balidriverentcar.id',
  web: 'balidriverentcar.id',
  segment: 'Rental mobil harian, mingguan, bulanan — self drive & with driver',
  established: 2017,
};

const TODAY = '2026-05-21';
const NOW_HHMM = '14:38';
const SHIFT = 'Siang (10:00 — 18:00)';

const PERIOD_LIST = [
  { id: '2026-03', label: 'Maret 2026' },
  { id: '2026-04', label: 'April 2026' },
  { id: '2026-05', label: 'Mei 2026' },
];
const CURRENT_PERIOD = '2026-05';

// Cabang
const CABANG = [
  { id: 'dps', name: 'HQ Denpasar',  addr: 'Jl. Imam Bonjol 312, Denpasar', lat: -8.6705, lng: 115.2126, armada: 28, head: 'Made Wirawan' },
  { id: 'kut', name: 'Pool Kuta',    addr: 'Jl. Sunset Road 88, Kuta',      lat: -8.7180, lng: 115.1745, armada: 22, head: 'Ketut Sudarsana' },
  { id: 'ubd', name: 'Pool Ubud',    addr: 'Jl. Raya Ubud 145, Gianyar',    lat: -8.5070, lng: 115.2625, armada: 12, head: 'Gusti Ngurah Adi' },
];

// Roles
const ROLES = {
  admin: {
    id: 'admin', name: 'Putu Ariyani', title: 'Admin / CS', initials: 'PA', cabang: 'dps',
    can: { booking: true, armada: true, dispatch: true, tracking: true, maintenance: false, customer: true, report: false, finance: false, settings: false },
  },
  dispatcher: {
    id: 'dispatcher', name: 'Komang Wijaya', title: 'Dispatcher', initials: 'KW', cabang: 'dps',
    can: { booking: true, armada: true, dispatch: true, tracking: true, maintenance: false, customer: false, report: false, finance: false, settings: false },
  },
  driver: {
    id: 'driver', name: 'Wayan Surya', title: 'Driver — Senior', initials: 'WS', cabang: 'dps',
    can: { booking: false, armada: false, dispatch: false, tracking: true, maintenance: false, customer: false, report: false, finance: false, settings: false },
  },
  mekanik: {
    id: 'mekanik', name: 'Pak Sudirja', title: 'Mekanik / Workshop', initials: 'SJ', cabang: 'dps',
    can: { booking: false, armada: true, dispatch: false, tracking: false, maintenance: true, customer: false, report: false, finance: false, settings: false },
  },
  owner: {
    id: 'owner', name: 'Ibu Anita Dharma', title: 'Owner / Manajer', initials: 'AD', cabang: 'dps',
    can: { booking: true, armada: true, dispatch: true, tracking: true, maintenance: true, customer: true, report: true, finance: true, settings: true },
  },
  customer: {
    id: 'customer', name: 'Andika Pratama', title: 'Tamu — Customer', initials: 'AP', cabang: '—',
    can: { booking: true, armada: false, dispatch: false, tracking: true, maintenance: false, customer: false, report: false, finance: false, settings: false },
  },
};

// Kategori armada
const KATEGORI = [
  { id: 'all',     label: 'Semua' },
  { id: 'city',    label: 'City Car' },
  { id: 'mpv',     label: 'MPV Keluarga' },
  { id: 'suv',     label: 'SUV' },
  { id: 'premium', label: 'Premium' },
  { id: 'van',     label: 'Van / Hiace' },
  { id: 'matic',   label: 'Matic' },
  { id: 'manual',  label: 'Manual' },
];

// Armada — 60 mobil
const ARMADA = [
  // City car
  { id: 'BDR-001', plat: 'DK 1101 AB', merk: 'Toyota',   model: 'Agya G',          tipe: 'city',    trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 5, bbm: 'bensin', tarif: 275_000, cabang: 'dps', status: 'available', odo: 24_500, lastService: '2026-04-12', nextService: 30_000 },
  { id: 'BDR-002', plat: 'DK 1102 AB', merk: 'Daihatsu', model: 'Ayla X',          tipe: 'city',    trans: 'manual', thn: 2022, warna: 'Silver',  seat: 5, bbm: 'bensin', tarif: 250_000, cabang: 'dps', status: 'rented',    odo: 41_200, lastService: '2026-03-22', nextService: 45_000 },
  { id: 'BDR-003', plat: 'DK 1103 AB', merk: 'Honda',    model: 'Brio Satya E',    tipe: 'city',    trans: 'matic',  thn: 2024, warna: 'Merah',   seat: 5, bbm: 'bensin', tarif: 300_000, cabang: 'dps', status: 'available', odo:  8_120, lastService: '2026-05-01', nextService: 15_000 },
  { id: 'BDR-004', plat: 'DK 1104 AB', merk: 'Toyota',   model: 'Agya G TRD',      tipe: 'city',    trans: 'matic',  thn: 2023, warna: 'Hitam',   seat: 5, bbm: 'bensin', tarif: 285_000, cabang: 'kut', status: 'rented',    odo: 32_900, lastService: '2026-04-05', nextService: 35_000 },
  { id: 'BDR-005', plat: 'DK 1105 AB', merk: 'Suzuki',   model: 'Karimun Wagon',   tipe: 'city',    trans: 'manual', thn: 2021, warna: 'Putih',   seat: 5, bbm: 'bensin', tarif: 235_000, cabang: 'kut', status: 'cleaning',  odo: 56_700, lastService: '2026-04-28', nextService: 60_000 },
  { id: 'BDR-006', plat: 'DK 1106 AB', merk: 'Honda',    model: 'Brio RS',         tipe: 'city',    trans: 'matic',  thn: 2024, warna: 'Kuning',  seat: 5, bbm: 'bensin', tarif: 320_000, cabang: 'dps', status: 'available', odo: 12_400, lastService: '2026-04-18', nextService: 20_000 },
  { id: 'BDR-007', plat: 'DK 1107 AB', merk: 'Daihatsu', model: 'Sigra X',         tipe: 'city',    trans: 'manual', thn: 2022, warna: 'Silver',  seat: 7, bbm: 'bensin', tarif: 285_000, cabang: 'ubd', status: 'rented',    odo: 38_800, lastService: '2026-03-30', nextService: 40_000 },

  // MPV keluarga
  { id: 'BDR-101', plat: 'DK 2201 BC', merk: 'Toyota',   model: 'Avanza G',        tipe: 'mpv',     trans: 'manual', thn: 2022, warna: 'Silver',  seat: 7, bbm: 'bensin', tarif: 375_000, cabang: 'dps', status: 'rented',    odo: 52_100, lastService: '2026-04-02', nextService: 55_000 },
  { id: 'BDR-102', plat: 'DK 2202 BC', merk: 'Toyota',   model: 'Avanza Veloz',    tipe: 'mpv',     trans: 'matic',  thn: 2023, warna: 'Hitam',   seat: 7, bbm: 'bensin', tarif: 425_000, cabang: 'dps', status: 'rented',    odo: 28_300, lastService: '2026-04-20', nextService: 35_000 },
  { id: 'BDR-103', plat: 'DK 2203 BC', merk: 'Daihatsu', model: 'Xenia R',         tipe: 'mpv',     trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 7, bbm: 'bensin', tarif: 395_000, cabang: 'kut', status: 'available', odo: 19_500, lastService: '2026-05-08', nextService: 25_000 },
  { id: 'BDR-104', plat: 'DK 2204 BC', merk: 'Mitsubishi', model: 'Xpander Cross', tipe: 'mpv',     trans: 'matic',  thn: 2024, warna: 'Bronze',  seat: 7, bbm: 'bensin', tarif: 525_000, cabang: 'dps', status: 'rented',    odo: 11_800, lastService: '2026-04-25', nextService: 20_000 },
  { id: 'BDR-105', plat: 'DK 2205 BC', merk: 'Mitsubishi', model: 'Xpander Ultimate', tipe: 'mpv',  trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 7, bbm: 'bensin', tarif: 495_000, cabang: 'kut', status: 'available', odo: 31_400, lastService: '2026-04-10', nextService: 35_000 },
  { id: 'BDR-106', plat: 'DK 2206 BC', merk: 'Toyota',   model: 'Avanza Veloz',    tipe: 'mpv',     trans: 'matic',  thn: 2022, warna: 'Silver',  seat: 7, bbm: 'bensin', tarif: 410_000, cabang: 'ubd', status: 'rented',    odo: 48_600, lastService: '2026-03-18', nextService: 50_000 },
  { id: 'BDR-107', plat: 'DK 2207 BC', merk: 'Honda',    model: 'Mobilio E',       tipe: 'mpv',     trans: 'matic',  thn: 2022, warna: 'Abu-abu', seat: 7, bbm: 'bensin', tarif: 395_000, cabang: 'kut', status: 'maintenance', odo: 62_100, lastService: '2026-05-15', nextService: 65_000 },
  { id: 'BDR-108', plat: 'DK 2208 BC', merk: 'Suzuki',   model: 'Ertiga GX',       tipe: 'mpv',     trans: 'matic',  thn: 2023, warna: 'Merah',   seat: 7, bbm: 'bensin', tarif: 415_000, cabang: 'dps', status: 'rented',    odo: 22_700, lastService: '2026-04-15', nextService: 25_000 },
  { id: 'BDR-109', plat: 'DK 2209 BC', merk: 'Suzuki',   model: 'Ertiga Sport',    tipe: 'mpv',     trans: 'manual', thn: 2022, warna: 'Hitam',   seat: 7, bbm: 'bensin', tarif: 385_000, cabang: 'dps', status: 'available', odo: 44_200, lastService: '2026-04-08', nextService: 50_000 },
  { id: 'BDR-110', plat: 'DK 2210 BC', merk: 'Toyota',   model: 'Calya G',         tipe: 'mpv',     trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 7, bbm: 'bensin', tarif: 365_000, cabang: 'ubd', status: 'available', odo: 27_900, lastService: '2026-04-22', nextService: 30_000 },

  // SUV
  { id: 'BDR-201', plat: 'DK 3301 CD', merk: 'Toyota',   model: 'Rush G TRD',      tipe: 'suv',     trans: 'matic',  thn: 2023, warna: 'Hitam',   seat: 7, bbm: 'bensin', tarif: 575_000, cabang: 'dps', status: 'rented',    odo: 26_300, lastService: '2026-04-12', nextService: 30_000 },
  { id: 'BDR-202', plat: 'DK 3302 CD', merk: 'Daihatsu', model: 'Terios R',        tipe: 'suv',     trans: 'matic',  thn: 2022, warna: 'Putih',   seat: 7, bbm: 'bensin', tarif: 545_000, cabang: 'kut', status: 'rented',    odo: 41_500, lastService: '2026-03-25', nextService: 45_000 },
  { id: 'BDR-203', plat: 'DK 3303 CD', merk: 'Honda',    model: 'BR-V Prestige',   tipe: 'suv',     trans: 'matic',  thn: 2024, warna: 'Silver',  seat: 7, bbm: 'bensin', tarif: 625_000, cabang: 'dps', status: 'available', odo: 14_800, lastService: '2026-05-02', nextService: 20_000 },
  { id: 'BDR-204', plat: 'DK 3304 CD', merk: 'Toyota',   model: 'Raize GR Sport',  tipe: 'suv',     trans: 'matic',  thn: 2024, warna: 'Merah',   seat: 5, bbm: 'bensin', tarif: 595_000, cabang: 'dps', status: 'rented',    odo:  9_400, lastService: '2026-05-05', nextService: 15_000 },
  { id: 'BDR-205', plat: 'DK 3305 CD', merk: 'Honda',    model: 'HR-V SE',         tipe: 'suv',     trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 5, bbm: 'bensin', tarif: 745_000, cabang: 'kut', status: 'available', odo: 21_200, lastService: '2026-04-28', nextService: 25_000 },
  { id: 'BDR-206', plat: 'DK 3306 CD', merk: 'Mitsubishi', model: 'Pajero Sport', tipe: 'suv',     trans: 'matic',  thn: 2022, warna: 'Hitam',   seat: 7, bbm: 'solar',  tarif: 1_250_000, cabang: 'dps', status: 'rented', odo: 58_700, lastService: '2026-04-01', nextService: 60_000 },
  { id: 'BDR-207', plat: 'DK 3307 CD', merk: 'Toyota',   model: 'Fortuner VRZ',    tipe: 'suv',     trans: 'matic',  thn: 2023, warna: 'Putih',   seat: 7, bbm: 'solar',  tarif: 1_450_000, cabang: 'dps', status: 'available', odo: 33_600, lastService: '2026-04-18', nextService: 40_000 },
  { id: 'BDR-208', plat: 'DK 3308 CD', merk: 'Toyota',   model: 'Fortuner GR',     tipe: 'suv',     trans: 'matic',  thn: 2024, warna: 'Hitam',   seat: 7, bbm: 'solar',  tarif: 1_650_000, cabang: 'kut', status: 'rented',    odo: 12_100, lastService: '2026-05-03', nextService: 20_000 },

  // Premium
  { id: 'BDR-301', plat: 'DK 4401 DE', merk: 'Toyota',   model: 'Alphard 2.5 G',   tipe: 'premium', trans: 'matic',  thn: 2023, warna: 'Hitam',   seat: 7, bbm: 'bensin', tarif: 2_750_000, cabang: 'dps', status: 'available', odo: 18_500, lastService: '2026-04-30', nextService: 25_000 },
  { id: 'BDR-302', plat: 'DK 4402 DE', merk: 'Toyota',   model: 'Alphard Hybrid',  tipe: 'premium', trans: 'matic',  thn: 2024, warna: 'Putih',   seat: 7, bbm: 'hybrid', tarif: 3_250_000, cabang: 'dps', status: 'rented',    odo:  7_200, lastService: '2026-05-10', nextService: 15_000 },
  { id: 'BDR-303', plat: 'DK 4403 DE', merk: 'Toyota',   model: 'Vellfire 2.5 ZG', tipe: 'premium', trans: 'matic',  thn: 2022, warna: 'Hitam',   seat: 7, bbm: 'bensin', tarif: 2_950_000, cabang: 'dps', status: 'available', odo: 38_900, lastService: '2026-04-14', nextService: 40_000 },
  { id: 'BDR-304', plat: 'DK 4404 DE', merk: 'Mercedes', model: 'E-Class E200',    tipe: 'premium', trans: 'matic',  thn: 2022, warna: 'Putih',   seat: 5, bbm: 'bensin', tarif: 2_450_000, cabang: 'kut', status: 'available', odo: 29_400, lastService: '2026-04-22', nextService: 35_000 },
  { id: 'BDR-305', plat: 'DK 4405 DE', merk: 'BMW',      model: '520i Luxury',     tipe: 'premium', trans: 'matic',  thn: 2023, warna: 'Hitam',   seat: 5, bbm: 'bensin', tarif: 2_650_000, cabang: 'kut', status: 'rented',    odo: 16_800, lastService: '2026-05-06', nextService: 20_000 },

  // Van / Hiace
  { id: 'BDR-401', plat: 'DK 5501 EF', merk: 'Toyota',   model: 'Hiace Commuter',  tipe: 'van',     trans: 'manual', thn: 2022, warna: 'Putih',   seat: 15, bbm: 'solar', tarif: 1_350_000, cabang: 'dps', status: 'rented',   odo: 78_400, lastService: '2026-03-28', nextService: 80_000 },
  { id: 'BDR-402', plat: 'DK 5502 EF', merk: 'Toyota',   model: 'Hiace Premio',    tipe: 'van',     trans: 'manual', thn: 2023, warna: 'Putih',   seat: 14, bbm: 'solar', tarif: 1_550_000, cabang: 'dps', status: 'available', odo: 42_100, lastService: '2026-04-15', nextService: 45_000 },
  { id: 'BDR-403', plat: 'DK 5503 EF', merk: 'Isuzu',    model: 'Elf Microbus',    tipe: 'van',     trans: 'manual', thn: 2021, warna: 'Putih',   seat: 16, bbm: 'solar', tarif: 1_250_000, cabang: 'kut', status: 'rented',   odo: 95_200, lastService: '2026-03-12', nextService: 100_000 },
  { id: 'BDR-404', plat: 'DK 5504 EF', merk: 'Toyota',   model: 'Hiace Commuter',  tipe: 'van',     trans: 'manual', thn: 2022, warna: 'Putih',   seat: 15, bbm: 'solar', tarif: 1_350_000, cabang: 'kut', status: 'available', odo: 67_800, lastService: '2026-04-08', nextService: 70_000 },
  { id: 'BDR-405', plat: 'DK 5505 EF', merk: 'Toyota',   model: 'Hiace Premio',    tipe: 'van',     trans: 'manual', thn: 2024, warna: 'Hitam',   seat: 14, bbm: 'solar', tarif: 1_650_000, cabang: 'dps', status: 'maintenance', odo: 22_500, lastService: '2026-05-18', nextService: 25_000 },
];
const ARMADA_BY_ID = Object.fromEntries(ARMADA.map(a => [a.id, a]));

// Status armada label/tone untuk grid armada
const STATUS_ARMADA = ['available', 'rented', 'cleaning', 'maintenance', 'reserved'];

// Pelanggan
const CUSTOMERS = [
  { id: 'C-2401', nama: 'Andika Pratama',        wa: '+62 812-7788-9911', email: 'andika@mail.com',     ktp: '3174042504900012', sim: 'A — 2028-04', kota: 'Jakarta',   sejak: '2024-09-12', total_booking: 4, total_spend: 8_450_000, rating: 4.9, status: 'aktif',     blacklist: false },
  { id: 'C-2402', nama: 'Putri Maharani',        wa: '+62 813-2233-4455', email: 'putri.m@mail.com',    ktp: '3273011102950023', sim: 'A — 2027-11', kota: 'Bandung',   sejak: '2024-11-08', total_booking: 2, total_spend: 3_200_000, rating: 4.7, status: 'aktif',     blacklist: false },
  { id: 'C-2403', nama: 'Kevin Tanudjaja',       wa: '+62 811-9988-0022', email: 'kevin.t@mail.com',    ktp: '3174081709890045', sim: 'A — 2026-08', kota: 'Surabaya',  sejak: '2023-05-20', total_booking: 9, total_spend: 22_800_000, rating: 5.0, status: 'vip',     blacklist: false },
  { id: 'C-2404', nama: 'Sari Wulandari',        wa: '+62 815-4422-1133', email: 'sari.w@mail.com',     ktp: '3578012806920067', sim: 'A — 2028-12', kota: 'Yogyakarta',sejak: '2025-01-15', total_booking: 3, total_spend: 5_950_000, rating: 4.8, status: 'aktif',     blacklist: false },
  { id: 'C-2405', nama: 'Reza Firmansyah',       wa: '+62 822-7766-5544', email: 'reza.f@mail.com',     ktp: '3175082311880089', sim: 'A — 2027-06', kota: 'Jakarta',   sejak: '2024-06-22', total_booking: 6, total_spend: 14_200_000, rating: 4.6, status: 'aktif',     blacklist: false },
  { id: 'C-2406', nama: 'Maria Christine Tan',   wa: '+65 9778-2211',     email: 'mctan@mail.sg',        ktp: 'PASSPORT-SG E78992', sim: 'IDP — 2027', kota: 'Singapore', sejak: '2025-02-10', total_booking: 1, total_spend: 7_500_000, rating: 5.0, status: 'aktif',  blacklist: false, asing: true },
  { id: 'C-2407', nama: 'Daniel Anderson',       wa: '+61 4-1122-9988',   email: 'd.anderson@mail.au',   ktp: 'PASSPORT-AU P12345', sim: 'IDP — 2026', kota: 'Sydney',    sejak: '2024-12-03', total_booking: 2, total_spend: 11_300_000, rating: 4.9, status: 'aktif', blacklist: false, asing: true },
  { id: 'C-2408', nama: 'Hendra Wijaya',         wa: '+62 819-3344-7700', email: 'hendra.w@mail.com',   ktp: '3174051208870111', sim: 'A — 2025-03', kota: 'Jakarta',   sejak: '2023-08-15', total_booking: 5, total_spend: 9_700_000, rating: 3.2, status: 'review',   blacklist: false, catatan: 'Pernah denda telat 1 hari + lecet bumper' },
  { id: 'C-2409', nama: 'Bambang Sutejo',        wa: '+62 821-9900-1122', email: 'b.sutejo@mail.com',   ktp: '3578091505800145', sim: 'A — exp',     kota: 'Malang',    sejak: '2022-04-10', total_booking: 1, total_spend: 1_200_000, rating: 2.0, status: 'blacklist', blacklist: true, catatan: 'Kabur tidak return, kasus polisi 2023' },
];
const CUSTOMER_BY_ID = Object.fromEntries(CUSTOMERS.map(c => [c.id, c]));

// Drivers (untuk with-driver service)
const DRIVERS = [
  { id: 'DRV-01', nama: 'Wayan Surya',     initials: 'WS', wa: '+62 813-1122-0011', usia: 38, lisensi: 'A Umum', pengalaman: 12, rating: 4.9, total_trip: 487, status: 'on-trip',  trip_aktif: 'TRP-1018', cabang: 'dps' },
  { id: 'DRV-02', nama: 'Komang Astawa',   initials: 'KA', wa: '+62 813-3344-2233', usia: 32, lisensi: 'A Umum', pengalaman: 8,  rating: 4.8, total_trip: 312, status: 'standby',  trip_aktif: null,       cabang: 'dps' },
  { id: 'DRV-03', nama: 'Nyoman Buana',    initials: 'NB', wa: '+62 813-5566-4455', usia: 41, lisensi: 'B1 Umum',pengalaman: 15, rating: 4.9, total_trip: 612, status: 'on-trip',  trip_aktif: 'TRP-1022', cabang: 'kut' },
  { id: 'DRV-04', nama: 'Gede Mahendra',   initials: 'GM', wa: '+62 813-7788-6677', usia: 29, lisensi: 'A Umum', pengalaman: 5,  rating: 4.6, total_trip: 178, status: 'standby',  trip_aktif: null,       cabang: 'kut' },
  { id: 'DRV-05', nama: 'Ketut Mariawan',  initials: 'KM', wa: '+62 813-9900-8899', usia: 45, lisensi: 'B1 Umum',pengalaman: 20, rating: 5.0, total_trip: 842, status: 'on-trip',  trip_aktif: 'TRP-1025', cabang: 'ubd' },
  { id: 'DRV-06', nama: 'Putu Adnyana',    initials: 'PA', wa: '+62 813-2211-3344', usia: 36, lisensi: 'A Umum', pengalaman: 10, rating: 4.7, total_trip: 398, status: 'libur',    trip_aktif: null,       cabang: 'dps' },
];
const DRIVER_BY_ID = Object.fromEntries(DRIVERS.map(d => [d.id, d]));

// Booking — campuran upcoming, ongoing, done
const BOOKINGS = [
  // Today / ongoing
  { id: 'BKG-30221', cust: 'C-2401', armada: 'BDR-002', driver: null,      mulai: '2026-05-20 09:00', selesai: '2026-05-23 09:00', durasi: 3, layanan: 'self-drive', pickup: 'Bandara Ngurah Rai', dropoff: 'Bandara Ngurah Rai', tarif: 250_000, total:   975_000, dp: 500_000, status: 'ongoing',   trip: 'TRP-1015', dibayar: 'qris', cabang: 'dps' },
  { id: 'BKG-30224', cust: 'C-2403', armada: 'BDR-301', driver: 'DRV-01',  mulai: '2026-05-19 08:00', selesai: '2026-05-22 20:00', durasi: 4, layanan: 'with-driver', pickup: 'Hotel Mulia Nusa Dua', dropoff: 'Bandara Ngurah Rai', tarif: 2_750_000, total: 12_500_000, dp: 6_000_000, status: 'ongoing',   trip: 'TRP-1018', dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30226', cust: 'C-2407', armada: 'BDR-207', driver: null,      mulai: '2026-05-18 14:00', selesai: '2026-05-25 14:00', durasi: 7, layanan: 'self-drive', pickup: 'Pool Kuta',          dropoff: 'Pool Kuta',          tarif: 1_450_000, total: 10_850_000, dp: 5_000_000, status: 'ongoing',   trip: 'TRP-1020', dibayar: 'kartu',    cabang: 'kut' },
  { id: 'BKG-30228', cust: 'C-2406', armada: 'BDR-104', driver: 'DRV-03',  mulai: '2026-05-21 06:30', selesai: '2026-05-21 22:00', durasi: 1, layanan: 'with-driver', pickup: 'Hotel The Mulia',     dropoff: 'Hotel The Mulia',    tarif:   525_000, total:  1_450_000, dp:   750_000, status: 'ongoing',   trip: 'TRP-1022', dibayar: 'qris',    cabang: 'kut' },
  { id: 'BKG-30231', cust: 'C-2402', armada: 'BDR-102', driver: null,      mulai: '2026-05-21 10:00', selesai: '2026-05-23 10:00', durasi: 2, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   425_000, total:    975_000, dp:   500_000, status: 'ongoing',   trip: 'TRP-1024', dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30232', cust: 'C-2405', armada: 'BDR-206', driver: 'DRV-05',  mulai: '2026-05-20 07:00', selesai: '2026-05-24 18:00', durasi: 5, layanan: 'with-driver', pickup: 'Villa Ubud Hanging',  dropoff: 'Villa Ubud Hanging', tarif: 1_250_000, total:  7_650_000, dp: 4_000_000, status: 'ongoing',   trip: 'TRP-1025', dibayar: 'transfer', cabang: 'ubd' },
  { id: 'BKG-30234', cust: 'C-2404', armada: 'BDR-204', driver: null,      mulai: '2026-05-21 11:00', selesai: '2026-05-22 11:00', durasi: 1, layanan: 'self-drive', pickup: 'Bandara Ngurah Rai', dropoff: 'Bandara Ngurah Rai', tarif:   595_000, total:    745_000, dp:   400_000, status: 'ongoing',   trip: 'TRP-1027', dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30236', cust: 'C-2401', armada: 'BDR-004', driver: null,      mulai: '2026-05-20 16:00', selesai: '2026-05-22 16:00', durasi: 2, layanan: 'self-drive', pickup: 'Pool Kuta',          dropoff: 'Pool Kuta',          tarif:   285_000, total:    645_000, dp:   350_000, status: 'ongoing',   trip: 'TRP-1029', dibayar: 'cash',    cabang: 'kut' },
  { id: 'BKG-30238', cust: 'C-2403', armada: 'BDR-101', driver: null,      mulai: '2026-05-19 12:00', selesai: '2026-05-22 12:00', durasi: 3, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   375_000, total:  1_275_000, dp:   650_000, status: 'ongoing',   trip: 'TRP-1031', dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30240', cust: 'C-2405', armada: 'BDR-201', driver: null,      mulai: '2026-05-20 18:00', selesai: '2026-05-23 18:00', durasi: 3, layanan: 'self-drive', pickup: 'Hotel Padma Legian',  dropoff: 'Hotel Padma Legian', tarif:   575_000, total:  1_875_000, dp: 1_000_000, status: 'ongoing',   trip: 'TRP-1033', dibayar: 'kartu',   cabang: 'dps' },
  { id: 'BKG-30242', cust: 'C-2402', armada: 'BDR-008', driver: null,      mulai: '2026-05-20 09:00', selesai: '2026-05-21 21:00', durasi: 1, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   285_000, total:    485_000, dp:   285_000, status: 'ongoing',   trip: 'TRP-1035', dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30244', cust: 'C-2407', armada: 'BDR-401', driver: 'DRV-02',  mulai: '2026-05-20 05:00', selesai: '2026-05-22 22:00', durasi: 3, layanan: 'with-driver', pickup: 'Bandara Ngurah Rai',  dropoff: 'Bandara Ngurah Rai', tarif: 1_350_000, total:  5_950_000, dp: 3_000_000, status: 'ongoing',   trip: 'TRP-1037', dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30246', cust: 'C-2403', armada: 'BDR-208', driver: null,      mulai: '2026-05-19 10:00', selesai: '2026-05-26 10:00', durasi: 7, layanan: 'self-drive', pickup: 'Pool Kuta',          dropoff: 'Pool Kuta',          tarif: 1_650_000, total: 12_300_000, dp: 6_000_000, status: 'ongoing',   trip: 'TRP-1039', dibayar: 'transfer', cabang: 'kut' },
  { id: 'BKG-30248', cust: 'C-2405', armada: 'BDR-302', driver: 'DRV-01',  mulai: '2026-05-18 06:00', selesai: '2026-05-22 23:00', durasi: 5, layanan: 'with-driver', pickup: 'Hotel Conrad Bali',   dropoff: 'Bandara Ngurah Rai', tarif: 3_250_000, total: 18_750_000, dp: 9_000_000, status: 'ongoing',   trip: 'TRP-1041', dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30250', cust: 'C-2406', armada: 'BDR-305', driver: null,      mulai: '2026-05-20 14:00', selesai: '2026-05-23 14:00', durasi: 3, layanan: 'self-drive', pickup: 'Hotel Mulia Nusa Dua', dropoff: 'Hotel Mulia Nusa Dua', tarif: 2_650_000, total:  8_650_000, dp: 4_500_000, status: 'ongoing', trip: 'TRP-1043', dibayar: 'kartu',  cabang: 'kut' },
  { id: 'BKG-30252', cust: 'C-2404', armada: 'BDR-106', driver: null,      mulai: '2026-05-19 09:00', selesai: '2026-05-22 09:00', durasi: 3, layanan: 'self-drive', pickup: 'Pool Ubud',          dropoff: 'Pool Ubud',          tarif:   410_000, total:  1_375_000, dp:   700_000, status: 'ongoing',   trip: 'TRP-1045', dibayar: 'qris',    cabang: 'ubd' },
  { id: 'BKG-30254', cust: 'C-2402', armada: 'BDR-403', driver: 'DRV-04',  mulai: '2026-05-20 08:00', selesai: '2026-05-22 20:00', durasi: 3, layanan: 'with-driver', pickup: 'Hotel Inaya Putri',   dropoff: 'Hotel Inaya Putri',  tarif: 1_250_000, total:  4_950_000, dp: 2_500_000, status: 'ongoing',   trip: 'TRP-1047', dibayar: 'transfer', cabang: 'kut' },
  { id: 'BKG-30256', cust: 'C-2401', armada: 'BDR-202', driver: null,      mulai: '2026-05-21 13:00', selesai: '2026-05-22 13:00', durasi: 1, layanan: 'self-drive', pickup: 'Bandara Ngurah Rai', dropoff: 'Bandara Ngurah Rai', tarif:   545_000, total:    695_000, dp:   400_000, status: 'ongoing',   trip: 'TRP-1049', dibayar: 'qris',    cabang: 'kut' },

  // Upcoming
  { id: 'BKG-30260', cust: 'C-2404', armada: 'BDR-003', driver: null,      mulai: '2026-05-22 10:00', selesai: '2026-05-24 10:00', durasi: 2, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   300_000, total:    675_000, dp:   350_000, status: 'confirmed', trip: null,         dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30262', cust: 'C-2402', armada: 'BDR-103', driver: null,      mulai: '2026-05-22 14:00', selesai: '2026-05-25 14:00', durasi: 3, layanan: 'self-drive', pickup: 'Bandara Ngurah Rai', dropoff: 'Bandara Ngurah Rai', tarif:   395_000, total:  1_300_000, dp:   650_000, status: 'confirmed', trip: null,         dibayar: 'transfer', cabang: 'kut' },
  { id: 'BKG-30264', cust: 'C-2406', armada: 'BDR-301', driver: 'DRV-05',  mulai: '2026-05-23 06:00', selesai: '2026-05-26 22:00', durasi: 4, layanan: 'with-driver', pickup: 'Hotel The Mulia',     dropoff: 'Hotel The Mulia',    tarif: 2_750_000, total: 12_650_000, dp: 6_500_000, status: 'confirmed', trip: null,         dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30266', cust: 'C-2407', armada: 'BDR-205', driver: null,      mulai: '2026-05-22 09:00', selesai: '2026-05-29 09:00', durasi: 7, layanan: 'self-drive', pickup: 'Pool Kuta',          dropoff: 'Pool Kuta',          tarif:   745_000, total:  5_550_000, dp: 2_800_000, status: 'confirmed', trip: null,         dibayar: 'kartu',   cabang: 'kut' },
  { id: 'BKG-30268', cust: 'C-2403', armada: 'BDR-402', driver: 'DRV-02',  mulai: '2026-05-24 05:00', selesai: '2026-05-27 22:00', durasi: 4, layanan: 'with-driver', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif: 1_550_000, total:  7_450_000, dp: 3_800_000, status: 'confirmed', trip: null,         dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30270', cust: 'C-2401', armada: 'BDR-006', driver: null,      mulai: '2026-05-23 12:00', selesai: '2026-05-24 12:00', durasi: 1, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   320_000, total:    470_000, dp:   250_000, status: 'pending',   trip: null,         dibayar: 'pending', cabang: 'dps' },
  { id: 'BKG-30272', cust: 'C-2405', armada: 'BDR-203', driver: null,      mulai: '2026-05-25 08:00', selesai: '2026-05-28 08:00', durasi: 3, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   625_000, total:  2_025_000, dp: 1_000_000, status: 'pending',   trip: null,         dibayar: 'pending', cabang: 'dps' },
  { id: 'BKG-30274', cust: 'C-2402', armada: 'BDR-109', driver: null,      mulai: '2026-05-24 09:00', selesai: '2026-05-26 09:00', durasi: 2, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   385_000, total:    895_000, dp:   450_000, status: 'confirmed', trip: null,         dibayar: 'qris',    cabang: 'dps' },

  // Past / done
  { id: 'BKG-30180', cust: 'C-2401', armada: 'BDR-101', driver: null,      mulai: '2026-05-10 09:00', selesai: '2026-05-13 09:00', durasi: 3, layanan: 'self-drive', pickup: 'Pool Denpasar',       dropoff: 'Pool Denpasar',      tarif:   375_000, total:  1_275_000, dp: 1_275_000, status: 'done',      trip: 'TRP-0998',   dibayar: 'qris',    cabang: 'dps' },
  { id: 'BKG-30185', cust: 'C-2403', armada: 'BDR-301', driver: 'DRV-01',  mulai: '2026-05-08 06:00', selesai: '2026-05-11 22:00', durasi: 4, layanan: 'with-driver', pickup: 'Bandara Ngurah Rai', dropoff: 'Bandara Ngurah Rai', tarif: 2_750_000, total: 12_650_000, dp:12_650_000, status: 'done',     trip: 'TRP-1003',   dibayar: 'transfer', cabang: 'dps' },
  { id: 'BKG-30192', cust: 'C-2408', armada: 'BDR-005', driver: null,      mulai: '2026-05-12 10:00', selesai: '2026-05-14 11:00', durasi: 2, layanan: 'self-drive', pickup: 'Pool Kuta',          dropoff: 'Pool Kuta',          tarif:   235_000, total:    645_000, dp:   645_000, status: 'done',      trip: 'TRP-1007',  dibayar: 'cash',    cabang: 'kut', catatan: 'Telat return 1 jam — denda Rp 50.000' },
];

// Trip aktif — dengan koordinat lat/lng di Bali untuk GPS tracking
// Lokasi tersebar: Denpasar, Kuta, Seminyak, Ubud, Tegallalang, Nusa Dua, Sanur, Tanah Lot, Bedugul
const TRIPS = [
  { id: 'TRP-1015', booking: 'BKG-30221', armada: 'BDR-002', driver: null,     status: 'in-trip', lokasi: 'Sanur',          lat: -8.6850, lng: 115.2620, kecepatan: 42, heading: 'Utara',  bbm_pct: 65, odo_now: 41_412, jarak_km: 212, ig_on: '2026-05-20 09:14', last_ping: '14:36', driver_name: 'Putri Maharani (self)' },
  { id: 'TRP-1018', booking: 'BKG-30224', armada: 'BDR-301', driver: 'DRV-01', status: 'in-trip', lokasi: 'Ubud — Tegallalang', lat: -8.4310, lng: 115.2790, kecepatan: 35, heading: 'Barat', bbm_pct: 48, odo_now: 18_710, jarak_km: 410, ig_on: '2026-05-19 08:12', last_ping: '14:37', driver_name: 'Wayan Surya' },
  { id: 'TRP-1020', booking: 'BKG-30226', armada: 'BDR-207', driver: null,     status: 'parked',  lokasi: 'Hotel Padma Resort Ubud', lat: -8.5050, lng: 115.2580, kecepatan:  0, heading: '—',     bbm_pct: 72, odo_now: 33_905, jarak_km: 305, ig_on: '2026-05-18 14:08', last_ping: '14:30', driver_name: 'Daniel Anderson (self)' },
  { id: 'TRP-1022', booking: 'BKG-30228', armada: 'BDR-104', driver: 'DRV-03', status: 'in-trip', lokasi: 'Tanah Lot',      lat: -8.6210, lng: 115.0867, kecepatan: 48, heading: 'Selatan',bbm_pct: 56, odo_now: 11_950, jarak_km: 152, ig_on: '2026-05-21 06:38', last_ping: '14:38', driver_name: 'Nyoman Buana' },
  { id: 'TRP-1024', booking: 'BKG-30231', armada: 'BDR-102', driver: null,     status: 'in-trip', lokasi: 'Seminyak',       lat: -8.6850, lng: 115.1640, kecepatan: 28, heading: 'Timur',  bbm_pct: 88, odo_now: 28_410, jarak_km:  48, ig_on: '2026-05-21 10:11', last_ping: '14:37', driver_name: 'Putri Maharani (self)' },
  { id: 'TRP-1025', booking: 'BKG-30232', armada: 'BDR-206', driver: 'DRV-05', status: 'in-trip', lokasi: 'Bedugul — Danau Beratan', lat: -8.2750, lng: 115.1660, kecepatan: 22, heading: 'Barat', bbm_pct: 31, odo_now: 58_950, jarak_km: 380, ig_on: '2026-05-20 07:14', last_ping: '14:35', driver_name: 'Ketut Mariawan' },
  { id: 'TRP-1027', booking: 'BKG-30234', armada: 'BDR-204', driver: null,     status: 'in-trip', lokasi: 'Bandara Ngurah Rai → Kuta', lat: -8.7480, lng: 115.1660, kecepatan: 55, heading: 'Utara',  bbm_pct: 95, odo_now:  9_440, jarak_km:  22, ig_on: '2026-05-21 11:04', last_ping: '14:38', driver_name: 'Sari Wulandari (self)' },
  { id: 'TRP-1029', booking: 'BKG-30236', armada: 'BDR-004', driver: null,     status: 'parked',  lokasi: 'Beachwalk Kuta', lat: -8.7240, lng: 115.1700, kecepatan:  0, heading: '—',     bbm_pct: 42, odo_now: 32_945, jarak_km:  68, ig_on: '2026-05-20 16:08', last_ping: '14:12', driver_name: 'Andika Pratama (self)' },
  { id: 'TRP-1031', booking: 'BKG-30238', armada: 'BDR-101', driver: null,     status: 'in-trip', lokasi: 'Sanur — Pantai Matahari Terbit', lat: -8.6960, lng: 115.2640, kecepatan: 32, heading: 'Selatan',bbm_pct: 58, odo_now: 52_180, jarak_km: 195, ig_on: '2026-05-19 12:09', last_ping: '14:37', driver_name: 'Kevin Tanudjaja (self)' },
  { id: 'TRP-1033', booking: 'BKG-30240', armada: 'BDR-201', driver: null,     status: 'in-trip', lokasi: 'Uluwatu',         lat: -8.8290, lng: 115.0850, kecepatan: 38, heading: 'Barat',  bbm_pct: 51, odo_now: 26_390, jarak_km: 142, ig_on: '2026-05-20 18:11', last_ping: '14:36', driver_name: 'Reza Firmansyah (self)' },
  { id: 'TRP-1035', booking: 'BKG-30242', armada: 'BDR-008', driver: null,     status: 'idle',    lokasi: 'Pool Denpasar',   lat: -8.6705, lng: 115.2126, kecepatan:  0, heading: '—',     bbm_pct: 78, odo_now: 19_500, jarak_km:   8, ig_on: '2026-05-20 09:05', last_ping: '14:38', driver_name: 'Putri Maharani (self)' },
  { id: 'TRP-1037', booking: 'BKG-30244', armada: 'BDR-401', driver: 'DRV-02', status: 'in-trip', lokasi: 'Jl. Bypass Ngurah Rai', lat: -8.7320, lng: 115.2080, kecepatan: 62, heading: 'Selatan',bbm_pct: 38, odo_now: 78_510, jarak_km: 285, ig_on: '2026-05-20 05:14', last_ping: '14:38', driver_name: 'Komang Astawa' },
  { id: 'TRP-1039', booking: 'BKG-30246', armada: 'BDR-208', driver: null,     status: 'in-trip', lokasi: 'Lovina (Buleleng)', lat: -8.1580, lng: 115.0250, kecepatan: 45, heading: 'Timur',  bbm_pct: 28, odo_now: 12_310, jarak_km: 510, ig_on: '2026-05-19 10:18', last_ping: '14:34', driver_name: 'Kevin Tanudjaja (self)', alert: 'bbm-low' },
  { id: 'TRP-1041', booking: 'BKG-30248', armada: 'BDR-302', driver: 'DRV-01', status: 'in-trip', lokasi: 'GWK Cultural Park', lat: -8.8100, lng: 115.1670, kecepatan: 30, heading: 'Utara',  bbm_pct: 67, odo_now:  7_280, jarak_km: 192, ig_on: '2026-05-18 06:08', last_ping: '14:37', driver_name: 'Wayan Surya' },
  { id: 'TRP-1043', booking: 'BKG-30250', armada: 'BDR-305', driver: null,     status: 'parked',  lokasi: 'Hotel Mulia Nusa Dua', lat: -8.8050, lng: 115.2270, kecepatan:  0, heading: '—',     bbm_pct: 84, odo_now: 16_810, jarak_km:  35, ig_on: '2026-05-20 14:06', last_ping: '13:55', driver_name: 'Maria Christine Tan (self)' },
  { id: 'TRP-1045', booking: 'BKG-30252', armada: 'BDR-106', driver: null,     status: 'in-trip', lokasi: 'Pura Tirta Empul',  lat: -8.4150, lng: 115.3140, kecepatan: 25, heading: 'Selatan',bbm_pct: 44, odo_now: 48_710, jarak_km: 168, ig_on: '2026-05-19 09:12', last_ping: '14:36', driver_name: 'Sari Wulandari (self)' },
  { id: 'TRP-1047', booking: 'BKG-30254', armada: 'BDR-403', driver: 'DRV-04', status: 'in-trip', lokasi: 'Jimbaran',         lat: -8.7900, lng: 115.1670, kecepatan: 18, heading: 'Utara',  bbm_pct: 35, odo_now: 95_320, jarak_km: 220, ig_on: '2026-05-20 08:09', last_ping: '14:37', driver_name: 'Gede Mahendra' },
  { id: 'TRP-1049', booking: 'BKG-30256', armada: 'BDR-202', driver: null,     status: 'in-trip', lokasi: 'Tol Bali Mandara', lat: -8.7390, lng: 115.2100, kecepatan: 78, heading: 'Selatan',bbm_pct: 91, odo_now: 41_590, jarak_km:  18, ig_on: '2026-05-21 13:08', last_ping: '14:38', driver_name: 'Andika Pratama (self)', alert: 'overspeed' },
];
const TRIP_BY_ID = Object.fromEntries(TRIPS.map(t => [t.id, t]));

// Route history (mock polyline) — bentuk perjalanan TRP-1018 dari Denpasar → Ubud → Tegallalang
const TRIP_ROUTE_DEMO = [
  { lat: -8.6705, lng: 115.2126, t: '08:12' },
  { lat: -8.6500, lng: 115.2200, t: '08:32' },
  { lat: -8.6200, lng: 115.2380, t: '09:05' },
  { lat: -8.5800, lng: 115.2500, t: '09:38' },
  { lat: -8.5400, lng: 115.2580, t: '10:20' },
  { lat: -8.5070, lng: 115.2625, t: '11:05' },
  { lat: -8.4800, lng: 115.2700, t: '12:30' },
  { lat: -8.4500, lng: 115.2780, t: '13:45' },
  { lat: -8.4310, lng: 115.2790, t: '14:37' },
];

// Maintenance jobs
const MAINTENANCE = [
  { id: 'WO-3201', armada: 'BDR-107', jenis: 'Servis Berkala 60.000 KM', mekanik: 'Pak Sudirja',   masuk: '2026-05-19', estimasi: '2026-05-22', status: 'in-progress', biaya: 2_850_000, parts: ['Oli mesin', 'Filter oli', 'Filter udara', 'Busi'], odo: 62_100, prioritas: 'normal' },
  { id: 'WO-3202', armada: 'BDR-405', jenis: 'Ganti Kopling Set',       mekanik: 'Pak Sudirja',   masuk: '2026-05-18', estimasi: '2026-05-25', status: 'in-progress', biaya: 8_500_000, parts: ['Kopling set Hiace', 'Oli transmisi', 'Filter solar'], odo: 22_500, prioritas: 'tinggi' },
  { id: 'WO-3203', armada: 'BDR-005', jenis: 'Cuci & Detailing',        mekanik: 'Tim Detailing', masuk: '2026-05-21', estimasi: '2026-05-21', status: 'in-progress', biaya:   150_000, parts: [], odo: 56_700, prioritas: 'rendah' },
  { id: 'WO-3204', armada: 'BDR-203', jenis: 'Tukar Ban (4 ban)',       mekanik: 'Pak Sudirja',   masuk: '2026-05-22', estimasi: '2026-05-22', status: 'scheduled',   biaya: 5_200_000, parts: ['Ban Bridgestone 215/65 R16 x4'], odo: 19_500, prioritas: 'normal' },
  { id: 'WO-3205', armada: 'BDR-403', jenis: 'Cek AC + Tambah Freon',   mekanik: 'Wayan Mekanik', masuk: '2026-05-23', estimasi: '2026-05-23', status: 'scheduled',   biaya:   450_000, parts: ['Freon R134a 2 kaleng'], odo: 95_200, prioritas: 'normal' },
  { id: 'WO-3206', armada: 'BDR-001', jenis: 'Servis Berkala 30.000 KM', mekanik: 'Pak Sudirja',  masuk: '2026-05-25', estimasi: '2026-05-25', status: 'scheduled',   biaya: 1_650_000, parts: ['Oli mesin', 'Filter oli'], odo: 24_500, prioritas: 'normal' },
  { id: 'WO-3198', armada: 'BDR-102', jenis: 'Perbaikan AC blower',     mekanik: 'Pak Sudirja',   masuk: '2026-05-12', estimasi: '2026-05-13', status: 'done',        biaya:   850_000, parts: ['Motor blower'], odo: 28_100, prioritas: 'normal', selesai: '2026-05-13' },
  { id: 'WO-3199', armada: 'BDR-301', jenis: 'Poles bodi & wax',        mekanik: 'Tim Detailing', masuk: '2026-05-14', estimasi: '2026-05-15', status: 'done',        biaya:   650_000, parts: ['Wax premium', 'Compound'], odo: 18_400, prioritas: 'rendah', selesai: '2026-05-15' },
];

// Alerts / notifikasi operasional
const ALERTS = [
  { id: 'AL-01', tipe: 'bbm-low',    armada: 'BDR-208', trip: 'TRP-1039', sev: 'warn',   pesan: 'BBM tinggal 28% — Driver di Lovina (jauh dari pool)', waktu: '14:32' },
  { id: 'AL-02', tipe: 'overspeed',  armada: 'BDR-202', trip: 'TRP-1049', sev: 'danger', pesan: 'Kecepatan 78 km/jam di Tol Bali Mandara (batas 60)', waktu: '14:38' },
  { id: 'AL-03', tipe: 'idle-long',  armada: 'BDR-008', trip: 'TRP-1035', sev: 'neutral',pesan: 'Mobil parkir di Pool Denpasar > 5 jam — booking aktif?', waktu: '14:20' },
  { id: 'AL-04', tipe: 'service-due',armada: 'BDR-403', trip: null,       sev: 'warn',   pesan: 'Servis berkala 100.000 KM jatuh dalam 4.800 KM', waktu: '13:45' },
  { id: 'AL-05', tipe: 'sim-expire', armada: null,      trip: null,       sev: 'warn',   pesan: 'SIM customer Hendra Wijaya (C-2408) sudah expire — review sebelum booking baru', waktu: '12:10' },
];

// KPI ringkasan untuk Dashboard
const KPI = {
  hari_ini: {
    armada_terpakai: 38,
    armada_idle: 17,
    armada_workshop: 5,
    revenue_hari: 28_450_000,
    booking_baru: 7,
    on_trip: 14,
    alert: 5,
    utilisasi_pct: 63,
  },
  bulan_ini: {
    revenue: 412_800_000,
    booking_total: 187,
    durasi_rata: 3.4,
    utilisasi_pct: 71,
    growth_mom: 12.4, // %
    avg_rating: 4.78,
  },
};

// Trend revenue 14 hari terakhir (untuk sparkline / dashboard)
const REVENUE_14D = [
  { d: '2026-05-08', v: 24_500_000, booking: 11 },
  { d: '2026-05-09', v: 31_200_000, booking: 14 },
  { d: '2026-05-10', v: 28_900_000, booking: 12 },
  { d: '2026-05-11', v: 19_400_000, booking:  8 },
  { d: '2026-05-12', v: 22_100_000, booking:  9 },
  { d: '2026-05-13', v: 26_700_000, booking: 11 },
  { d: '2026-05-14', v: 33_500_000, booking: 15 },
  { d: '2026-05-15', v: 35_200_000, booking: 16 },
  { d: '2026-05-16', v: 38_400_000, booking: 18 },
  { d: '2026-05-17', v: 29_800_000, booking: 13 },
  { d: '2026-05-18', v: 25_600_000, booking: 11 },
  { d: '2026-05-19', v: 32_400_000, booking: 14 },
  { d: '2026-05-20', v: 36_800_000, booking: 17 },
  { d: '2026-05-21', v: 28_450_000, booking:  7 }, // partial — today
];

// Top armada by revenue bulan ini
const TOP_ARMADA = [
  { armada: 'BDR-301', trips: 12, revenue: 38_500_000, rating: 4.95, util_pct: 88 },
  { armada: 'BDR-302', trips:  9, revenue: 32_400_000, rating: 4.92, util_pct: 81 },
  { armada: 'BDR-401', trips: 14, revenue: 24_800_000, rating: 4.80, util_pct: 76 },
  { armada: 'BDR-207', trips: 10, revenue: 22_650_000, rating: 4.85, util_pct: 72 },
  { armada: 'BDR-104', trips: 18, revenue: 18_900_000, rating: 4.78, util_pct: 89 },
  { armada: 'BDR-102', trips: 16, revenue: 16_400_000, rating: 4.72, util_pct: 84 },
  { armada: 'BDR-204', trips: 22, revenue: 15_800_000, rating: 4.81, util_pct: 91 },
  { armada: 'BDR-206', trips:  7, revenue: 14_200_000, rating: 4.88, util_pct: 68 },
];

// Activity feed
const ACTIVITY = [
  { id: 'A01', t: '14:38', actor: 'Komang (Dispatcher)', text: 'Booking BKG-30240 dikonfirmasi — Toyota Rush ke Reza F.', kind: 'booking' },
  { id: 'A02', t: '14:35', actor: 'Sistem GPS',          text: 'Alert overspeed: BDR-202 di Tol Bali Mandara — 78 km/jam.', kind: 'alert' },
  { id: 'A03', t: '14:28', actor: 'Putu (CS)',            text: 'Booking BKG-30270 menunggu DP dari Andika Pratama.', kind: 'booking' },
  { id: 'A04', t: '14:18', actor: 'Wayan Surya (Driver)', text: 'Check-in penumpang di Tegallalang — TRP-1018.', kind: 'trip' },
  { id: 'A05', t: '14:05', actor: 'Pak Sudirja (Mekanik)',text: 'WO-3201 progress 60% — menunggu busi NGK Iridium.', kind: 'maintenance' },
  { id: 'A06', t: '13:50', actor: 'Sistem',               text: 'Auto-reminder dikirim ke Sari Wulandari — return BDR-204 besok 11:00.', kind: 'system' },
  { id: 'A07', t: '13:42', actor: 'Made (HQ)',            text: 'BAST check-out BDR-204 selesai — odo 9.420 KM, BBM penuh.', kind: 'bast' },
  { id: 'A08', t: '13:15', actor: 'Ketut (Pool Kuta)',     text: 'BDR-005 selesai cuci, siap rental ulang jam 15:00.', kind: 'armada' },
];

// Asuransi & denda preset
const ASURANSI = [
  { id: 'TLO',  nama: 'Total Loss Only',         premi_pct:  3.5, deskripsi: 'Hanya cover kerusakan total >75% atau kehilangan.' },
  { id: 'ALL',  nama: 'All Risk',                 premi_pct:  7.0, deskripsi: 'Cover semua kerusakan + kehilangan, deductible Rp 500rb.' },
  { id: 'BASIC',nama: 'Basic Customer Liability', premi_pct:  1.5, deskripsi: 'Cover pihak ke-3 saja, tanggung jawab penyewa untuk bodi.' },
];

const DENDA = [
  { id: 'TELAT-1H',     nama: 'Telat return < 3 jam',    biaya:    50_000 },
  { id: 'TELAT-1H+',    nama: 'Telat return > 3 jam',    biaya:   150_000 },
  { id: 'TELAT-FULL',   nama: 'Telat return > 6 jam',    biaya: '1 hari sewa' },
  { id: 'BBM-KURANG',   nama: 'BBM tidak full saat return', biaya: 'Rp 15.000/L kurang' },
  { id: 'KOTOR-INTERIOR',nama: 'Interior kotor berat',    biaya:   250_000 },
  { id: 'LECET-RINGAN', nama: 'Lecet bodi (per panel)',   biaya: 1_500_000 },
  { id: 'PENYOK-BUMPER',nama: 'Bumper penyok / rusak',    biaya: 3_500_000 },
  { id: 'PECAH-KACA',   nama: 'Pecah kaca depan',         biaya: 4_500_000 },
  { id: 'HILANG-KUNCI', nama: 'Hilang kunci serep',       biaya: 2_500_000 },
  { id: 'LUAR-AREA',    nama: 'Keluar area Bali tanpa izin', biaya: 1_000_000 },
];

// Checklist BAST (Berita Acara Serah Terima)
const BAST_CHECKLIST = [
  { kategori: 'Eksterior', items: ['Bodi depan', 'Bodi belakang', 'Bodi samping kiri', 'Bodi samping kanan', 'Atap', 'Kap mesin', 'Bumper depan', 'Bumper belakang', 'Lampu utama', 'Lampu belakang', 'Spion kiri', 'Spion kanan', 'Kaca depan', 'Kaca belakang', 'Ban + velg (4)'] },
  { kategori: 'Interior',  items: ['Jok depan', 'Jok belakang', 'Karpet dasar', 'Karpet bagasi', 'Dashboard', 'Setir', 'Pedal', 'AC dingin', 'Audio + speaker', 'USB charger', 'Lampu kabin'] },
  { kategori: 'Dokumen',   items: ['STNK asli', 'Buku service', 'Kartu tol e-money'] },
  { kategori: 'Equipment', items: ['Ban serep', 'Dongkrak', 'Kunci roda', 'Toolkit', 'Segitiga pengaman', 'P3K', 'Kunci serep'] },
  { kategori: 'Operasional', items: ['BBM (level)', 'Odometer awal', 'Foto 4 sisi mobil'] },
];

// ====== Helpers ======

function rupiah(n, opts = { sym: true, compact: false }) {
  if (n === null || n === undefined) return '—';
  if (typeof n === 'string') return n;
  const abs = Math.abs(n);
  const sign = n < 0 ? '-' : '';
  if (opts.compact && abs >= 1_000_000_000) return sign + (opts.sym ? 'Rp ' : '') + (abs / 1_000_000_000).toFixed(1) + 'M';
  if (opts.compact && abs >= 1_000_000)     return sign + (opts.sym ? 'Rp ' : '') + (abs / 1_000_000).toFixed(1) + 'jt';
  if (opts.compact && abs >= 1_000)         return sign + (opts.sym ? 'Rp ' : '') + (abs / 1_000).toFixed(0) + 'rb';
  const str = abs.toLocaleString('id-ID');
  return (opts.sym ? 'Rp ' : '') + sign + str;
}

function formatDateID(iso) {
  if (!iso) return '—';
  const m = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
  const d = new Date(iso);
  return `${d.getDate()} ${m[d.getMonth()]} ${d.getFullYear()}`;
}

function formatDateTimeID(iso) {
  if (!iso) return '—';
  const m = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
  // accept "YYYY-MM-DD HH:MM"
  const [datePart, timePart] = String(iso).split(' ');
  const d = new Date(datePart);
  const dateStr = `${d.getDate()} ${m[d.getMonth()]}`;
  return timePart ? `${dateStr}, ${timePart}` : dateStr;
}

function periodLabel(id) {
  return PERIOD_LIST.find(p => p.id === id)?.label || id;
}

function minutesSince(hhmm) {
  if (!hhmm) return 0;
  const [h, m] = hhmm.split(':').map(Number);
  const [nh, nm] = NOW_HHMM.split(':').map(Number);
  return (nh * 60 + nm) - (h * 60 + m);
}

function fmtMin(mins) {
  if (mins < 1) return 'baru saja';
  if (mins < 60) return `${mins} menit`;
  const h = Math.floor(mins / 60), m = mins % 60;
  return `${h}j ${m}m`;
}

function bookingTotal(b) {
  return b.total || 0;
}

function statusTone(s) {
  return ({
    // armada
    available: 'success', rented: 'accent', cleaning: 'neutral', maintenance: 'warn', reserved: 'accent',
    // booking
    pending: 'warn', confirmed: 'accent', ongoing: 'success', done: 'neutral', cancelled: 'danger',
    // trip
    'in-trip': 'success', parked: 'neutral', idle: 'neutral',
    // payment
    paid: 'success', dp: 'accent', qris: 'accent', kartu: 'accent', cash: 'neutral', transfer: 'accent',
    // driver
    'on-trip': 'success', standby: 'accent', libur: 'neutral',
    // maintenance
    scheduled: 'accent', 'in-progress': 'warn',
    // customer
    aktif: 'success', vip: 'accent', review: 'warn', blacklist: 'danger',
    // alerts
    danger: 'danger', warn: 'warn', success: 'success', neutral: 'neutral',
    // priority
    tinggi: 'danger', normal: 'accent', rendah: 'neutral',
  })[s] || 'neutral';
}

function statusLabel(s) {
  return ({
    available: 'Tersedia', rented: 'Disewa', cleaning: 'Cuci', maintenance: 'Workshop', reserved: 'Booked',
    pending: 'Menunggu DP', confirmed: 'Terkonfirmasi', ongoing: 'Berjalan', done: 'Selesai', cancelled: 'Batal',
    'in-trip': 'Jalan', parked: 'Parkir', idle: 'Idle',
    paid: 'Lunas', dp: 'DP', qris: 'QRIS', kartu: 'Kartu', cash: 'Tunai', transfer: 'Transfer',
    'on-trip': 'On Trip', standby: 'Standby', libur: 'Libur',
    scheduled: 'Terjadwal', 'in-progress': 'Berjalan',
    aktif: 'Aktif', vip: 'VIP', review: 'Review', blacklist: 'Blacklist',
    tinggi: 'Tinggi', normal: 'Normal', rendah: 'Rendah',
    'self-drive': 'Self Drive', 'with-driver': 'With Driver',
    matic: 'Matic', manual: 'Manual',
    bensin: 'Bensin', solar: 'Solar', hybrid: 'Hybrid',
  })[s] || s;
}

function tipeArmadaLabel(t) {
  return ({ city: 'City Car', mpv: 'MPV', suv: 'SUV', premium: 'Premium', van: 'Van' })[t] || t;
}

function bbmTone(pct) {
  if (pct < 30) return 'danger';
  if (pct < 50) return 'warn';
  return 'success';
}

// Project lat/lng Bali ke koordinat SVG viewBox (800 x 500)
// Bounding box approx: lat -8.85 (south) — -8.05 (north), lng 114.4 (west) — 115.7 (east)
function latLngToSvg(lat, lng) {
  const minLat = -8.85, maxLat = -8.05;
  const minLng = 114.40, maxLng = 115.70;
  const x = ((lng - minLng) / (maxLng - minLng)) * 800;
  const y = ((maxLat - lat) / (maxLat - minLat)) * 500;
  return { x: Math.round(x * 10) / 10, y: Math.round(y * 10) / 10 };
}

function cabangName(id) {
  return CABANG.find(c => c.id === id)?.name || id;
}

function armadaLabel(id) {
  const a = ARMADA_BY_ID[id];
  if (!a) return id;
  return `${a.merk} ${a.model} · ${a.plat}`;
}

Object.assign(window, {
  TENANT, TODAY, NOW_HHMM, SHIFT, PERIOD_LIST, CURRENT_PERIOD, ROLES, CABANG,
  KATEGORI, ARMADA, ARMADA_BY_ID, STATUS_ARMADA,
  CUSTOMERS, CUSTOMER_BY_ID, DRIVERS, DRIVER_BY_ID,
  BOOKINGS, TRIPS, TRIP_BY_ID, TRIP_ROUTE_DEMO,
  MAINTENANCE, ALERTS, KPI, REVENUE_14D, TOP_ARMADA, ACTIVITY,
  ASURANSI, DENDA, BAST_CHECKLIST,
  rupiah, formatDateID, formatDateTimeID, periodLabel, minutesSince, fmtMin,
  bookingTotal, statusTone, statusLabel, tipeArmadaLabel, bbmTone,
  latLngToSvg, cabangName, armadaLabel,
});
