<?php
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: no-referrer');
session_start();
// Auth check + session fingerprint + expiry
$fp = hash('sha256', ($_SERVER['HTTP_USER_AGENT'] ?? '') . '|' . ($_SERVER['REMOTE_ADDR'] ?? ''));
if(!isset($_SESSION['auth_ok'])||$_SESSION['auth_ok']!==true){header('Location:login.php');exit;}
if(isset($_SESSION['fingerprint'])&&$_SESSION['fingerprint']!==$fp){session_destroy();header('Location:login.php');exit;}
if(isset($_SESSION['last_activity'])&&(time()-$_SESSION['last_activity']>7200)){session_destroy();header('Location:login.php');exit;}
$_SESSION['last_activity']=time();
$DB_HOST='localhost';$DB_NAME='deeldabr_eu261';$DB_USER='deeldabr_eu261';$DB_PASS='ASDjaS(DCWEFHjewke3we4f@#';
try{$pdo=new PDO("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=utf8mb4",$DB_USER,$DB_PASS,[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]);}catch(PDOException $e){die('DB failed');}

// Schema migrations — only run once (tracked by file flag)
$schemaFile=__DIR__.'/.schema_v18';
if(!file_exists($schemaFile)){
$pdo->exec("CREATE TABLE IF NOT EXISTS mail_templates (
  id INT AUTO_INCREMENT PRIMARY KEY,
  slug VARCHAR(50) NOT NULL UNIQUE,
  label VARCHAR(100) NOT NULL,
  subject VARCHAR(255) NOT NULL DEFAULT '',
  body TEXT NOT NULL DEFAULT '',
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

// Seed defaults if empty
$cnt=$pdo->query("SELECT COUNT(*) FROM mail_templates")->fetchColumn();
if($cnt==0){
  $pdo->exec("INSERT INTO mail_templates (slug,label,subject,body) VALUES
    ('claim_submit','Adatbekérő kiküldés','Flight Disruption Notification','This template uses the designed HTML email (email-notification.html) with personalized claim link, flight details, and compensation info. It is not editable here — edit the email-notification.html file directly on the server.'),
    ('hibas_id','Hibás ID','Document Issue – New ID Required','Dear {{NAME}},\n\nThank you for submitting your claim for flight {{FLIGHT}} on {{DATE}} from {{DEP}} to {{ARR}} (Booking: {{BOOKING}}).\n\nUnfortunately, the identification document you provided does not meet the requirements for processing your claim. To proceed, we need a clear and complete copy of your national ID card or passport.\n\nPlease ensure the following when uploading your document:\n\n- Both sides of the document are included (front and back)\n- All four corners of the document are fully visible\n- The image is taken in a well-lit area so all details are legible\n- The following information must be clearly readable: full name, date of birth, document number, date of issue, and signature (if included on the document)\n\nPlease reply to this email with the corrected document for all passengers included in your booking.\n\nWe apologise for the inconvenience and appreciate your cooperation.\n\nKind regards,\nSkyClaim Customer Relations'),
    ('kis_turelmet','Kis türelmet kérünk még','Claim Update – Please Be Patient','Dear {{NAME}},\n\nThank you for your patience regarding your claim for flight {{FLIGHT}} on {{DATE}}.\n\nWe are currently processing your case and will notify you as soon as there is an update.\n\nBooking Reference: {{BOOKING}}\n\nBest regards,\nSkyClaim Team')");
}
// Always update label in case it changed
$pdo->exec("UPDATE mail_templates SET label='Adatbekérő kiküldés' WHERE slug='claim_submit'");
// Update hibas_id template text
$pdo->prepare("UPDATE mail_templates SET body=?, subject='Document Issue – New ID Required' WHERE slug='hibas_id'")->execute(["Dear {{NAME}},\n\nThank you for submitting your claim for flight {{FLIGHT}} on {{DATE}} from {{DEP}} to {{ARR}} (Booking: {{BOOKING}}).\n\nUnfortunately, the identification document you provided does not meet the requirements for processing your claim. To proceed, we need a clear and complete copy of your national ID card or passport.\n\nPlease ensure the following when uploading your document:\n\n- Both sides of the document are included (front and back)\n- All four corners of the document are fully visible\n- The image is taken in a well-lit area so all details are legible\n- The following information must be clearly readable: full name, date of birth, document number, date of issue, and signature (if included on the document)\n\nPlease reply to this email with the corrected document for all passengers included in your booking.\n\nWe apologise for the inconvenience and appreciate your cooperation.\n\nKind regards,\nSkyClaim Customer Relations"]);

// History tables
$pdo->exec("CREATE TABLE IF NOT EXISTS mail_history (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id INT NOT NULL,
  template_slug VARCHAR(50) NOT NULL,
  template_label VARCHAR(100) NOT NULL,
  sent_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_cust (customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

$pdo->exec("CREATE TABLE IF NOT EXISTS status_history (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id INT NOT NULL,
  status VARCHAR(50) NOT NULL,
  changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_cust (customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

$pdo->exec("CREATE TABLE IF NOT EXISTS flight_data (
  id INT AUTO_INCREMENT PRIMARY KEY,
  flight_date DATE NOT NULL,
  flight_number VARCHAR(20) NOT NULL,
  flight_aliases VARCHAR(100) DEFAULT '',
  departure_iata VARCHAR(5) DEFAULT '',
  arrival_iata VARCHAR(5) DEFAULT '',
  reason VARCHAR(100) DEFAULT '',
  distance_km INT NULL DEFAULT NULL,
  airhelp_eligible VARCHAR(20) DEFAULT '',
  airhelp_note TEXT DEFAULT '',
  airhelp_source VARCHAR(20) DEFAULT '',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uq_flight (flight_date, flight_number),
  INDEX idx_fn (flight_number)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
// Add columns if missing (upgrade)
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN distance_km INT NULL DEFAULT NULL AFTER reason");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN airhelp_eligible VARCHAR(20) DEFAULT '' AFTER distance_km");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN airhelp_note TEXT DEFAULT '' AFTER airhelp_eligible");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN airhelp_source VARCHAR(20) DEFAULT '' AFTER airhelp_note");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN flight_aliases VARCHAR(100) DEFAULT '' AFTER flight_number");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN departure_iata VARCHAR(5) DEFAULT '' AFTER flight_aliases");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD COLUMN arrival_iata VARCHAR(5) DEFAULT '' AFTER departure_iata");}catch(Exception $e){}
// Performance indexes
try{$pdo->exec("ALTER TABLE flight_data ADD INDEX idx_date (flight_date)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE flight_data ADD INDEX idx_eligible (airhelp_eligible)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD INDEX idx_bk (booking_ref)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD INDEX idx_fn_dt (flight_number, flight_date)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD INDEX idx_airline (airline)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD INDEX idx_status (status)");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD COLUMN claim_method VARCHAR(30) DEFAULT '' AFTER status");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD COLUMN notes TEXT DEFAULT '' AFTER claim_method");}catch(Exception $e){}
// Migrate status from ENUM to VARCHAR (supports all status values)
try{$pdo->exec("ALTER TABLE customers MODIFY COLUMN status VARCHAR(50) NOT NULL DEFAULT 'doc_needed'");}catch(Exception $e){}
// Add email column if missing
try{$pdo->exec("ALTER TABLE customers ADD COLUMN email VARCHAR(255) NULL AFTER last_name");}catch(Exception $e){}
// Add mail_template column if missing
try{$pdo->exec("ALTER TABLE customers ADD COLUMN mail_template VARCHAR(50) DEFAULT '' AFTER mail_sent_at");}catch(Exception $e){}
// Add seat column if missing
try{$pdo->exec("ALTER TABLE customers ADD COLUMN seat VARCHAR(10) DEFAULT '' AFTER arrival");}catch(Exception $e){}
// Auto-fix airline based on flight number for existing records
try{
  $pdo->exec("UPDATE customers SET airline='easyJet' WHERE airline='' AND (UPPER(flight_number) LIKE 'U2%' OR UPPER(flight_number) LIKE 'EZY%' OR UPPER(flight_number) LIKE 'EZS%' OR UPPER(flight_number) LIKE 'EJU%')");
  $pdo->exec("UPDATE customers SET airline='Wizz Air' WHERE airline='' AND (UPPER(flight_number) LIKE 'W6%' OR UPPER(flight_number) LIKE 'W4%' OR UPPER(flight_number) LIKE 'W9%' OR UPPER(flight_number) LIKE 'WZZ%')");
  $pdo->exec("UPDATE customers SET airline='Ryanair' WHERE airline='' AND (UPPER(flight_number) LIKE 'FR%' OR UPPER(flight_number) LIKE 'RK%')");
  // Also fix 'Other' or empty where detectable
  $pdo->exec("UPDATE customers SET airline='easyJet' WHERE (airline='Other' OR airline='') AND (UPPER(flight_number) LIKE 'U2%' OR UPPER(flight_number) LIKE 'EZY%' OR UPPER(flight_number) LIKE 'EZS%' OR UPPER(flight_number) LIKE 'EJU%')");
  $pdo->exec("UPDATE customers SET airline='Wizz Air' WHERE (airline='Other' OR airline='') AND (UPPER(flight_number) LIKE 'W6%' OR UPPER(flight_number) LIKE 'W4%' OR UPPER(flight_number) LIKE 'W9%' OR UPPER(flight_number) LIKE 'WZZ%')");
}catch(Exception $e){}

// Future flights table
$pdo->exec("CREATE TABLE IF NOT EXISTS future_flights (
  id INT AUTO_INCREMENT PRIMARY KEY,
  flight_date DATE NOT NULL,
  airline VARCHAR(100) NOT NULL DEFAULT 'easyJet',
  flight_number VARCHAR(20) NOT NULL,
  departure VARCHAR(100) DEFAULT '',
  departure_iata VARCHAR(5) DEFAULT '',
  arrival VARCHAR(100) DEFAULT '',
  arrival_iata VARCHAR(5) DEFAULT '',
  status VARCHAR(50) DEFAULT 'scheduled',
  passengers INT DEFAULT 0,
  notes TEXT DEFAULT '',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uq_future (flight_date, flight_number),
  INDEX idx_date (flight_date),
  INDEX idx_airline (airline)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
try{$pdo->exec("ALTER TABLE future_flights ADD COLUMN passengers INT DEFAULT 0 AFTER status");}catch(Exception $e){}

// Remarketing system
$pdo->exec("CREATE TABLE IF NOT EXISTS remarketing_logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id INT NOT NULL,
  step TINYINT NOT NULL,
  day_offset INT NOT NULL,
  template_file VARCHAR(100) NOT NULL,
  sent_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  send_ok TINYINT(1) NOT NULL DEFAULT 1,
  error_message VARCHAR(500) NULL,
  INDEX idx_customer (customer_id),
  INDEX idx_sent_at (sent_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
try{$pdo->exec("ALTER TABLE customers ADD COLUMN remarketing_active TINYINT(1) NOT NULL DEFAULT 0");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD COLUMN claim_mail_sent_at DATETIME NULL DEFAULT NULL");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD COLUMN remarketing_stopped_at DATETIME NULL DEFAULT NULL");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD COLUMN remarketing_stopped_reason VARCHAR(100) DEFAULT ''");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE customers ADD INDEX idx_remarketing (remarketing_active, claim_mail_sent_at)");}catch(Exception $e){}
// Add source column to remarketing_logs so we can distinguish easyJet vs WZ entries
try{
  $chkCol=$pdo->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='remarketing_logs' AND COLUMN_NAME='source'")->fetchColumn();
  if(!$chkCol){
    $pdo->exec("ALTER TABLE remarketing_logs ADD COLUMN source VARCHAR(20) NOT NULL DEFAULT 'customers'");
  }
}catch(Exception $e){
  // If ALTER fails, try recreating with source column
  error_log('SkyClaim: Failed to add source column to remarketing_logs: '.$e->getMessage());
}
// Check if source column exists — used by queries later
$rmLogsHasSource=false;
try{$rmLogsHasSource=(bool)$pdo->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='remarketing_logs' AND COLUMN_NAME='source'")->fetchColumn();}catch(Exception $e){}

// Retroactive fix: activate remarketing for customers who got claim_submit email but remarketing wasn't turned on
try{
  $pdo->exec("UPDATE customers SET remarketing_active=1, claim_mail_sent_at=COALESCE(claim_mail_sent_at, mail_sent_at) WHERE mail_template='claim_submit' AND remarketing_active=0 AND mail_sent_at IS NOT NULL AND is_main=1 AND id_doc_path IS NULL");
  $pdo->exec("UPDATE wz_passengers SET remarketing_active=1, claim_mail_sent_at=COALESCE(claim_mail_sent_at, mail_sent_at) WHERE mail_template='claim_submit' AND remarketing_active=0 AND mail_sent_at IS NOT NULL AND is_holder=1 AND id_doc_path IS NULL");
  // Also activate holders when a sub-passenger in their booking was sent claim_submit
  $pdo->exec("UPDATE customers c1 SET c1.remarketing_active=1, c1.claim_mail_sent_at=COALESCE(c1.claim_mail_sent_at, NOW()) WHERE c1.is_main=1 AND c1.remarketing_active=0 AND EXISTS (SELECT 1 FROM customers c2 WHERE c2.booking_ref=c1.booking_ref AND c2.mail_template='claim_submit' AND c2.mail_sent_at IS NOT NULL)");
  $pdo->exec("UPDATE wz_passengers p1 SET p1.remarketing_active=1, p1.claim_mail_sent_at=COALESCE(p1.claim_mail_sent_at, NOW()) WHERE p1.is_holder=1 AND p1.remarketing_active=0 AND EXISTS (SELECT 1 FROM wz_passengers p2 WHERE p2.booking_id=p1.booking_id AND p2.mail_template='claim_submit' AND p2.mail_sent_at IS NOT NULL)");
}catch(Exception $e){}

// Email tracking table
$pdo->exec("CREATE TABLE IF NOT EXISTS email_tracking (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id INT NOT NULL,
  event_type ENUM('open','click') NOT NULL,
  ip VARCHAR(45) DEFAULT '',
  user_agent VARCHAR(500) DEFAULT '',
  tracked_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_customer (customer_id),
  INDEX idx_type (event_type),
  INDEX idx_time (tracked_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

// Seed future flights if empty
$futCnt=$pdo->query("SELECT COUNT(*) FROM future_flights")->fetchColumn();
if($futCnt==0){
  $pdo->exec("INSERT INTO future_flights (flight_date,airline,flight_number,departure,departure_iata,arrival,arrival_iata,status,passengers,notes) VALUES
    ('2026-04-02','easyJet','U2 8541','London (LGW)','LGW','Budapest (BUD)','BUD','scheduled',12,''),
    ('2026-04-03','easyJet','U2 8542','Budapest (BUD)','BUD','London (LGW)','LGW','scheduled',8,''),
    ('2026-04-05','easyJet','U2 3456','Milan (MXP)','MXP','London (LGW)','LGW','scheduled',5,''),
    ('2026-04-06','easyJet','U2 1234','London (LTN)','LTN','Amsterdam (AMS)','AMS','scheduled',3,''),
    ('2026-04-07','easyJet','U2 7812','Paris (CDG)','CDG','London (LGW)','LGW','scheduled',15,''),
    ('2026-04-08','easyJet','U2 4490','Barcelona (BCN)','BCN','London (LGW)','LGW','scheduled',7,''),
    ('2026-04-09','easyJet','U2 6678','Berlin (BER)','BER','London (LTN)','LTN','scheduled',4,''),
    ('2026-04-10','easyJet','U2 9921','Rome (FCO)','FCO','London (LGW)','LGW','scheduled',11,''),
    ('2026-04-11','easyJet','U2 5530','Lisbon (LIS)','LIS','London (LGW)','LGW','scheduled',6,''),
    ('2026-04-12','easyJet','U2 3310','Edinburgh (EDI)','EDI','London (LGW)','LGW','scheduled',2,''),
    ('2026-04-14','Ryanair','FR 1821','Dublin (DUB)','DUB','Budapest (BUD)','BUD','scheduled',9,''),
    ('2026-04-15','Ryanair','FR 4456','Milan (BGY)','BGY','Budapest (BUD)','BUD','scheduled',14,''),
    ('2026-04-16','Ryanair','FR 7789','London (STN)','STN','Malaga (AGP)','AGP','scheduled',6,''),
    ('2026-04-17','Ryanair','FR 2234','Brussels (CRL)','CRL','Budapest (BUD)','BUD','scheduled',3,''),
    ('2026-04-18','Ryanair','FR 9901','Rome (CIA)','CIA','Barcelona (BCN)','BCN','scheduled',8,''),
    ('2026-04-20','Wizz Air','W6 2341','Budapest (BUD)','BUD','London (LTN)','LTN','scheduled',18,''),
    ('2026-04-21','Wizz Air','W6 2342','London (LTN)','LTN','Budapest (BUD)','BUD','scheduled',10,''),
    ('2026-04-22','Wizz Air','W6 5567','Warsaw (WAW)','WAW','London (LTN)','LTN','scheduled',5,''),
    ('2026-04-23','Wizz Air','W6 7780','Bucharest (OTP)','OTP','London (LTN)','LTN','scheduled',7,''),
    ('2026-04-24','Wizz Air','W6 1123','Sofia (SOF)','SOF','London (LTN)','LTN','scheduled',4,''),
    ('2026-04-26','easyJet','U2 8101','Nice (NCE)','NCE','London (LGW)','LGW','scheduled',9,''),
    ('2026-04-27','easyJet','U2 8202','Athens (ATH)','ATH','London (LGW)','LGW','scheduled',6,''),
    ('2026-04-28','easyJet','U2 8303','Palma (PMI)','PMI','London (LGW)','LGW','scheduled',13,''),
    ('2026-04-29','easyJet','U2 8404','Prague (PRG)','PRG','London (LGW)','LGW','scheduled',3,''),
    ('2026-04-30','easyJet','U2 8505','Vienna (VIE)','VIE','London (LGW)','LGW','scheduled',11,''),
    ('2026-05-01','Ryanair','FR 3345','Porto (OPO)','OPO','London (STN)','STN','scheduled',5,''),
    ('2026-05-02','Ryanair','FR 6678','Krakow (KRK)','KRK','London (STN)','STN','scheduled',7,''),
    ('2026-05-03','easyJet','U2 2211','Copenhagen (CPH)','CPH','London (LGW)','LGW','scheduled',4,''),
    ('2026-05-04','Wizz Air','W6 3344','Belgrade (BEG)','BEG','London (LTN)','LTN','scheduled',8,''),
    ('2026-05-05','easyJet','U2 7700','Catania (CTA)','CTA','Milan (MXP)','MXP','scheduled',6,'')
  ");
}

// TEST: Seed remarketing data for first customer (Bamboo Lee)
$testRm=$pdo->query("SELECT id FROM customers WHERE first_name='Bamboo' AND last_name='Lee' LIMIT 1")->fetch();
if($testRm){
  $tid=$testRm['id'];
  // Set claim_mail_sent_at to 8 days ago and activate remarketing
  $pdo->prepare("UPDATE customers SET remarketing_active=1, claim_mail_sent_at=DATE_SUB(NOW(), INTERVAL 8 DAY) WHERE id=? AND claim_mail_sent_at IS NULL")->execute([$tid]);
  // Insert test remarketing logs if not exist
  $existLogs=$pdo->prepare("SELECT COUNT(*) FROM remarketing_logs WHERE customer_id=?");$existLogs->execute([$tid]);
  if($existLogs->fetchColumn()==0){
    $pdo->prepare("INSERT INTO remarketing_logs (customer_id,step,day_offset,template_file,sent_at,send_ok) VALUES (?,1,1,'remarketing-day1.html',DATE_SUB(NOW(), INTERVAL 7 DAY),1)")->execute([$tid]);
    $pdo->prepare("INSERT INTO remarketing_logs (customer_id,step,day_offset,template_file,sent_at,send_ok) VALUES (?,2,3,'remarketing-day3.html',DATE_SUB(NOW(), INTERVAL 5 DAY),1)")->execute([$tid]);
    $pdo->prepare("INSERT INTO remarketing_logs (customer_id,step,day_offset,template_file,sent_at,send_ok) VALUES (?,3,6,'remarketing-day6.html',DATE_SUB(NOW(), INTERVAL 2 DAY),1)")->execute([$tid]);
  }
}

// ===== WIZZ AIR TABLES =====
$pdo->exec("CREATE TABLE IF NOT EXISTS wz_accounts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  account_number VARCHAR(50) NOT NULL UNIQUE,
  account_created DATE NULL,
  holder_name VARCHAR(200) NOT NULL DEFAULT '',
  holder_gender VARCHAR(10) DEFAULT '',
  holder_dob DATE NULL,
  nationality VARCHAR(100) DEFAULT '',
  phone VARCHAR(50) DEFAULT '',
  address TEXT DEFAULT '',
  passport_number VARCHAR(50) DEFAULT '',
  passport_issued_country VARCHAR(100) DEFAULT '',
  passport_expiry DATE NULL,
  loyalty_program VARCHAR(100) DEFAULT '',
  loyalty_status VARCHAR(50) DEFAULT '',
  email VARCHAR(255) DEFAULT '',
  notes TEXT DEFAULT '',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_holder (holder_name),
  INDEX idx_created (account_created)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

$pdo->exec("CREATE TABLE IF NOT EXISTS wz_bookings (
  id INT AUTO_INCREMENT PRIMARY KEY,
  account_id INT NOT NULL,
  pnr VARCHAR(20) NOT NULL,
  flight_number VARCHAR(20) NOT NULL,
  flight_date DATE NOT NULL,
  origin VARCHAR(100) DEFAULT '',
  origin_iata VARCHAR(5) DEFAULT '',
  destination VARCHAR(100) DEFAULT '',
  destination_iata VARCHAR(5) DEFAULT '',
  flight_status VARCHAR(50) DEFAULT 'scheduled',
  flight_category VARCHAR(50) DEFAULT '',
  pax_count INT DEFAULT 1,
  cost DECIMAL(10,2) DEFAULT 0,
  distance_km INT NULL DEFAULT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_account (account_id),
  INDEX idx_pnr (pnr),
  INDEX idx_flight (flight_number, flight_date),
  INDEX idx_date (flight_date),
  UNIQUE KEY uq_booking_pax (account_id, pnr, flight_number, flight_date),
  FOREIGN KEY (account_id) REFERENCES wz_accounts(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

$pdo->exec("CREATE TABLE IF NOT EXISTS wz_passengers (
  id INT AUTO_INCREMENT PRIMARY KEY,
  booking_id INT NOT NULL,
  account_id INT NOT NULL,
  passenger_name VARCHAR(200) NOT NULL DEFAULT '',
  passenger_gender VARCHAR(10) DEFAULT '',
  seat VARCHAR(10) DEFAULT '',
  checkin_status VARCHAR(50) DEFAULT '',
  travel_document VARCHAR(100) DEFAULT '',
  is_holder TINYINT(1) DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_booking (booking_id),
  INDEX idx_account (account_id),
  INDEX idx_name (passenger_name),
  FOREIGN KEY (booking_id) REFERENCES wz_bookings(id) ON DELETE CASCADE,
  FOREIGN KEY (account_id) REFERENCES wz_accounts(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
// Extend wz_passengers with customer-like fields
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN first_name VARCHAR(100) DEFAULT '' AFTER passenger_name");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN last_name VARCHAR(100) DEFAULT '' AFTER first_name");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN email VARCHAR(255) DEFAULT '' AFTER last_name");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN id_doc_filename VARCHAR(255) NULL AFTER travel_document");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN id_doc_path VARCHAR(500) NULL AFTER id_doc_filename");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN id_doc_viewed TINYINT(1) DEFAULT 0 AFTER id_doc_path");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN travel_doc_filename VARCHAR(255) NULL AFTER id_doc_viewed");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN travel_doc_path VARCHAR(500) NULL AFTER travel_doc_filename");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN travel_doc_viewed TINYINT(1) DEFAULT 0 AFTER travel_doc_path");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN assignment_filename VARCHAR(255) NULL AFTER travel_doc_viewed");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN assignment_path VARCHAR(500) NULL AFTER assignment_filename");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN mail_sent_at DATETIME NULL AFTER assignment_path");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN mail_template VARCHAR(50) DEFAULT '' AFTER mail_sent_at");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN status VARCHAR(50) DEFAULT 'doc_needed' AFTER mail_template");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN claim_method VARCHAR(30) DEFAULT '' AFTER status");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN notes TEXT DEFAULT '' AFTER claim_method");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN remarketing_active TINYINT(1) DEFAULT 0 AFTER notes");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN claim_mail_sent_at DATETIME NULL AFTER remarketing_active");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN remarketing_stopped_at DATETIME NULL AFTER claim_mail_sent_at");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN remarketing_stopped_reason VARCHAR(100) DEFAULT '' AFTER remarketing_stopped_at");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER remarketing_stopped_reason");}catch(Exception $e){}
// Passenger-level personal fields (each passenger can have their own details)
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN dob DATE NULL AFTER email");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN nationality VARCHAR(100) DEFAULT '' AFTER dob");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN passport_number VARCHAR(50) DEFAULT '' AFTER nationality");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN passport_issued_country VARCHAR(100) DEFAULT '' AFTER passport_number");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN passport_expiry DATE NULL AFTER passport_issued_country");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN phone VARCHAR(50) DEFAULT '' AFTER passport_expiry");}catch(Exception $e){}
try{$pdo->exec("ALTER TABLE wz_passengers ADD COLUMN address TEXT DEFAULT '' AFTER phone");}catch(Exception $e){}
// Extend wz_bookings with reason
try{$pdo->exec("ALTER TABLE wz_bookings ADD COLUMN reason VARCHAR(255) DEFAULT '' AFTER flight_status");}catch(Exception $e){}
// Auto-split passenger_name into first_name + last_name if empty
$pdo->exec("UPDATE wz_passengers SET first_name=SUBSTRING_INDEX(passenger_name,' ',1), last_name=TRIM(SUBSTRING(passenger_name,LOCATE(' ',passenger_name)+1)) WHERE first_name='' AND passenger_name!=''");

// Seed Wizz Air test data — add missing test accounts
$wzExist=$pdo->query("SELECT account_number FROM wz_accounts")->fetchAll(PDO::FETCH_COLUMN);
$wzExistSet=array_flip($wzExist);

if(!isset($wzExistSet['WZ-90041823'])){
  // === Account 1: Maria Kovacs — 2 passengers (Maria + Peter) ===
  $pdo->exec("INSERT INTO wz_accounts (account_number,account_created,holder_name,holder_gender,holder_dob,nationality,phone,address,passport_number,passport_issued_country,passport_expiry,loyalty_program,loyalty_status,email) VALUES
    ('WZ-90041823','2023-05-14','Maria Kovacs','Female','1989-07-22','Hungarian','+36301234567','Váci út 45, 1134 Budapest, Hungary','HU12345678','Hungary','2029-11-30','WIZZ Discount Club','Gold','maria.kovacs@example.com')");
  $wzAcc1=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_bookings (account_id,pnr,flight_number,flight_date,origin,origin_iata,destination,destination_iata,flight_status,reason,pax_count,cost,distance_km) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")
    ->execute([$wzAcc1,'WZR7K3','W61045','2026-03-15','Budapest (BUD)','BUD','London Luton (LTN)','LTN','delayed','Delayed (195 min)',2,89.99,1450]);
  $wzBk1=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,1,?,'doc_needed')")
    ->execute([$wzBk1,$wzAcc1,'Maria Kovacs','Maria','Kovacs','Female','14A','checked_in','maria.kovacs@example.com']);
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,0,?,'doc_needed')")
    ->execute([$wzBk1,$wzAcc1,'Peter Kovacs','Peter','Kovacs','Male','14B','checked_in','']);
}

if(!isset($wzExistSet['WZ-76218490'])){
  // === Account 2: Andrei Popescu — 1 passenger (solo, cancelled flight) ===
  $pdo->exec("INSERT INTO wz_accounts (account_number,account_created,holder_name,holder_gender,holder_dob,nationality,phone,address,passport_number,passport_issued_country,passport_expiry,loyalty_program,loyalty_status,email) VALUES
    ('WZ-76218490','2024-01-09','Andrei Popescu','Male','1995-03-11','Romanian','+40721555888','Strada Victoriei 12, Bucharest, Romania','RO87654321','Romania','2030-06-15','','Basic','andrei.popescu@example.com')");
  $wzAcc2=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_bookings (account_id,pnr,flight_number,flight_date,origin,origin_iata,destination,destination_iata,flight_status,reason,pax_count,cost,distance_km) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")
    ->execute([$wzAcc2,'ABCD12','W62284','2026-02-20','Bucharest (OTP)','OTP','London Luton (LTN)','LTN','cancelled','Cancelled',1,54.99,2110]);
  $wzBk2=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,1,?,'doc_needed')")
    ->execute([$wzBk2,$wzAcc2,'Andrei Popescu','Andrei','Popescu','Male','3C','not_checked_in','andrei.popescu@example.com']);
}

if(!isset($wzExistSet['WZ-33509172'])){
  // === Account 3: Elena Nowak — 3 passengers (Elena + Tomasz + Maja) ===
  $pdo->exec("INSERT INTO wz_accounts (account_number,account_created,holder_name,holder_gender,holder_dob,nationality,phone,address,passport_number,passport_issued_country,passport_expiry,loyalty_program,loyalty_status,email) VALUES
    ('WZ-33509172','2022-11-20','Elena Nowak','Female','1991-12-04','Polish','+48501222333','ul. Marszalkowska 88/5, 00-001 Warsaw, Poland','PL55443322','Poland','2028-09-01','WIZZ Discount Club','Silver','elena.nowak@example.com')");
  $wzAcc3=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_bookings (account_id,pnr,flight_number,flight_date,origin,origin_iata,destination,destination_iata,flight_status,reason,pax_count,cost,distance_km) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")
    ->execute([$wzAcc3,'XYZ789','W64306','2026-04-02','Warsaw (WAW)','WAW','Barcelona (BCN)','BCN','delayed','Delayed (240 min)',3,149.99,1862]);
  $wzBk3=$pdo->lastInsertId();
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,1,?,'doc_needed')")
    ->execute([$wzBk3,$wzAcc3,'Elena Nowak','Elena','Nowak','Female','8A','checked_in','elena.nowak@example.com']);
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,0,?,'doc_needed')")
    ->execute([$wzBk3,$wzAcc3,'Tomasz Nowak','Tomasz','Nowak','Male','8B','checked_in','']);
  $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,passenger_gender,seat,checkin_status,is_holder,email,status) VALUES (?,?,?,?,?,?,?,?,0,?,'doc_needed')")
    ->execute([$wzBk3,$wzAcc3,'Maja Nowak','Maja','Nowak','Female','8C','checked_in','']);
}

  @file_put_contents($schemaFile,date('Y-m-d H:i:s'));
} // end schema migrations

// Include mailer for email sending
require_once __DIR__ . '/mailer.php';

// Wizz Air notification email builder — uses email-notification-wizzair.html
function buildWzNotificationEmail($customer,$claimLink,$allPax,$preview=false){
  $tplPath=__DIR__.'/email-notification-wizzair.html';
  if(!file_exists($tplPath))return buildNotificationEmail($customer,$claimLink,$allPax,$preview);
  
  // Use replacePlaceholders from mailer.php (same as easyJet) to fill template
  $html=replacePlaceholders(file_get_contents($tplPath),$customer,$claimLink,$allPax);
  
  // Add tracking — same logic as buildNotificationEmail in mailer.php
  $customerId=intval($customer['id']??0);
  if($customerId && !$preview){
    $trackBase='https://eu261compensation.com/track.php';
    // 1) Replace claim link with click-tracked redirect (src=wz for Wizz Air)
    $trackedLink=$trackBase.'?t=c&id='.$customerId.'&src=wz&url='.urlencode($claimLink);
    // Try both raw & and HTML-encoded &amp; versions (email clients may encode)
    $claimLinkHtmlEncoded=str_replace('&','&amp;',$claimLink);
    $html=str_replace($claimLink,$trackedLink,$html);
    $html=str_replace($claimLinkHtmlEncoded,$trackedLink,$html);
    // 2) Add open tracking pixel before </body>
    $pixel='<img src="'.$trackBase.'?t=o&id='.$customerId.'&src=wz" width="1" height="1" style="display:none;width:1px;height:1px;border:0" alt="">';
    if(stripos($html,'</body>')!==false){$html=str_ireplace('</body>',$pixel.'</body>',$html);}
    else{$html.=$pixel;}
  }
  
  return $html;
}

// ===== CLAIM FORM URL — ÍRD ÁT A SAJÁT DOMAIN-EDRE! =====
$claimFormUrl = 'https://eu261compensation.com/easyjet-claim-funnel.html';
$wzClaimFormUrl = 'https://eu261compensation.com/wizzair-claim-funnel.html';

// WZ claim link builder — same as buildClaimLink but uses WZ claim form URL
function buildWzClaimLink($customer,$allPax=[]){
  global $wzClaimFormUrl;
  $depIata='';$arrIata='';$depCity=$customer['departure'];$arrCity=$customer['arrival'];
  if(preg_match('/\(([A-Z]{3})\)/',$customer['departure'],$m)){$depIata=$m[1];$depCity=trim(preg_replace('/\s*\([A-Z]{3}\)\s*/','',$customer['departure']));}
  if(preg_match('/\(([A-Z]{3})\)/',$customer['arrival'],$m)){$arrIata=$m[1];$arrCity=trim(preg_replace('/\s*\([A-Z]{3}\)\s*/','',$customer['arrival']));}
  $paxNames=[];
  if(!empty($allPax)){foreach($allPax as $p){$paxNames[]=str_replace(' ','_',$p['first_name']).'_'.str_replace(' ','_',$p['last_name']);}}
  else{$paxNames[]=str_replace(' ','_',$customer['first_name']).'_'.str_replace(' ','_',$customer['last_name']);}
  $reason=$customer['reason']??'';
  if(is_numeric($reason))$reason='Delayed ('.$reason.' min)';
  elseif(strtolower($reason)==='cancelled'||strtolower($reason)==='canceled')$reason='Cancelled';
  return $wzClaimFormUrl.'?'.http_build_query(['booking'=>$customer['booking_ref'],'flight'=>$customer['flight_number'],'date'=>$customer['flight_date'],'from'=>$depIata,'fromCity'=>$depCity,'to'=>$arrIata,'toCity'=>$arrCity,'reason'=>$reason,'pax'=>implode(',',$paxNames)]);
}

if(isset($_GET['action'])){

  header('Content-Type: application/json');

  // Helper: auto-set status to form_send (Claim beadni) if ID doc viewed + assignment exists
  function autoClaimStatus($pdo, $id) {
    $st=$pdo->prepare("SELECT id_doc_viewed, assignment_path, status FROM customers WHERE id=?");
    $st->execute([$id]);$r=$st->fetch();
    if($r && $r['id_doc_viewed'] && $r['assignment_path'] && in_array($r['status'],['doc_needed','form_sent','bad_id_sent'])) {
      $pdo->prepare("UPDATE customers SET status='form_send',updated_at=NOW() WHERE id=?")->execute([$id]);
      $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,'form_send')")->execute([$id]);
    }
  }

  if($_GET['action']==='update_field'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$field=$in['field']??'';$val=$in['value']??'';
    $allowed=['first_name','last_name','booking_ref','flight_number','flight_date','reason','departure','arrival','airline','distance_km','address_street','address_city','address_postal','address_country','customer_id','email','seat','claim_method','notes'];
    if($id&&$field&&in_array($field,$allowed)){
      if($field==='distance_km')$val=$val?intval($val):null;
      $pdo->prepare("UPDATE customers SET {$field}=?,updated_at=NOW() WHERE id=?")->execute([$val,$id]);
      echo json_encode(['ok'=>true]);
    }else echo json_encode(['ok'=>false,'msg'=>'Invalid field']);exit;
  }
  if($_GET['action']==='update_status'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$s=$in['status']??'';
    if($id&&$s){$pdo->prepare("UPDATE customers SET status=?,updated_at=NOW() WHERE id=?")->execute([$s,$id]);
      $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$s]);
      echo json_encode(['ok'=>true]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='mark_viewed'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$dt=$in['doc_type']??'';
    $col=($dt==='id')?'id_doc_viewed':'travel_doc_viewed';
    if($id){$pdo->prepare("UPDATE customers SET {$col}=1,updated_at=NOW() WHERE id=?")->execute([$id]);
      // Check if both ID doc viewed AND assignment exists → Claim beadni
      $st=$pdo->prepare("SELECT id_doc_filename,id_doc_viewed,assignment_path,status FROM customers WHERE id=?");$st->execute([$id]);$r=$st->fetch();
      if($r&&$r['id_doc_filename']&&$r['id_doc_viewed']&&$r['assignment_path']&&in_array($r['status'],['doc_needed','form_sent','bad_id_sent'])){
        $pdo->prepare("UPDATE customers SET status='form_send',updated_at=NOW() WHERE id=?")->execute([$id]);
        $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,'form_send')")->execute([$id]);
        echo json_encode(['ok'=>true,'new_status'=>'form_send']);exit;}
      echo json_encode(['ok'=>true]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='delete_doc'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$dt=$in['doc_type']??'';
    $col=($dt==='id')?'id_doc':'travel_doc';$vc=($dt==='id')?'id_doc_viewed':'travel_doc_viewed';
    if($id){
      // Keep file on disk, only clear DB reference
      $pdo->prepare("UPDATE customers SET {$col}_filename=NULL,{$col}_path=NULL,{$vc}=0,updated_at=NOW() WHERE id=?")->execute([$id]);
      if($dt==='id')$pdo->prepare("UPDATE customers SET status='doc_needed',updated_at=NOW() WHERE id=? AND status IN('form_send','bad_id_sent')")->execute([$id]);
      echo json_encode(['ok'=>true]);}exit;
  }
  if($_GET['action']==='upload_doc'){
    $id=$_POST['id']??0;$dt=$_POST['doc_type']??'';$col=($dt==='id')?'id_doc':'travel_doc';
    if($id&&isset($_FILES['file'])&&$_FILES['file']['error']===UPLOAD_ERR_OK){$f=$_FILES['file'];$ud=__DIR__.'/uploads/';if(!is_dir($ud))mkdir($ud,0755,true);
      $st=$pdo->prepare("SELECT customer_id FROM customers WHERE id=?");$st->execute([$id]);$c=$st->fetch();$pf=$c?$c['customer_id']:'x';
      $ext=pathinfo($f['name'],PATHINFO_EXTENSION);$sn=$pf."_{$dt}_".time().".{$ext}";
      if(move_uploaded_file($f['tmp_name'],$ud.$sn)){$pdo->prepare("UPDATE customers SET {$col}_filename=?,{$col}_path=?,updated_at=NOW() WHERE id=?")->execute([$f['name'],$sn,$id]);echo json_encode(['ok'=>true]);}else echo json_encode(['ok'=>false]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='delete_assignment'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){
      // Keep file on disk, only clear DB reference
      $pdo->prepare("UPDATE customers SET assignment_filename=NULL,assignment_path=NULL,updated_at=NOW() WHERE id=?")->execute([$id]);
      echo json_encode(['ok'=>true]);}exit;
  }
  if($_GET['action']==='upload_assignment'){
    $id=$_POST['id']??0;
    if($id&&isset($_FILES['file'])&&$_FILES['file']['error']===UPLOAD_ERR_OK){$f=$_FILES['file'];$ud=__DIR__.'/uploads/';if(!is_dir($ud))mkdir($ud,0755,true);
      $st=$pdo->prepare("SELECT customer_id,assignment_path FROM customers WHERE id=?");$st->execute([$id]);$c=$st->fetch();
      $pf=$c?$c['customer_id']:'x';$ext=pathinfo($f['name'],PATHINFO_EXTENSION);$sn=$pf."_assignment_".time().".{$ext}";
      if(move_uploaded_file($f['tmp_name'],$ud.$sn)){$pdo->prepare("UPDATE customers SET assignment_filename=?,assignment_path=?,updated_at=NOW() WHERE id=?")->execute([$f['name'],$sn,$id]);
        autoClaimStatus($pdo,$id);
        $stChk=$pdo->prepare("SELECT status FROM customers WHERE id=?");$stChk->execute([$id]);$stRow=$stChk->fetch();
        echo json_encode(['ok'=>true,'filename'=>$f['name'],'path'=>$sn,'new_status'=>$stRow['status']]);}else echo json_encode(['ok'=>false]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='generate_assignment'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){
      require_once __DIR__.'/generate_assignment.php';
      $templatePath=__DIR__.'/assignment_template.docx';
      $uploadDir=__DIR__.'/uploads/';
      if(!file_exists($templatePath)){echo json_encode(['ok'=>false,'msg'=>'Template not found']);exit;}
      $result=generateAssignment($pdo,$id,$uploadDir,$templatePath);
      if($result){
        autoClaimStatus($pdo,$id);
        $st=$pdo->prepare("SELECT assignment_filename,assignment_path,status FROM customers WHERE id=?");$st->execute([$id]);$r=$st->fetch();
        echo json_encode(['ok'=>true,'filename'=>$r['assignment_filename'],'path'=>$r['assignment_path'],'new_status'=>$r['status']]);
      }else echo json_encode(['ok'=>false,'msg'=>'Generation failed — check address data']);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='send_mail'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$tpl=$in['template']??'';
    if($id){
      // Get template label
      $ts=$pdo->prepare("SELECT label FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$tRow=$ts->fetch();
      $tLabel=$tRow?$tRow['label']:$tpl;
      
      // Actually send email via SendGrid
      $emailResult = sendCustomerEmail($pdo, $id, $tpl);
      
      if (!$emailResult['ok']) {
        echo json_encode(['ok'=>false,'message'=>$emailResult['message']]);exit;
      }
      
      $newStatus='';
      if($tpl==='claim_submit')$newStatus='form_sent';
      elseif($tpl==='hibas_id')$newStatus='bad_id_sent';
      if($newStatus){$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,status=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$newStatus,$id]);
        $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$newStatus]);
        // Activate remarketing on claim_submit — also activate main passenger if sub
        if($tpl==='claim_submit'){
          $pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=NOW() WHERE id=? AND remarketing_active=0")->execute([$id]);
          $cr=$pdo->prepare("SELECT booking_ref,is_main FROM customers WHERE id=?");$cr->execute([$id]);$cRow=$cr->fetch();
          if($cRow&&!$cRow['is_main']){$pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=COALESCE(claim_mail_sent_at,NOW()) WHERE booking_ref=? AND is_main=1 AND remarketing_active=0")->execute([$cRow['booking_ref']]);}
        }
      }
      else{$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$id]);}
      // Log mail history
      $pdo->prepare("INSERT INTO mail_history (customer_id,template_slug,template_label) VALUES (?,?,?)")->execute([$id,$tpl,$tLabel]);
      $st=$pdo->prepare("SELECT mail_sent_at,status FROM customers WHERE id=?");$st->execute([$id]);$r=$st->fetch();
      echo json_encode(['ok'=>true,'mail_sent_at'=>$r['mail_sent_at'],'new_status'=>$r['status'],'email_message'=>$emailResult['message']]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='bulk_send_mail'){
    $in=json_decode(file_get_contents('php://input'),true);$ids=$in['ids']??[];
    if(!is_array($ids)||!count($ids)){echo json_encode(['ok'=>false]);exit;}
    $sent=0;$failed=0;$errors=[];
    foreach($ids as $item){
      $id=$item['id']??0;$tpl=$item['template']??'';
      if(!$id||!$tpl)continue;
      $ts=$pdo->prepare("SELECT label FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$tRow=$ts->fetch();$tLabel=$tRow?$tRow['label']:$tpl;
      
      // Actually send email via SendGrid
      $emailResult = sendCustomerEmail($pdo, $id, $tpl);
      
      if (!$emailResult['ok']) {
        $failed++;
        $errors[] = $emailResult['message'];
        continue; // Skip DB update if email failed
      }
      
      $newStatus='';
      if($tpl==='claim_submit')$newStatus='form_sent';
      elseif($tpl==='hibas_id')$newStatus='bad_id_sent';
      if($newStatus){$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,status=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$newStatus,$id]);
        $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$newStatus]);
        // Activate remarketing on claim_submit — also activate main passenger if sub
        if($tpl==='claim_submit'){
          $pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=NOW() WHERE id=? AND remarketing_active=0")->execute([$id]);
          $cr=$pdo->prepare("SELECT booking_ref,is_main FROM customers WHERE id=?");$cr->execute([$id]);$cRow=$cr->fetch();
          if($cRow&&!$cRow['is_main']){$pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=COALESCE(claim_mail_sent_at,NOW()) WHERE booking_ref=? AND is_main=1 AND remarketing_active=0")->execute([$cRow['booking_ref']]);}
        }
      }
      else{$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$id]);}
      $pdo->prepare("INSERT INTO mail_history (customer_id,template_slug,template_label) VALUES (?,?,?)")->execute([$id,$tpl,$tLabel]);
      $sent++;
      
      // Small delay between emails to avoid SendGrid rate limits
      if ($sent % 10 === 0) usleep(500000); // 0.5s pause every 10 emails
    }
    echo json_encode(['ok'=>true,'sent'=>$sent,'failed'=>$failed,'errors'=>array_slice($errors,0,5)]);exit;
  }
  if($_GET['action']==='get_history'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){
      $mh=$pdo->prepare("SELECT template_label,sent_at FROM mail_history WHERE customer_id=? ORDER BY sent_at DESC");$mh->execute([$id]);$mails=$mh->fetchAll();
      $sh=$pdo->prepare("SELECT status,changed_at FROM status_history WHERE customer_id=? ORDER BY changed_at DESC");$sh->execute([$id]);$statuses=$sh->fetchAll();
      echo json_encode(['ok'=>true,'mails'=>$mails,'statuses'=>$statuses]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='get_templates'){
    $rows=$pdo->query("SELECT * FROM mail_templates ORDER BY id")->fetchAll();
    echo json_encode(['ok'=>true,'templates'=>$rows]);exit;
  }
  if($_GET['action']==='save_template'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$subj=$in['subject']??'';$body=$in['body']??'';
    if($id){$pdo->prepare("UPDATE mail_templates SET subject=?,body=?,updated_at=NOW() WHERE id=?")->execute([$subj,$body,$id]);echo json_encode(['ok'=>true]);}else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='add_template'){
    $in=json_decode(file_get_contents('php://input'),true);
    $label=$in['label']??'';$slug=$in['slug']??'';$subj=$in['subject']??'';$body=$in['body']??'';
    if(!$label||!$slug){echo json_encode(['ok'=>false,'message'=>'Label and slug are required']);exit;}
    // Sanitize slug
    $slug=preg_replace('/[^a-z0-9_]/','',$slug);
    // Check duplicate slug
    $chk=$pdo->prepare("SELECT id FROM mail_templates WHERE slug=?");$chk->execute([$slug]);
    if($chk->fetch()){echo json_encode(['ok'=>false,'message'=>'A template with this slug already exists']);exit;}
    $pdo->prepare("INSERT INTO mail_templates (slug,label,subject,body) VALUES (?,?,?,?)")->execute([$slug,$label,$subj,$body]);
    $newId=$pdo->lastInsertId();
    echo json_encode(['ok'=>true,'id'=>(int)$newId,'slug'=>$slug]);exit;
  }
  if($_GET['action']==='delete_template'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){
      $pdo->prepare("DELETE FROM mail_templates WHERE id=?")->execute([$id]);
      echo json_encode(['ok'=>true]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='preview_email'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if(!$id){echo json_encode(['ok'=>false,'message'=>'No customer id']);exit;}
    require_once __DIR__ . '/mailer.php';
    $stmt=$pdo->prepare("SELECT * FROM customers WHERE id=?");$stmt->execute([$id]);$customer=$stmt->fetch();
    if(!$customer){echo json_encode(['ok'=>false,'message'=>'Customer not found']);exit;}
    // Get all passengers in booking for claim link
    $paxStmt=$pdo->prepare("SELECT first_name,last_name FROM customers WHERE booking_ref=? ORDER BY is_main DESC, id ASC");
    $paxStmt->execute([$customer['booking_ref']]);$allPax=$paxStmt->fetchAll();
    $claimLink=buildClaimLink($customer,$allPax);
    $html=buildNotificationEmail($customer,$claimLink,$allPax,true);
    echo json_encode(['ok'=>true,'html'=>$html,'claim_link'=>$claimLink]);exit;
  }
  if($_GET['action']==='preview_template'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$tpl=$in['template']??'';
    if(!$id||!$tpl){echo json_encode(['ok'=>false,'message'=>'Missing id or template']);exit;}
    require_once __DIR__ . '/mailer.php';
    $stmt=$pdo->prepare("SELECT * FROM customers WHERE id=?");$stmt->execute([$id]);$customer=$stmt->fetch();
    if(!$customer){echo json_encode(['ok'=>false,'message'=>'Customer not found']);exit;}
    $paxStmt=$pdo->prepare("SELECT first_name,last_name FROM customers WHERE booking_ref=? ORDER BY is_main DESC, id ASC");
    $paxStmt->execute([$customer['booking_ref']]);$allPax=$paxStmt->fetchAll();
    $claimLink=buildClaimLink($customer,$allPax);
    if($tpl==='claim_submit'){
      $depIata='';$arrIata='';
      if(preg_match('/\(([A-Z]{3})\)/',$customer['departure'],$m))$depIata=$m[1];
      if(preg_match('/\(([A-Z]{3})\)/',$customer['arrival'],$m))$arrIata=$m[1];
      $routeStr=($depIata&&$arrIata)?" {$depIata}-{$arrIata}":'';
      $airlineName=$customer['airline']??'easyJet';
      $subject="Claim up to €600 for your {$airlineName} flight{$routeStr}";
      $body='[HTML email — edit subject only]';
      $isHtml=true;
      $html=buildNotificationEmail($customer,$claimLink,$allPax,true);
    }else{
      $ts=$pdo->prepare("SELECT * FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$t=$ts->fetch();
      if(!$t){echo json_encode(['ok'=>false,'message'=>'Template not found']);exit;}
      $subject=replacePlaceholders($t['subject'],$customer,$claimLink,$allPax);
      $body=replacePlaceholders($t['body'],$customer,$claimLink,$allPax);
      $isHtml=false;
      $html='';
    }
    $email=$customer['email']??'';
    if(!$email&&!$customer['is_main']){$ms=$pdo->prepare("SELECT email FROM customers WHERE booking_ref=? AND is_main=1 LIMIT 1");$ms->execute([$customer['booking_ref']]);$mr=$ms->fetch();if($mr)$email=$mr['email'];}
    echo json_encode(['ok'=>true,'subject'=>$subject,'body'=>$body,'is_html'=>$isHtml,'html'=>$html,'email'=>$email,'name'=>$customer['first_name'].' '.$customer['last_name']]);exit;
  }
  if($_GET['action']==='send_custom_mail'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$tpl=$in['template']??'';$customSubject=$in['subject']??'';$customBody=$in['body']??'';
    if(!$id||!$tpl){echo json_encode(['ok'=>false]);exit;}
    require_once __DIR__ . '/mailer.php';
    $stmt=$pdo->prepare("SELECT * FROM customers WHERE id=?");$stmt->execute([$id]);$customer=$stmt->fetch();
    if(!$customer){echo json_encode(['ok'=>false,'message'=>'Customer not found']);exit;}
    // Get email
    $email=$customer['email'];
    if(!$email&&!$customer['is_main']){$ms=$pdo->prepare("SELECT email FROM customers WHERE booking_ref=? AND is_main=1 LIMIT 1");$ms->execute([$customer['booking_ref']]);$mr=$ms->fetch();if($mr)$email=$mr['email'];}
    if(!$email){echo json_encode(['ok'=>false,'message'=>'No email address']);exit;}
    $toName=$customer['first_name'].' '.$customer['last_name'];
    // Build HTML body
    if($tpl==='claim_submit'){
      // For claim_submit, use the HTML template (subject may be customized)
      $paxStmt=$pdo->prepare("SELECT first_name,last_name FROM customers WHERE booking_ref=? ORDER BY is_main DESC, id ASC");
      $paxStmt->execute([$customer['booking_ref']]);$allPax=$paxStmt->fetchAll();
      $claimLink=buildClaimLink($customer,$allPax);
      $htmlBody=buildNotificationEmail($customer,$claimLink,$allPax);
    }else{
      // For text templates, use the (possibly edited) body
      $htmlBody=buildSimpleEmail($customBody,$customer);
    }
    $subject=$customSubject;
    // Send
    if(MAIL_METHOD==='brevo'){$result=sendViaBrevo($email,$toName,$subject,$htmlBody);}
    elseif(MAIL_METHOD==='resend'){$result=sendViaResend($email,$toName,$subject,$htmlBody);}
    else{$result=sendViaPhpMail($email,$toName,$subject,$htmlBody);}
    if(!$result['ok']){echo json_encode($result);exit;}
    // Log to DB (same as send_mail)
    $ts=$pdo->prepare("SELECT label FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$tRow=$ts->fetch();$tLabel=$tRow?$tRow['label']:$tpl;
    $newStatus='';
    if($tpl==='claim_submit')$newStatus='form_sent';
    elseif($tpl==='hibas_id')$newStatus='bad_id_sent';
    if($newStatus){$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,status=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$newStatus,$id]);
      $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$newStatus]);
      // Activate remarketing on claim_submit send — also activate main passenger if sub
      if($tpl==='claim_submit'){
        $pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=NOW() WHERE id=? AND remarketing_active=0")->execute([$id]);
        $cr=$pdo->prepare("SELECT booking_ref,is_main FROM customers WHERE id=?");$cr->execute([$id]);$cRow=$cr->fetch();
        if($cRow&&!$cRow['is_main']){$pdo->prepare("UPDATE customers SET remarketing_active=1,claim_mail_sent_at=COALESCE(claim_mail_sent_at,NOW()) WHERE booking_ref=? AND is_main=1 AND remarketing_active=0")->execute([$cRow['booking_ref']]);}
      }
    }
    else{$pdo->prepare("UPDATE customers SET mail_sent_at=NOW(),mail_template=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$id]);}
    $pdo->prepare("INSERT INTO mail_history (customer_id,template_slug,template_label) VALUES (?,?,?)")->execute([$id,$tpl,$tLabel]);
    $st=$pdo->prepare("SELECT mail_sent_at FROM customers WHERE id=?");$st->execute([$id]);$r=$st->fetch();
    echo json_encode(['ok'=>true,'mail_sent_at'=>$r['mail_sent_at'],'email_message'=>$result['message']]);exit;
  }
  if($_GET['action']==='delete_customer'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){
      // Keep files on disk, only delete DB records
      $pdo->prepare("DELETE FROM mail_history WHERE customer_id=?")->execute([$id]);
      $pdo->prepare("DELETE FROM status_history WHERE customer_id=?")->execute([$id]);
      $pdo->prepare("DELETE FROM customers WHERE id=?")->execute([$id]);
      echo json_encode(['ok'=>true]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='add_customer'){
    $in=json_decode(file_get_contents('php://input'),true);
    $fn=$in['first_name']??'';$ln=$in['last_name']??'';$bk=$in['booking_ref']??'';
    $fl=$in['flight_number']??'';$dt=$in['flight_date']??'';$dep=$in['departure']??'';
    $arr=$in['arrival']??'';$email=$in['email']??'';$airline=$in['airline']??'easyJet';
    $reason=$in['reason']??'';$dist=$in['distance_km']??null;
    if(!$fn||!$ln||!$bk){echo json_encode(['ok'=>false,'message'=>'First name, last name and booking ref are required']);exit;}
    if($dist!==null&&$dist!=='')$dist=intval($dist);else $dist=null;
    if($dt){$parsed=strtotime($dt);if($parsed)$dt=date('Y-m-d',$parsed);}
    $custId='CU-'.strtoupper(substr(md5($fn.$ln.$bk.time().rand()),0,8));
    // Check if booking already exists
    $chk=$pdo->prepare("SELECT COUNT(*) as cnt FROM customers WHERE booking_ref=?");$chk->execute([$bk]);
    $isMain=$chk->fetch()['cnt']==0?1:0;
    $pdo->prepare("INSERT INTO customers (customer_id,booking_ref,flight_number,flight_date,reason,departure,arrival,first_name,last_name,email,airline,distance_km,is_main,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,'doc_needed')")
      ->execute([$custId,$bk,$fl,$dt?:null,$reason,$dep,$arr,$fn,$ln,$email,$airline,$dist,$isMain]);
    $newId=$pdo->lastInsertId();
    $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,'created')")->execute([$newId]);
    echo json_encode(['ok'=>true,'id'=>(int)$newId,'customer_id'=>$custId,'is_main'=>$isMain]);exit;
  }
  if($_GET['action']==='add_sub_passenger'){
    $in=json_decode(file_get_contents('php://input'),true);
    $bk=$in['booking_ref']??'';$fn=$in['first_name']??'';$ln=$in['last_name']??'';
    $email=$in['email']??'';
    if(!$fn||!$ln||!$bk){echo json_encode(['ok'=>false,'message'=>'First name, last name and booking ref are required']);exit;}
    // Get main customer data for flight info
    $mainStmt=$pdo->prepare("SELECT * FROM customers WHERE booking_ref=? AND is_main=1 LIMIT 1");$mainStmt->execute([$bk]);$mainCust=$mainStmt->fetch();
    if(!$mainCust){$mainStmt=$pdo->prepare("SELECT * FROM customers WHERE booking_ref=? ORDER BY id ASC LIMIT 1");$mainStmt->execute([$bk]);$mainCust=$mainStmt->fetch();}
    if(!$mainCust){echo json_encode(['ok'=>false,'message'=>'Booking not found']);exit;}
    $custId='CU-'.strtoupper(substr(md5($fn.$ln.$bk.time().rand()),0,8));
    $pdo->prepare("INSERT INTO customers (customer_id,booking_ref,flight_number,flight_date,reason,departure,arrival,first_name,last_name,email,airline,distance_km,is_main,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,0,'doc_needed')")
      ->execute([$custId,$bk,$mainCust['flight_number'],$mainCust['flight_date'],$mainCust['reason'],$mainCust['departure'],$mainCust['arrival'],$fn,$ln,$email,$mainCust['airline'],$mainCust['distance_km']]);
    $newId=$pdo->lastInsertId();
    $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,'created')")->execute([$newId]);
    echo json_encode(['ok'=>true,'id'=>(int)$newId,'customer_id'=>$custId]);exit;
  }
  if($_GET['action']==='bulk_delete'){
    $in=json_decode(file_get_contents('php://input'),true);$ids=$in['ids']??[];
    if(!is_array($ids)||empty($ids)){echo json_encode(['ok'=>false]);exit;}
    $deleted=0;
    foreach($ids as $id){
      $id=intval($id);if(!$id)continue;
      // Keep files on disk, only delete DB records
      $pdo->prepare("DELETE FROM mail_history WHERE customer_id=?")->execute([$id]);
      $pdo->prepare("DELETE FROM status_history WHERE customer_id=?")->execute([$id]);
      $pdo->prepare("DELETE FROM customers WHERE id=?")->execute([$id]);
      $deleted++;
    }
    echo json_encode(['ok'=>true,'deleted'=>$deleted]);exit;
  }
  if($_GET['action']==='get_future_flights'){
    $rows=$pdo->query("SELECT * FROM future_flights ORDER BY flight_date ASC, flight_number ASC")->fetchAll();
    echo json_encode(['ok'=>true,'flights'=>$rows]);exit;
  }
  if($_GET['action']==='add_future_flight'){
    $in=json_decode(file_get_contents('php://input'),true);
    $dt=$in['flight_date']??'';$air=$in['airline']??'easyJet';$fl=$in['flight_number']??'';
    $dep=$in['departure']??'';$depIata=$in['departure_iata']??'';$arr=$in['arrival']??'';$arrIata=$in['arrival_iata']??'';
    $status=$in['status']??'scheduled';$notes=$in['notes']??'';
    if(!$dt||!$fl){echo json_encode(['ok'=>false,'message'=>'Date and flight number are required']);exit;}
    $parsed=strtotime($dt);if($parsed)$dt=date('Y-m-d',$parsed);
    // Extract IATA from "Budapest (BUD)" format if not provided
    if(!$depIata&&preg_match('/\(([A-Z]{3})\)/',$dep,$m))$depIata=$m[1];
    if(!$arrIata&&preg_match('/\(([A-Z]{3})\)/',$arr,$m))$arrIata=$m[1];
    // Detect airline from flight number if not set
    if(!$air||$air==='Other'){
      $fnu=strtoupper(trim($fl));
      if(preg_match('/^(EZY|EZS|EJU|U2)/',$fnu))$air='easyJet';
      elseif(preg_match('/^(FR|RK)/',$fnu))$air='Ryanair';
      elseif(preg_match('/^W[0-9]|^WZZ/',$fnu))$air='Wizz Air';
    }
    try{
      $pdo->prepare("INSERT INTO future_flights (flight_date,airline,flight_number,departure,departure_iata,arrival,arrival_iata,status,passengers,notes) VALUES (?,?,?,?,?,?,?,?,?,?)")
        ->execute([$dt,$air,$fl,$dep,$depIata,$arr,$arrIata,$status,0,$notes]);
      echo json_encode(['ok'=>true,'id'=>(int)$pdo->lastInsertId()]);
    }catch(PDOException $e){
      if(strpos($e->getMessage(),'Duplicate')!==false)echo json_encode(['ok'=>false,'message'=>'This flight already exists for this date']);
      else echo json_encode(['ok'=>false,'message'=>'Failed: '.$e->getMessage()]);
    }exit;
  }
  if($_GET['action']==='update_future_flight'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$field=$in['field']??'';$val=$in['value']??'';
    $allowed=['flight_date','airline','flight_number','departure','departure_iata','arrival','arrival_iata','status','passengers','notes'];
    if($id&&in_array($field,$allowed)){
      $pdo->prepare("UPDATE future_flights SET {$field}=?,updated_at=NOW() WHERE id=?")->execute([$val,$id]);
      echo json_encode(['ok'=>true]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='delete_future_flight'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){$pdo->prepare("DELETE FROM future_flights WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='import_future_flights'){
    if(!isset($_FILES['file'])||$_FILES['file']['error']!==UPLOAD_ERR_OK){echo json_encode(['ok'=>false,'msg'=>'No file']);exit;}
    $csv=file_get_contents($_FILES['file']['tmp_name']);
    $csv=preg_replace('/^\xEF\xBB\xBF/','',$csv);
    if(!mb_check_encoding($csv,'UTF-8')){$csv=mb_convert_encoding($csv,'UTF-8','Windows-1252');}
    $lines=preg_split('/\r\n|\r|\n/',$csv);
    if(count($lines)<2){echo json_encode(['ok'=>false,'msg'=>'Empty file']);exit;}
    $delim=strpos($lines[0],';')!==false?';':',';
    $header=array_map('trim',str_getcsv(array_shift($lines),$delim));
    // Map columns
    $map=[];
    $aliases=['flight_date'=>['Date','flight_date','FlightDate'],'airline'=>['Airline','airline'],'flight_number'=>['Flight','Flight Number','flight_number','FlightNumber'],'departure'=>['Departure','From','departure'],'arrival'=>['Arrival','To','arrival'],'status'=>['Status','status'],'passengers'=>['Passengers','passengers','Pax'],'notes'=>['Notes','notes']];
    foreach($aliases as $f=>$al){foreach($al as $a){$idx=array_search($a,$header);if($idx!==false){$map[$f]=$idx;break;}}}
    if(!isset($map['flight_date'])||!isset($map['flight_number'])){echo json_encode(['ok'=>false,'msg'=>'Missing required columns: Date, Flight Number']);exit;}
    $imported=0;$skipped=0;
    foreach($lines as $line){
      $line=trim($line);if(!$line)continue;
      $cols=str_getcsv($line,$delim);
      $g=function($f)use($cols,$map){if(!isset($map[$f]))return'';return trim($cols[$map[$f]]??'');};
      $dt=$g('flight_date');$fl=$g('flight_number');
      if(!$dt||!$fl){$skipped++;continue;}
      $parsed=strtotime($dt);if(!$parsed){$skipped++;continue;}
      $dtFmt=date('Y-m-d',$parsed);
      $air=$g('airline');$dep=$g('departure');$arr=$g('arrival');$st=$g('status')?:'scheduled';$notes=$g('notes');$pax=intval($g('passengers'));
      $depIata='';$arrIata='';
      if(preg_match('/\(([A-Z]{3})\)/',$dep,$m))$depIata=$m[1];
      if(preg_match('/\(([A-Z]{3})\)/',$arr,$m))$arrIata=$m[1];
      if(!$air){$fnu=strtoupper($fl);if(preg_match('/^(EZY|EZS|EJU|U2)/',$fnu))$air='easyJet';elseif(preg_match('/^(FR|RK)/',$fnu))$air='Ryanair';elseif(preg_match('/^W[0-9]/',$fnu))$air='Wizz Air';else $air='Other';}
      try{
        $pdo->prepare("INSERT INTO future_flights (flight_date,airline,flight_number,departure,departure_iata,arrival,arrival_iata,status,passengers,notes) VALUES (?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE airline=VALUES(airline),departure=VALUES(departure),departure_iata=VALUES(departure_iata),arrival=VALUES(arrival),arrival_iata=VALUES(arrival_iata),status=VALUES(status),passengers=VALUES(passengers),notes=VALUES(notes)")
          ->execute([$dtFmt,$air,$fl,$dep,$depIata,$arr,$arrIata,$st,$pax,$notes]);
        $imported++;
      }catch(Exception $e){$skipped++;}
    }
    echo json_encode(['ok'=>true,'imported'=>$imported,'skipped'=>$skipped]);exit;
  }
  if($_GET['action']==='set_mail_template'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$tpl=$in['template']??'';
    if($id){$pdo->prepare("UPDATE customers SET mail_template=? WHERE id=?")->execute([$tpl,$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='get_remarketing_logs'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if(!$id){echo json_encode(['ok'=>false]);exit;}
    $st=$pdo->prepare("SELECT step,day_offset,sent_at,send_ok,error_message FROM remarketing_logs WHERE customer_id=? ORDER BY step ASC");
    $st->execute([$id]);$logs=$st->fetchAll();
    echo json_encode(['ok'=>true,'logs'=>$logs]);exit;
  }
  if($_GET['action']==='debug_remarketing'){
    $rmSrc=false;
    try{$rmSrc=(bool)$pdo->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='remarketing_logs' AND COLUMN_NAME='source'")->fetchColumn();}catch(Exception $e){}
    $out=['ok'=>true,'rmLogsHasSource'=>$rmSrc];
    // 1) Raw DB data
    try{$out['ej_raw']=$pdo->query("SELECT id,first_name,last_name,booking_ref,is_main,mail_template,mail_sent_at,remarketing_active,claim_mail_sent_at,status,id_doc_path FROM customers WHERE mail_template='claim_submit' OR remarketing_active=1 OR claim_mail_sent_at IS NOT NULL ORDER BY id DESC LIMIT 50")->fetchAll();}catch(Exception $e){$out['ej_raw_error']=$e->getMessage();}
    try{$out['wz_raw']=$pdo->query("SELECT p.id,p.first_name,p.last_name,p.passenger_name,b.pnr,p.is_holder,p.mail_template,p.mail_sent_at,p.remarketing_active,p.claim_mail_sent_at,p.status,p.id_doc_path FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id WHERE p.mail_template='claim_submit' OR p.remarketing_active=1 OR p.claim_mail_sent_at IS NOT NULL ORDER BY p.id DESC LIMIT 50")->fetchAll();}catch(Exception $e){$out['wz_raw_error']=$e->getMessage();}
    // 2) The actual remarketing active queries (without source subquery to avoid errors)
    try{$out['wz_active']=$pdo->query("SELECT p.id,p.first_name,p.last_name,p.email,b.pnr as booking_ref,b.flight_number,b.flight_date,b.origin as departure,b.destination as arrival,p.claim_mail_sent_at,p.remarketing_active,p.id_doc_path,p.status,p.is_holder,'wz_passengers' as source FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id WHERE p.claim_mail_sent_at IS NOT NULL AND p.is_holder=1 ORDER BY p.claim_mail_sent_at DESC")->fetchAll();}catch(Exception $e){$out['wz_active_error']=$e->getMessage();}
    try{$out['ej_active']=$pdo->query("SELECT c.id,c.first_name,c.last_name,c.email,c.booking_ref,c.flight_number,c.flight_date,c.departure,c.arrival,c.claim_mail_sent_at,c.remarketing_active,c.id_doc_path,c.status,c.is_main,'customers' as source FROM customers c WHERE c.claim_mail_sent_at IS NOT NULL AND c.is_main=1 ORDER BY c.claim_mail_sent_at DESC")->fetchAll();}catch(Exception $e){$out['ej_active_error']=$e->getMessage();}
    // 3) Tracking
    try{$out['tracking']=$pdo->query("SELECT * FROM email_tracking ORDER BY tracked_at DESC LIMIT 20")->fetchAll();}catch(Exception $e){$out['tracking_error']=$e->getMessage();}
    // 4) Remarketing logs
    try{$out['rm_logs']=$pdo->query("SELECT * FROM remarketing_logs ORDER BY sent_at DESC LIMIT 20")->fetchAll();}catch(Exception $e){$out['rm_logs_error']=$e->getMessage();}
    echo json_encode($out,JSON_PRETTY_PRINT);exit;
  }
  if($_GET['action']==='get_all_remarketing'){
    // Check if remarketing_logs has source column
    $rmSrc=false;
    try{$rmSrc=(bool)$pdo->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='remarketing_logs' AND COLUMN_NAME='source'")->fetchColumn();}catch(Exception $e){}
    // Remarketing logs — adapt queries based on whether source column exists
    if($rmSrc){
      $rows=$pdo->query("
        SELECT rl.id,rl.customer_id,rl.step,rl.day_offset,rl.template_file,rl.sent_at,rl.send_ok,rl.error_message,
               c.first_name,c.last_name,c.email,c.booking_ref,c.flight_number,c.flight_date,c.departure,c.arrival,c.airline,
               c.claim_mail_sent_at,c.remarketing_active,c.id_doc_path,c.status,'customers' as source
        FROM remarketing_logs rl
        JOIN customers c ON c.id=rl.customer_id
        WHERE rl.source='customers' OR rl.source=''
        ORDER BY rl.sent_at DESC LIMIT 500
      ")->fetchAll();
      $wzLogs=$pdo->query("
        SELECT rl.id,rl.customer_id,rl.step,rl.day_offset,rl.template_file,rl.sent_at,rl.send_ok,rl.error_message,
               p.first_name,p.last_name,p.email,b.pnr as booking_ref,b.flight_number,b.flight_date,
               b.origin as departure,b.destination as arrival,'Wizz Air' as airline,
               p.claim_mail_sent_at,p.remarketing_active,p.id_doc_path,p.status,'wz_passengers' as source
        FROM remarketing_logs rl
        JOIN wz_passengers p ON p.id=rl.customer_id
        JOIN wz_bookings b ON p.booking_id=b.id
        WHERE rl.source='wz_passengers'
        ORDER BY rl.sent_at DESC LIMIT 500
      ")->fetchAll();
      $rows=array_merge($rows,$wzLogs);
    }else{
      // No source column — all logs are easyJet
      $rows=$pdo->query("
        SELECT rl.id,rl.customer_id,rl.step,rl.day_offset,rl.template_file,rl.sent_at,rl.send_ok,rl.error_message,
               c.first_name,c.last_name,c.email,c.booking_ref,c.flight_number,c.flight_date,c.departure,c.arrival,c.airline,
               c.claim_mail_sent_at,c.remarketing_active,c.id_doc_path,c.status,'customers' as source
        FROM remarketing_logs rl
        JOIN customers c ON c.id=rl.customer_id
        ORDER BY rl.sent_at DESC LIMIT 500
      ")->fetchAll();
    }
    usort($rows,function($a,$b){return strcmp($b['sent_at'],$a['sent_at']);});
    $rows=array_slice($rows,0,500);
    // Check if stopped columns exist
    $hasStoppedCols=false;
    try{$hasStoppedCols=(bool)$pdo->query("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='customers' AND COLUMN_NAME='remarketing_stopped_at'")->fetchColumn();}catch(Exception $e){}
    $ejStoppedSql=$hasStoppedCols?'c.remarketing_stopped_at,c.remarketing_stopped_reason,':'NULL as remarketing_stopped_at,\'\' as remarketing_stopped_reason,';
    $wzStoppedSql=$hasStoppedCols?'p.remarketing_stopped_at,p.remarketing_stopped_reason,':'NULL as remarketing_stopped_at,\'\' as remarketing_stopped_reason,';
    // Active remarketing customers (easyJet) — show ALL who ever got claim email, not just active
    $ejSentCountSql=$rmSrc
      ?"(SELECT COUNT(*) FROM remarketing_logs rl2 WHERE rl2.customer_id=c.id AND rl2.send_ok=1 AND (rl2.source='customers' OR rl2.source=''))"
      :"(SELECT COUNT(*) FROM remarketing_logs rl2 WHERE rl2.customer_id=c.id AND rl2.send_ok=1)";
    $active=$pdo->query("
      SELECT c.id,c.first_name,c.last_name,c.email,c.booking_ref,c.flight_number,c.flight_date,c.departure,c.arrival,c.airline,
             c.claim_mail_sent_at,c.remarketing_active,c.id_doc_path,c.status,
             {$ejStoppedSql}
             {$ejSentCountSql} as sent_count,
             'customers' as source
      FROM customers c
      WHERE c.claim_mail_sent_at IS NOT NULL AND c.is_main=1
      ORDER BY c.claim_mail_sent_at DESC
    ")->fetchAll();
    // WZ passengers — show ALL who ever got claim email
    $wzSentCountSql=$rmSrc
      ?"(SELECT COUNT(*) FROM remarketing_logs rl2 WHERE rl2.customer_id=p.id AND rl2.send_ok=1 AND rl2.source='wz_passengers')"
      :"0";
    $wzActive=$pdo->query("
      SELECT p.id,p.first_name,p.last_name,p.email,b.pnr as booking_ref,b.flight_number,b.flight_date,
             b.origin as departure,b.destination as arrival,'Wizz Air' as airline,
             p.claim_mail_sent_at,p.remarketing_active,p.id_doc_path,p.status,
             {$wzStoppedSql}
             {$wzSentCountSql} as sent_count,
             'wz_passengers' as source
      FROM wz_passengers p
      JOIN wz_bookings b ON p.booking_id=b.id
      WHERE p.claim_mail_sent_at IS NOT NULL AND p.is_holder=1
      ORDER BY p.claim_mail_sent_at DESC
    ")->fetchAll();
    $active=array_merge($active,$wzActive);
    // Email tracking data (with source to distinguish easyJet vs WizzAir)
    $tracking=$pdo->query("
      SELECT customer_id,source,event_type,MIN(tracked_at) as first_at,MAX(tracked_at) as last_at,COUNT(*) as cnt
      FROM email_tracking
      GROUP BY customer_id,source,event_type
    ")->fetchAll();
    // Sub-passengers for each booking
    $subPax=$pdo->query("
      SELECT c.id,c.booking_ref,c.first_name,c.last_name,c.is_main,c.id_doc_filename,c.id_doc_path
      FROM customers c
      WHERE c.booking_ref IN (
        SELECT DISTINCT booking_ref FROM customers WHERE remarketing_active=1 OR claim_mail_sent_at IS NOT NULL
      )
      ORDER BY c.booking_ref,c.is_main DESC,c.id ASC
    ")->fetchAll();
    // WZ sub-passengers
    $wzSubPax=$pdo->query("
      SELECT p.id,b.pnr as booking_ref,p.first_name,p.last_name,p.is_holder as is_main,p.id_doc_filename,p.id_doc_path
      FROM wz_passengers p
      JOIN wz_bookings b ON p.booking_id=b.id
      WHERE b.pnr IN (
        SELECT DISTINCT b2.pnr FROM wz_passengers p2 JOIN wz_bookings b2 ON p2.booking_id=b2.id WHERE p2.remarketing_active=1 OR p2.claim_mail_sent_at IS NOT NULL
      )
      ORDER BY b.pnr,p.is_holder DESC,p.id ASC
    ")->fetchAll();
    $subPax=array_merge($subPax,$wzSubPax);
    echo json_encode(['ok'=>true,'logs'=>$rows,'active'=>$active,'tracking'=>$tracking,'subPax'=>$subPax]);exit;
  }
  if($_GET['action']==='stop_remarketing'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$source=$in['source']??'customers';$reason=$in['reason']??'Manual stop';
    if($id){
      // Try with stopped columns, fallback to just remarketing_active
      try{
        if($source==='wz_passengers'){$pdo->prepare("UPDATE wz_passengers SET remarketing_active=0,remarketing_stopped_at=NOW(),remarketing_stopped_reason=? WHERE id=?")->execute([$reason,$id]);}
        else{$pdo->prepare("UPDATE customers SET remarketing_active=0,remarketing_stopped_at=NOW(),remarketing_stopped_reason=? WHERE id=?")->execute([$reason,$id]);}
      }catch(Exception $e){
        if($source==='wz_passengers'){$pdo->prepare("UPDATE wz_passengers SET remarketing_active=0 WHERE id=?")->execute([$id]);}
        else{$pdo->prepare("UPDATE customers SET remarketing_active=0 WHERE id=?")->execute([$id]);}
      }
      echo json_encode(['ok'=>true]);
    }
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='restart_remarketing'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$source=$in['source']??'customers';
    if($id){
      try{
        if($source==='wz_passengers'){$pdo->prepare("UPDATE wz_passengers SET remarketing_active=1,remarketing_stopped_at=NULL,remarketing_stopped_reason='' WHERE id=?")->execute([$id]);}
        else{$pdo->prepare("UPDATE customers SET remarketing_active=1,remarketing_stopped_at=NULL,remarketing_stopped_reason='' WHERE id=?")->execute([$id]);}
      }catch(Exception $e){
        if($source==='wz_passengers'){$pdo->prepare("UPDATE wz_passengers SET remarketing_active=1 WHERE id=?")->execute([$id]);}
        else{$pdo->prepare("UPDATE customers SET remarketing_active=1 WHERE id=?")->execute([$id]);}
      }
      echo json_encode(['ok'=>true]);
    }
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='import_csv'){
    if(!isset($_FILES['file'])||$_FILES['file']['error']!==UPLOAD_ERR_OK){echo json_encode(['ok'=>false,'msg'=>'No file']);exit;}
    $csv=file_get_contents($_FILES['file']['tmp_name']);
    // Handle BOM
    $csv=preg_replace('/^\xEF\xBB\xBF/','',$csv);
    // Auto-detect encoding and convert to UTF-8
    if(!mb_check_encoding($csv,'UTF-8')){
      $enc=mb_detect_encoding($csv,['UTF-8','Windows-1252','ISO-8859-1','ISO-8859-15','ASCII'],true);
      if($enc&&$enc!=='UTF-8')$csv=mb_convert_encoding($csv,'UTF-8',$enc);
      else $csv=mb_convert_encoding($csv,'UTF-8','Windows-1252'); // fallback
    }
    $lines=preg_split('/\r\n|\r|\n/',$csv);
    if(count($lines)<2){echo json_encode(['ok'=>false,'msg'=>'Empty CSV']);exit;}
    
    // Parse header
    $header=str_getcsv(array_shift($lines));
    $header=array_map('trim',$header);
    
    // Map columns
    $colMap=[];
    $mapping=[
      'booking_ref'=>['Booking Number','Booking Ref','BookingNumber','booking_ref','PNR'],
      'flight_number'=>['Flight Number','FlightNumber','flight_number','Flight'],
      'flight_date'=>['Date','Flight Date','FlightDate','flight_date'],
      'departure'=>['Departure','From','departure'],
      'arrival'=>['Arrival','To','arrival'],
      'first_name'=>['First Name','FirstName','first_name','First'],
      'last_name'=>['Last Name','LastName','last_name','Last'],
      'email'=>['Email','email','E-mail'],
      'address_street'=>['Address','Street','address_street','Address 1'],
      'address_city'=>['City','city','address_city'],
      'address_country'=>['Country','country','address_country'],
      'address_postal'=>['ZIP','Postal','Zip','zip','Postal Code','address_postal'],
      'seat'=>['Seat','seat'],
      'phone'=>['Phone','phone','Phone Number'],
      'distance_km'=>['Length','Distance','distance_km','Distance (km)','Km'],
      'reason_raw'=>['Reason','reason','Disruption'],
    ];
    foreach($mapping as $field=>$aliases){
      foreach($aliases as $alias){
        $idx=array_search($alias,$header);
        if($idx!==false){$colMap[$field]=$idx;break;}
      }
    }
    
    if(!isset($colMap['booking_ref'])||!isset($colMap['first_name'])||!isset($colMap['last_name'])){
      echo json_encode(['ok'=>false,'msg'=>'Missing required columns: Booking Number, First Name, Last Name']);exit;
    }
    
    // Detect airline from flight number
    function detectAirline($fn){
      $fn=strtoupper(trim($fn));
      if(preg_match('/^(EZY|EZS|EJU)/',$fn))return'easyJet';
      if(preg_match('/^(FR|RK)/',$fn))return'Ryanair';
      if(preg_match('/^W[0-9]|^WZZ/',$fn))return'Wizz Air';
      if(preg_match('/^(LH)/',$fn))return'Lufthansa';
      if(preg_match('/^(BA)/',$fn))return'British Airways';
      if(preg_match('/^(AF)/',$fn))return'Air France';
      if(preg_match('/^(KL)/',$fn))return'KLM';
      if(preg_match('/^(VY)/',$fn))return'Vueling';
      if(preg_match('/^(U2)/',$fn))return'easyJet';
      return'Other';
    }
    
    // Parse date from various formats
    function parseDate($d){
      $d=trim($d);if(!$d)return null;
      // "Fri 31 Mar 2023" format
      $t=strtotime($d);
      if($t)return date('Y-m-d',$t);
      return null;
    }
    
    $imported=0;$skipped=0;$skipDup=0;$skipEmpty=0;$bookingGroups=[];$skipLog=[];
    
    // First pass: group by booking
    $rows=[];$lineNum=1;
    foreach($lines as $line){
      $lineNum++;
      $line=trim($line);if(!$line)continue;
      $cols=str_getcsv($line);
      $get=function($field)use($cols,$colMap){
        if(!isset($colMap[$field]))return'';
        $v=trim($cols[$colMap[$field]]??'');
        return($v==='N/A'||$v==='n/a')?'':$v;
      };
      $bk=$get('booking_ref');$fn=$get('first_name');$ln=$get('last_name');
      if(!$bk){
        $skipped++;$skipEmpty++;
        $skipLog[]='Row '.$lineNum.': missing booking_ref → "'.mb_substr(implode(',',$cols),0,80).'"';
        continue;
      }
      // Remove Mr/Mrs/Miss/Ms prefix
      $fn=preg_replace('/^(Mr|Mrs|Miss|Ms|Dr)\s+/i','',$fn);
      $rows[]=['bk'=>$bk,'fn'=>$fn,'ln'=>$ln,'cols'=>$cols,'get'=>$get,'lineNum'=>$lineNum];
      if(!isset($bookingGroups[$bk]))$bookingGroups[$bk]=0;
      $bookingGroups[$bk]++;
    }
    
    // Track first per booking = main
    $seenBookings=[];
    
    foreach($rows as $row){
      $bk=$row['bk'];$fn=$row['fn'];$ln=$row['ln'];$get=$row['get'];
      
      $flNum=$get('flight_number');
      $dt=parseDate($get('flight_date'));
      
      // Check if exists: same booking + name + flight + date
      $chk=$pdo->prepare("SELECT id FROM customers WHERE booking_ref=? AND first_name=? AND last_name=? AND flight_number=? AND flight_date=?");
      $chk->execute([$bk,$fn,$ln,$flNum,$dt]);
      if($chk->fetch()){
        $skipped++;$skipDup++;
        $skipLog[]='Duplicate: '.$fn.' '.$ln.' (booking: '.$bk.', flight: '.$flNum.', date: '.$dt.')';
        continue;
      }
      
      $isMain=!isset($seenBookings[$bk])?1:0;
      $seenBookings[$bk]=true;
      
      $airline=detectAirline($flNum);
      $dep=$get('departure');
      $arr=$get('arrival');
      $email=$get('email');
      $street=$get('address_street');
      $city=$get('address_city');
      $country=$get('address_country');
      $postal=$get('address_postal');
      $seat=$get('seat');
      
      // Smart address fix: in easyJet CSV, "City" often contains country name,
      // "State" contains postal code, and actual city is embedded in Address field.
      // Known countries list for detection
      $countries=['France','Germany','Spain','Italy','Portugal','Netherlands','Belgium',
        'Switzerland','Austria','United Kingdom','UK','Ireland','Poland','Greece','Turkey',
        'Czech Republic','Romania','Hungary','Croatia','Bulgaria','Slovakia','Slovenia',
        'Lithuania','Latvia','Estonia','Luxembourg','Malta','Cyprus','Iceland','Norway',
        'Sweden','Denmark','Finland','Canada','Colombia','Brazil','Morocco','Tunisia',
        'Israel','India','Australia','New Zealand','Japan','China','Thailand','USA','United States'];
      
      // If "City" looks like a country name and Country is empty/N/A
      $cityLooksLikeCountry=false;
      foreach($countries as $cn){
        if(strcasecmp($city,$cn)===0){$cityLooksLikeCountry=true;break;}
      }
      
      if($cityLooksLikeCountry && !$country){
        // City is actually the country
        $actualCountry=$city;
        $city='';
        $country=$actualCountry;
        
        // State field might have the postal code
        // Access State column directly
        $stateIdx=array_search('State',$header);
        if($stateIdx!==false){
          $stateVal=trim($cols[$stateIdx]??'');
          if($stateVal && $stateVal!=='N/A' && $stateVal!=='n/a'){
            $postal=$stateVal;
          }
        }
        
        // Try to extract city from the end of street address
        // e.g. "18 Rue du Clos des Abbesses YERRES" → city = YERRES
        // e.g. "Schipluidenlaan 596 Amsterdam" → city = Amsterdam
        if($street){
          $parts=preg_split('/\s+/',$street);
          if(count($parts)>=2){
            $lastWord=end($parts);
            // If last word is all uppercase or starts with uppercase and is > 2 chars, likely a city
            if(strlen($lastWord)>2 && (ctype_upper($lastWord) || ctype_upper($lastWord[0]))){
              $city=$lastWord;
              $street=implode(' ',array_slice($parts,0,-1));
            }
          }
        }
      }
      
      // If country is still empty but city has a value, try to detect from address
      if(!$country && $street){
        // Check Address 2 field for additional info
        $addr2Idx=array_search('Address 2',$header);
        if($addr2Idx!==false){
          $addr2=trim($cols[$addr2Idx]??'');
          if($addr2 && $addr2!=='N/A' && $addr2!=='n/a'){
            $street.=', '.$addr2;
          }
        }
      }
      
      $custId='CU-'.strtoupper(substr(md5($fn.$ln.$bk.time().rand()),0,8));
      
      // Distance - store as integer
      $distRaw=$get('distance_km');
      $distKm=$distRaw?intval(preg_replace('/[^0-9]/','',$distRaw)):null;
      
      // Reason - store raw (formatting happens in JS)
      $reason=$get('reason_raw');
      
      $pdo->prepare("INSERT INTO customers (customer_id,booking_ref,flight_number,flight_date,departure,arrival,first_name,last_name,email,airline,is_main,address_street,address_city,address_postal,address_country,seat,distance_km,reason,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'doc_needed')")
        ->execute([$custId,$bk,$flNum,$dt,$dep,$arr,$fn,$ln,$email,$airline,$isMain,$street,$city,$postal,$country,$seat,$distKm,$reason]);
      $imported++;
    }
    
    echo json_encode(['ok'=>true,'imported'=>$imported,'skipped'=>$skipped,'skipDup'=>$skipDup,'skipEmpty'=>$skipEmpty,'skipLog'=>$skipLog]);exit;
  }
  if($_GET['action']==='import_flights'){
    if(!isset($_FILES['file'])||$_FILES['file']['error']!==UPLOAD_ERR_OK){echo json_encode(['ok'=>false,'msg'=>'No file']);exit;}
    $csv=file_get_contents($_FILES['file']['tmp_name']);
    $csv=preg_replace('/^\xEF\xBB\xBF/','',$csv);
    $lines=preg_split('/\r\n|\r|\n/',$csv);
    if(count($lines)<2){echo json_encode(['ok'=>false,'msg'=>'Empty CSV']);exit;}
    // Detect delimiter
    $firstLine=$lines[0];
    $delim=strpos($firstLine,';')!==false?';':',';
    
    // Check if first line is header or data
    $firstCols=str_getcsv($firstLine,$delim);
    $hasHeader=false;
    $headerAliases=['date','flight_date','flightdate','flightnumber','flight_number','flight number','flight','reason','disruption','status','length','distance','km','distance_km'];
    foreach($firstCols as $c){if(in_array(strtolower(trim($c)),$headerAliases)){$hasHeader=true;break;}}
    
    if($hasHeader){
      $header=array_map('trim',str_getcsv(array_shift($lines),$delim));
      $dateIdx=$flIdx=$rsnIdx=$distIdx=-1;
      foreach($header as $i=>$h){
        $hl=strtolower($h);
        if(in_array($hl,['date','flight_date','flightdate']))$dateIdx=$i;
        if(in_array($hl,['flightnumber','flight_number','flight number','flight']))$flIdx=$i;
        if(in_array($hl,['reason','disruption','status']))$rsnIdx=$i;
        if(in_array($hl,['length','distance','km','distance_km']))$distIdx=$i;
      }
    }else{
      // No header — assume order: DATE;FlightNumber;Reason;Length
      $dateIdx=0;$flIdx=1;$rsnIdx=2;$distIdx=3;
    }
    
    if($dateIdx<0||$flIdx<0){echo json_encode(['ok'=>false,'msg'=>'Cannot detect DATE or FlightNumber columns']);exit;}
    $imported=0;$skipped=0;
    $stmt=$pdo->prepare("INSERT INTO flight_data (flight_date,flight_number,reason,distance_km) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE reason=VALUES(reason),distance_km=VALUES(distance_km)");
    foreach($lines as $line){
      $line=trim($line);if(!$line)continue;
      $cols=str_getcsv($line,$delim);
      $dt=trim($cols[$dateIdx]??'');$fl=strtoupper(trim($cols[$flIdx]??''));
      $rsn=$rsnIdx>=0?trim($cols[$rsnIdx]??''):'';
      if($rsn==='N/A'||$rsn==='n/a')$rsn='';
      $dist=$distIdx>=0?trim($cols[$distIdx]??''):null;
      if($dist==='N/A'||$dist==='n/a'||$dist==='')$dist=null;
      else $dist=intval(preg_replace('/[^0-9]/','',$dist))?:null;
      if(!$dt||!$fl){$skipped++;continue;}
      $parsed=strtotime($dt);if(!$parsed){$skipped++;continue;}
      $dtFmt=date('Y-m-d',$parsed);
      $stmt->execute([$dtFmt,$fl,$rsn,$dist]);
      $imported++;
    }
    // Auto-fill reason + distance_km in customers
    autoFillCustomersFromFlights($pdo);
    echo json_encode(['ok'=>true,'imported'=>$imported,'skipped'=>$skipped]);exit;
  }
  if($_GET['action']==='get_flights'){
    $rows=$pdo->query("SELECT * FROM flight_data ORDER BY flight_date DESC, flight_number ASC")->fetchAll();
    echo json_encode(['ok'=>true,'flights'=>$rows]);exit;
  }
  if($_GET['action']==='delete_flight'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){$pdo->prepare("DELETE FROM flight_data WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='import_airhelp'){
    if(!isset($_FILES['file'])||$_FILES['file']['error']!==UPLOAD_ERR_OK){echo json_encode(['ok'=>false,'msg'=>'No file']);exit;}
    $txt=file_get_contents($_FILES['file']['tmp_name']);
    $txt=preg_replace('/^\xEF\xBB\xBF/','',$txt);
    $lines=preg_split('/\r\n|\r|\n/',$txt);
    
    $imported=0;$skipped=0;
    $currentFlight=null;
    $detailLines=[];
    
    // Process function: save collected flight + detail lines
    $processFlight=function() use (&$currentFlight,&$detailLines,&$imported,&$skipped,&$pdo){
      if(!$currentFlight)return;
      $fn=$currentFlight['fn'];
      $dt=$currentFlight['dt'];
      
      // Parse detail lines for disruption info, distance, eligible status
      $eligible='';$note='';$distKm=null;$delayMin=null;$reasonDetail='';
      
      foreach($detailLines as $dl){
        // Check for ELIGIBLE
        if(stripos($dl,'ELIGIBLE')!==false && stripos($dl,"doesn't qualify")===false && stripos($dl,'not qualify')===false){
          $eligible='ELIGIBLE';
          if(!$note)$note=$dl;
        }
        // Check for NOT ELIGIBLE
        if(stripos($dl,"doesn't qualify")!==false||stripos($dl,'not qualify')!==false){
          if($eligible!=='ELIGIBLE')$eligible='NOT ELIGIBLE'; // don't downgrade ELIGIBLE
          $note=$dl;
        }
        
        // Parse Disruption line: "Disruption: CANCELLED | Distance: 1214 km | Compensation: €250..."
        if(preg_match('/Disruption:\s*(CANCELLED|DELAYED)/i',$dl,$dm)){
          $reasonDetail=strtolower($dm[1])==='cancelled'?'Cancelled':$dm[1];
        }
        // Parse distance
        if(preg_match('/Distance:\s*(\d[\d,]*)\s*km/i',$dl,$ddm)){
          $distKm=intval(str_replace(',','',$ddm[1]));
        }
        // Parse delay: "Delay: 11 hours 42 minutes"
        if(preg_match('/Delay:\s*(\d+)\s*hour/i',$dl,$dhm)){
          $delayMin=intval($dhm[1])*60;
          if(preg_match('/(\d+)\s*minute/i',$dl,$dmm))$delayMin+=intval($dmm[1]);
          $reasonDetail=strval($delayMin); // store as minutes number
        }
      }
      
      // Use reason from disruption detail if available, otherwise from flight line
      $reason=$reasonDetail?:$currentFlight['reason'];
      
      // Generate aliases
      $aliases=easyjetAliases($fn);
      $aliasStr=implode(', ',$aliases);
      
      // Find existing record by any alias
      $found=false;
      foreach($aliases as $alias){
        $chk=$pdo->prepare("SELECT id FROM flight_data WHERE flight_number=? AND flight_date=?");
        $chk->execute([$alias,$dt]);
        if($row=$chk->fetch()){
          // Always overwrite with newest data
          $sql="UPDATE flight_data SET airhelp_eligible=?,airhelp_note=?,airhelp_source=?,flight_aliases=?,departure_iata=?,arrival_iata=?,reason=?";
          $params=[$eligible,$note,$currentFlight['source'],$aliasStr,$currentFlight['dep'],$currentFlight['arr'],$reason];
          if($distKm){$sql.=",distance_km=?";$params[]=$distKm;}
          $sql.=" WHERE id=?";$params[]=$row['id'];
          $pdo->prepare($sql)->execute($params);
          $found=true;$imported++;break;
        }
      }
      
      if(!$found){
        $pdo->prepare("INSERT INTO flight_data (flight_date,flight_number,flight_aliases,departure_iata,arrival_iata,reason,distance_km,airhelp_eligible,airhelp_note,airhelp_source) VALUES (?,?,?,?,?,?,?,?,?,?)")
          ->execute([$dt,$fn,$aliasStr,$currentFlight['dep'],$currentFlight['arr'],$reason,$distKm,$eligible,$note,$currentFlight['source']]);
        $imported++;
      }
      
      $currentFlight=null;
      $detailLines=[];
    };
    
    foreach($lines as $line){
      $line=trim($line);
      
      // Separator or end — process previous flight
      if(str_starts_with($line,'---')||str_starts_with($line,'===')){
        $processFlight();
        continue;
      }
      
      // Parse flight line: [OK]  U2 1455  |  GVA -> OPO  |  03/07/2016  |  cancelled  |  Flight: SELECTED
      if(preg_match('/^\[OK\]\s+(.+?)\s*\|\s*([A-Z]{3})\s*->\s*([A-Z]{3})\s*\|\s*(\d{2}\/\d{2}\/\d{4})\s*\|\s*(.+?)\s*\|\s*Flight:\s*(.+)$/i',$line,$m)){
        // Process previous flight before starting new one
        $processFlight();
        
        $flRaw=trim($m[1]);
        $dep=trim($m[2]);
        $arr=trim($m[3]);
        $dateRaw=trim($m[4]);
        $reason=trim($m[5]);
        $source=trim($m[6]);
        
        $flNum=strtoupper(preg_replace('/\s+/','',$flRaw));
        
        $parts=explode('/',$dateRaw);
        $dt=count($parts)===3?$parts[2].'-'.$parts[1].'-'.$parts[0]:null;
        if(!$dt){$skipped++;continue;}
        
        if(strtolower($reason)==='cancelled'||strtolower($reason)==='canceled')$reason='Cancelled';
        
        $currentFlight=['fn'=>$flNum,'dt'=>$dt,'dep'=>$dep,'arr'=>$arr,'reason'=>$reason,'source'=>$source];
        $detailLines=[];
        continue;
      }
      
      // Any other non-empty line after a flight line = detail line
      if($currentFlight && $line){
        $detailLines[]=$line;
      }
    }
    // Process last flight
    $processFlight();
    
    // Auto-fill customers
    autoFillCustomersFromFlights($pdo);
    echo json_encode(['ok'=>true,'imported'=>$imported,'skipped'=>$skipped]);exit;
  }

  // ===== WIZZ AIR ACTIONS =====
  if($_GET['action']==='wz_get_data'){
    $accounts=$pdo->query("SELECT * FROM wz_accounts ORDER BY holder_name ASC")->fetchAll();
    $bookings=$pdo->query("SELECT * FROM wz_bookings ORDER BY flight_date DESC")->fetchAll();
    $passengers=$pdo->query("SELECT * FROM wz_passengers ORDER BY is_holder DESC, passenger_name ASC")->fetchAll();
    echo json_encode(['ok'=>true,'accounts'=>$accounts,'bookings'=>$bookings,'passengers'=>$passengers]);exit;
  }
  if($_GET['action']==='wz_import_csv'){
    if(!isset($_FILES['file'])||$_FILES['file']['error']!==UPLOAD_ERR_OK){echo json_encode(['ok'=>false,'msg'=>'No file']);exit;}
    $txt=file_get_contents($_FILES['file']['tmp_name']);
    $txt=preg_replace('/^\xEF\xBB\xBF/','',$txt);
    $lines=preg_split('/\r\n|\r|\n/',$txt);
    if(count($lines)<2){echo json_encode(['ok'=>false,'msg'=>'Empty file']);exit;}
    // Detect delimiter
    $firstLine=$lines[0];
    $delim=substr_count($firstLine,';')>substr_count($firstLine,',')?';':',';
    if(substr_count($firstLine,"\t")>substr_count($firstLine,$delim))$delim="\t";
    $header=array_map('trim',str_getcsv(array_shift($lines),$delim));
    // Map columns flexibly
    $colMap=[];
    $aliases=[
      'account_number'=>['Account_Number','Account Number','AccountNumber','account_number'],
      'account_created'=>['Account_Created','Account Created','AccountCreated','account_created'],
      'holder_name'=>['Account_Holder_Name','Account Holder Name','Holder Name','holder_name'],
      'holder_gender'=>['Account_Holder_Gender','Holder Gender','holder_gender'],
      'holder_dob'=>['Account_Holder_DOB','Holder DOB','holder_dob','Date of Birth'],
      'nationality'=>['Nationality','nationality'],
      'phone'=>['Phone','phone','Phone Number'],
      'address'=>['Address','address'],
      'passport_number'=>['Passport_Number','Passport Number','passport_number'],
      'passport_issued_country'=>['Passport_Issued_Country','Passport Issued Country','passport_issued_country'],
      'passport_expiry'=>['Passport_Expiry','Passport Expiry','passport_expiry'],
      'loyalty_program'=>['Loyalty_Program','Loyalty Program','loyalty_program'],
      'loyalty_status'=>['Loyalty_Status','Loyalty Status','loyalty_status'],
      'flight_category'=>['Flight_Category','Flight Category','flight_category'],
      'pnr'=>['PNR','pnr','Booking Reference'],
      'flight_number'=>['Flight_Number','Flight Number','flight_number'],
      'flight_date'=>['Flight_Date','Flight Date','flight_date'],
      'origin'=>['Origin','origin','Departure'],
      'destination'=>['Destination','destination','Arrival'],
      'flight_status'=>['Flight_Status','Flight Status','flight_status'],
      'pax_count'=>['Pax_Count','Pax Count','pax_count'],
      'cost'=>['Cost','cost','Price'],
      'passenger_name'=>['Passenger_Name','Passenger Name','passenger_name'],
      'passenger_gender'=>['Passenger_Gender','Passenger Gender','passenger_gender'],
      'seat'=>['Seat','seat'],
      'checkin_status'=>['Checkin_Status','Checkin Status','checkin_status','Check-in Status'],
      'travel_document'=>['Travel_Document','Travel Document','travel_document']
    ];
    foreach($aliases as $f=>$al){foreach($al as $a){$idx=array_search($a,$header);if($idx!==false){$colMap[$f]=$idx;break;}}}
    if(!isset($colMap['account_number'])){echo json_encode(['ok'=>false,'msg'=>'Missing required column: Account_Number']);exit;}
    
    $imported=0;$skipped=0;$accountsCreated=0;$bookingsCreated=0;$passengersCreated=0;
    $g=function($f,$cols)use($colMap){if(!isset($colMap[$f]))return'';return trim($cols[$colMap[$f]]??'');};
    
    foreach($lines as $line){
      $line=trim($line);if(!$line)continue;
      $cols=str_getcsv($line,$delim);
      $accNum=$g('account_number',$cols);
      if(!$accNum){$skipped++;continue;}
      
      // Parse dates
      $parseDate=function($d){
        if(!$d)return null;
        $d=trim($d);
        // Try various formats
        foreach(['Y-m-d','d/m/Y','m/d/Y','Y/m/d','d-m-Y','d.m.Y'] as $fmt){
          $dt=DateTime::createFromFormat($fmt,$d);
          if($dt)return $dt->format('Y-m-d');
        }
        $ts=strtotime($d);
        return $ts?date('Y-m-d',$ts):null;
      };
      
      // Upsert account
      $holderName=$g('holder_name',$cols);
      $accCreated=$parseDate($g('account_created',$cols));
      $holderGender=$g('holder_gender',$cols);
      $holderDob=$parseDate($g('holder_dob',$cols));
      $nationality=$g('nationality',$cols);
      $phone=$g('phone',$cols);
      $address=$g('address',$cols);
      $passportNum=$g('passport_number',$cols);
      $passportCountry=$g('passport_issued_country',$cols);
      $passportExpiry=$parseDate($g('passport_expiry',$cols));
      $loyaltyProg=$g('loyalty_program',$cols);
      $loyaltyStatus=$g('loyalty_status',$cols);
      
      $existAcc=$pdo->prepare("SELECT id FROM wz_accounts WHERE account_number=?");
      $existAcc->execute([$accNum]);
      $accRow=$existAcc->fetch();
      if(!$accRow){
        $pdo->prepare("INSERT INTO wz_accounts (account_number,account_created,holder_name,holder_gender,holder_dob,nationality,phone,address,passport_number,passport_issued_country,passport_expiry,loyalty_program,loyalty_status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")
          ->execute([$accNum,$accCreated,$holderName,$holderGender,$holderDob,$nationality,$phone,$address,$passportNum,$passportCountry,$passportExpiry,$loyaltyProg,$loyaltyStatus]);
        $accId=$pdo->lastInsertId();
        $accountsCreated++;
      } else {
        $accId=$accRow['id'];
        // Update account data
        $pdo->prepare("UPDATE wz_accounts SET holder_name=COALESCE(NULLIF(?,''  ),holder_name),account_created=COALESCE(?,account_created),holder_gender=COALESCE(NULLIF(?,''),holder_gender),holder_dob=COALESCE(?,holder_dob),nationality=COALESCE(NULLIF(?,''),nationality),phone=COALESCE(NULLIF(?,''),phone),address=COALESCE(NULLIF(?,''),address),passport_number=COALESCE(NULLIF(?,''),passport_number),passport_issued_country=COALESCE(NULLIF(?,''),passport_issued_country),passport_expiry=COALESCE(?,passport_expiry),loyalty_program=COALESCE(NULLIF(?,''),loyalty_program),loyalty_status=COALESCE(NULLIF(?,''),loyalty_status) WHERE id=?")
          ->execute([$holderName,$accCreated,$holderGender,$holderDob,$nationality,$phone,$address,$passportNum,$passportCountry,$passportExpiry,$loyaltyProg,$loyaltyStatus,$accId]);
      }
      
      // Upsert booking (if PNR + flight data present)
      $pnr=$g('pnr',$cols);
      $flNum=$g('flight_number',$cols);
      $flDate=$parseDate($g('flight_date',$cols));
      
      $bookingId=null;
      if($pnr && $flNum && $flDate){
        $origin=$g('origin',$cols);$dest=$g('destination',$cols);
        $originIata='';$destIata='';
        if(preg_match('/\(([A-Z]{3})\)/',$origin,$m))$originIata=$m[1];
        elseif(preg_match('/^[A-Z]{3}$/',$origin))$originIata=$origin;
        if(preg_match('/\(([A-Z]{3})\)/',$dest,$m))$destIata=$m[1];
        elseif(preg_match('/^[A-Z]{3}$/',$dest))$destIata=$dest;
        $flStatus=$g('flight_status',$cols)?:'scheduled';
        $flCat=$g('flight_category',$cols);
        $paxCount=intval($g('pax_count',$cols))?:1;
        $cost=floatval(str_replace(',','.',$g('cost',$cols)));
        
        $existBk=$pdo->prepare("SELECT id FROM wz_bookings WHERE account_id=? AND pnr=? AND flight_number=? AND flight_date=?");
        $existBk->execute([$accId,$pnr,$flNum,$flDate]);
        $bkRow=$existBk->fetch();
        if(!$bkRow){
          $pdo->prepare("INSERT INTO wz_bookings (account_id,pnr,flight_number,flight_date,origin,origin_iata,destination,destination_iata,flight_status,flight_category,pax_count,cost) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)")
            ->execute([$accId,$pnr,$flNum,$flDate,$origin,$originIata,$dest,$destIata,$flStatus,$flCat,$paxCount,$cost]);
          $bookingId=$pdo->lastInsertId();
          $bookingsCreated++;
        } else {
          $bookingId=$bkRow['id'];
          $pdo->prepare("UPDATE wz_bookings SET origin=COALESCE(NULLIF(?,''),origin),origin_iata=COALESCE(NULLIF(?,''),origin_iata),destination=COALESCE(NULLIF(?,''),destination),destination_iata=COALESCE(NULLIF(?,''),destination_iata),flight_status=COALESCE(NULLIF(?,''),flight_status),flight_category=COALESCE(NULLIF(?,''),flight_category),pax_count=?,cost=? WHERE id=?")
            ->execute([$origin,$originIata,$dest,$destIata,$flStatus,$flCat,$paxCount,$cost,$bookingId]);
        }
      }
      
      // Add passenger (if name present)
      $paxName=$g('passenger_name',$cols);
      if($paxName && $bookingId){
        $paxGender=$g('passenger_gender',$cols);
        $seat=$g('seat',$cols);
        $checkin=$g('checkin_status',$cols);
        $travelDoc=$g('travel_document',$cols);
        $isHolder=(strtolower(trim($paxName))===strtolower(trim($holderName)))?1:0;
        
        // Check duplicate
        $existPax=$pdo->prepare("SELECT id FROM wz_passengers WHERE booking_id=? AND passenger_name=?");
        $existPax->execute([$bookingId,$paxName]);
        if(!$existPax->fetch()){
          $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,passenger_gender,seat,checkin_status,travel_document,is_holder) VALUES (?,?,?,?,?,?,?,?)")
            ->execute([$bookingId,$accId,$paxName,$paxGender,$seat,$checkin,$travelDoc,$isHolder]);
          $passengersCreated++;
        } else {
          $pdo->prepare("UPDATE wz_passengers SET passenger_gender=COALESCE(NULLIF(?,''),passenger_gender),seat=COALESCE(NULLIF(?,''),seat),checkin_status=COALESCE(NULLIF(?,''),checkin_status),travel_document=COALESCE(NULLIF(?,''),travel_document) WHERE booking_id=? AND passenger_name=?")
            ->execute([$paxGender,$seat,$checkin,$travelDoc,$bookingId,$paxName]);
        }
      }
      $imported++;
    }
    echo json_encode(['ok'=>true,'imported'=>$imported,'skipped'=>$skipped,'accounts'=>$accountsCreated,'bookings'=>$bookingsCreated,'passengers'=>$passengersCreated]);exit;
  }
  if($_GET['action']==='wz_delete_account'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){$pdo->prepare("DELETE FROM wz_accounts WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_update_account'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$field=$in['field']??'';$value=$in['value']??'';
    $allowed=['holder_name','holder_gender','holder_dob','nationality','phone','address','passport_number','passport_issued_country','passport_expiry','loyalty_program','loyalty_status','email','notes'];
    if($id && in_array($field,$allowed)){
      $pdo->prepare("UPDATE wz_accounts SET $field=? WHERE id=?")->execute([$value,$id]);
      echo json_encode(['ok'=>true]);
    } else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_update_passenger'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$field=$in['field']??'';$value=$in['value']??'';
    $allowed=['first_name','last_name','email','seat','checkin_status','status','claim_method','notes','mail_template','dob','nationality','passport_number','passport_issued_country','passport_expiry','phone','address'];
    if($id && in_array($field,$allowed)){
      $pdo->prepare("UPDATE wz_passengers SET $field=?,updated_at=NOW() WHERE id=?")->execute([$value,$id]);
      echo json_encode(['ok'=>true]);
    } else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_log_status'){
    $in=json_decode(file_get_contents('php://input'),true);$id=intval($in['id']??0);$status=$in['status']??'';
    if($id&&$status){$pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$status]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_update_booking'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$field=$in['field']??'';$value=$in['value']??'';
    $allowed=['pnr','flight_number','flight_date','origin','destination','flight_status','reason','distance_km','cost'];
    if($id && in_array($field,$allowed)){
      if($field==='distance_km')$value=$value?intval($value):null;
      if($field==='cost')$value=$value?floatval($value):0;
      $pdo->prepare("UPDATE wz_bookings SET $field=?,updated_at=NOW() WHERE id=?")->execute([$value,$id]);
      echo json_encode(['ok'=>true]);
    } else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_upload_doc'){
    $id=$_POST['id']??0;$dt=$_POST['doc_type']??'';
    $col=($dt==='id')?'id_doc':'travel_doc';
    if($id&&isset($_FILES['file'])&&$_FILES['file']['error']===UPLOAD_ERR_OK){
      $f=$_FILES['file'];$ud=__DIR__.'/uploads/';if(!is_dir($ud))mkdir($ud,0755,true);
      $ext=pathinfo($f['name'],PATHINFO_EXTENSION);$sn="wz_{$id}_{$dt}_".time().".{$ext}";
      if(move_uploaded_file($f['tmp_name'],$ud.$sn)){
        $pdo->prepare("UPDATE wz_passengers SET {$col}_filename=?,{$col}_path=?,updated_at=NOW() WHERE id=?")->execute([$f['name'],$sn,$id]);
        echo json_encode(['ok'=>true,'filename'=>$f['name'],'path'=>$sn]);
      }else echo json_encode(['ok'=>false]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_delete_doc'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$dt=$in['doc_type']??'';
    $col=($dt==='id')?'id_doc':'travel_doc';$vc=($dt==='id')?'id_doc_viewed':'travel_doc_viewed';
    if($id){
      $pdo->prepare("UPDATE wz_passengers SET {$col}_filename=NULL,{$col}_path=NULL,{$vc}=0,updated_at=NOW() WHERE id=?")->execute([$id]);
      echo json_encode(['ok'=>true]);
    }exit;
  }
  if($_GET['action']==='wz_mark_viewed'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;$dt=$in['doc_type']??'';
    $col=($dt==='id')?'id_doc_viewed':'travel_doc_viewed';
    if($id){$pdo->prepare("UPDATE wz_passengers SET {$col}=1,updated_at=NOW() WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_delete_passenger'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){$pdo->prepare("DELETE FROM wz_passengers WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}
    else echo json_encode(['ok'=>false]);exit;
  }
  // ===== WZ: SEND MAIL =====
  if($_GET['action']==='wz_send_mail'){
    $in=json_decode(file_get_contents('php://input'),true);$pid=$in['id']??0;$tpl=$in['template']??'';
    if(!$pid||!$tpl){echo json_encode(['ok'=>false,'message'=>'Missing id or template']);exit;}
    // Get passenger + booking + account
    $ps=$pdo->prepare("SELECT p.*,b.pnr,b.flight_number,b.flight_date,b.origin,b.origin_iata,b.destination,b.destination_iata,b.distance_km AS bk_distance_km,b.reason AS bk_reason,a.account_number,a.holder_name,a.email AS acc_email FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id JOIN wz_accounts a ON p.account_id=a.id WHERE p.id=?");
    $ps->execute([$pid]);$pax=$ps->fetch();
    if(!$pax){echo json_encode(['ok'=>false,'message'=>'Passenger not found']);exit;}
    $email=$pax['email']?:$pax['acc_email'];
    if(!$email){echo json_encode(['ok'=>false,'message'=>'No email address']);exit;}
    $toName=trim(($pax['first_name']?:$pax['passenger_name']).' '.($pax['last_name']?:''));
    // Build fake customer array for mailer compatibility
    $fakeCustomer=['id'=>$pid,'first_name'=>$pax['first_name']?:$pax['passenger_name'],'last_name'=>$pax['last_name']??'','email'=>$email,'booking_ref'=>$pax['pnr'],'flight_number'=>$pax['flight_number'],'flight_date'=>$pax['flight_date'],'departure'=>$pax['origin'],'arrival'=>$pax['destination'],'airline'=>'Wizz Air','distance_km'=>$pax['bk_distance_km'],'reason'=>$pax['bk_reason'],'address_street'=>'','address_city'=>'','address_postal'=>'','address_country'=>'','customer_id'=>'WZ-'.$pid,'is_main'=>$pax['is_holder']];
    // Get all pax in same booking for claim link
    $allPaxStmt=$pdo->prepare("SELECT first_name,last_name,passenger_name FROM wz_passengers WHERE booking_id=? ORDER BY is_holder DESC, id ASC");
    $allPaxStmt->execute([$pax['booking_id']]);$allPax=array_map(function($p){return['first_name'=>$p['first_name']?:explode(' ',$p['passenger_name'])[0]??'','last_name'=>$p['last_name']?:implode(' ',array_slice(explode(' ',$p['passenger_name']),1))];},$allPaxStmt->fetchAll());
    require_once __DIR__.'/mailer.php';
    $claimLink=buildWzClaimLink($fakeCustomer,$allPax);
    if($tpl==='claim_submit'){$htmlBody=buildWzNotificationEmail($fakeCustomer,$claimLink,$allPax);$subject='Claim up to €600 for your Wizz Air flight';}
    else{$ts=$pdo->prepare("SELECT * FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$t=$ts->fetch();if(!$t){echo json_encode(['ok'=>false,'message'=>'Template not found']);exit;}$subject=replacePlaceholders($t['subject'],$fakeCustomer,$claimLink,$allPax);$body=replacePlaceholders($t['body'],$fakeCustomer,$claimLink,$allPax);$htmlBody=buildSimpleEmail($body,$fakeCustomer);}
    if(MAIL_METHOD==='brevo'){$result=sendViaBrevo($email,$toName,$subject,$htmlBody);}
    elseif(MAIL_METHOD==='resend'){$result=sendViaResend($email,$toName,$subject,$htmlBody,'support@support.eu261compensation.com','SkyClaim — Wizz Air');}
    else{$result=sendViaPhpMail($email,$toName,$subject,$htmlBody);}
    if(!$result['ok']){echo json_encode($result);exit;}
    // Update passenger
    $newStatus='';
    if($tpl==='claim_submit')$newStatus='form_sent';
    elseif($tpl==='hibas_id')$newStatus='bad_id_sent';
    if($newStatus){$pdo->prepare("UPDATE wz_passengers SET mail_sent_at=NOW(),mail_template=?,status=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$newStatus,$pid]);
      $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$pid,$newStatus]);
      // Activate remarketing on claim_submit — always on the HOLDER of this booking
      if($tpl==='claim_submit'){
        // Activate on the sent passenger
        $pdo->prepare("UPDATE wz_passengers SET remarketing_active=1,claim_mail_sent_at=NOW() WHERE id=? AND remarketing_active=0")->execute([$pid]);
        // Also activate on the holder if this is a sub-passenger
        if(!$pax['is_holder']){
          $pdo->prepare("UPDATE wz_passengers SET remarketing_active=1,claim_mail_sent_at=COALESCE(claim_mail_sent_at,NOW()) WHERE booking_id=? AND is_holder=1 AND remarketing_active=0")->execute([$pax['booking_id']]);
        }
      }
    }
    else{$pdo->prepare("UPDATE wz_passengers SET mail_sent_at=NOW(),mail_template=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$pid]);}
    // Log
    $ts2=$pdo->prepare("SELECT label FROM mail_templates WHERE slug=?");$ts2->execute([$tpl]);$tRow=$ts2->fetch();$tLabel=$tRow?$tRow['label']:$tpl;
    $pdo->prepare("INSERT INTO mail_history (customer_id,template_slug,template_label) VALUES (?,?,?)")->execute([$pid,$tpl,$tLabel]);
    $st2=$pdo->prepare("SELECT mail_sent_at,status FROM wz_passengers WHERE id=?");$st2->execute([$pid]);$r2=$st2->fetch();
    echo json_encode(['ok'=>true,'mail_sent_at'=>$r2['mail_sent_at'],'new_status'=>$r2['status'],'email_message'=>$result['message']]);exit;
  }
  // ===== WZ: BULK SEND MAIL =====
  if($_GET['action']==='wz_bulk_send_mail'){
    $in=json_decode(file_get_contents('php://input'),true);$ids=$in['ids']??[];
    if(!is_array($ids)||!count($ids)){echo json_encode(['ok'=>false]);exit;}
    $sent=0;$failed=0;$errors=[];
    foreach($ids as $item){
      $pid=$item['id']??0;$tpl=$item['template']??'';
      if(!$pid||!$tpl)continue;
      // Re-use wz_send_mail logic inline
      $ps=$pdo->prepare("SELECT p.*,b.pnr,b.flight_number,b.flight_date,b.origin,b.destination,b.distance_km AS bk_distance_km,b.reason AS bk_reason,a.email AS acc_email FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id JOIN wz_accounts a ON p.account_id=a.id WHERE p.id=?");
      $ps->execute([$pid]);$pax=$ps->fetch();
      if(!$pax){$failed++;continue;}
      $email=$pax['email']?:$pax['acc_email'];
      if(!$email){$failed++;$errors[]='No email for '.$pax['passenger_name'];continue;}
      $toName=trim(($pax['first_name']?:$pax['passenger_name']).' '.($pax['last_name']?:''));
      $fakeCustomer=['id'=>$pid,'first_name'=>$pax['first_name']?:$pax['passenger_name'],'last_name'=>$pax['last_name']??'','email'=>$email,'booking_ref'=>$pax['pnr'],'flight_number'=>$pax['flight_number'],'flight_date'=>$pax['flight_date'],'departure'=>$pax['origin'],'arrival'=>$pax['destination'],'airline'=>'Wizz Air','distance_km'=>$pax['bk_distance_km'],'reason'=>$pax['bk_reason'],'address_street'=>'','address_city'=>'','address_postal'=>'','address_country'=>'','customer_id'=>'WZ-'.$pid,'is_main'=>$pax['is_holder']];
      $allPaxStmt=$pdo->prepare("SELECT first_name,last_name,passenger_name FROM wz_passengers WHERE booking_id=? ORDER BY is_holder DESC");
      $allPaxStmt->execute([$pax['booking_id']]);$allPax=array_map(function($p){return['first_name'=>$p['first_name']?:explode(' ',$p['passenger_name'])[0]??'','last_name'=>$p['last_name']?:implode(' ',array_slice(explode(' ',$p['passenger_name']),1))];},$allPaxStmt->fetchAll());
      require_once __DIR__.'/mailer.php';
      $claimLink=buildWzClaimLink($fakeCustomer,$allPax);
      if($tpl==='claim_submit'){$htmlBody=buildWzNotificationEmail($fakeCustomer,$claimLink,$allPax);$subject='Claim up to €600 for your Wizz Air flight';}
      else{$ts=$pdo->prepare("SELECT * FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$t=$ts->fetch();if(!$t){$failed++;continue;}$subject=replacePlaceholders($t['subject'],$fakeCustomer,$claimLink,$allPax);$body=replacePlaceholders($t['body'],$fakeCustomer,$claimLink,$allPax);$htmlBody=buildSimpleEmail($body,$fakeCustomer);}
      if(MAIL_METHOD==='brevo'){$result=sendViaBrevo($email,$toName,$subject,$htmlBody);}
      elseif(MAIL_METHOD==='resend'){$result=sendViaResend($email,$toName,$subject,$htmlBody,'support@support.eu261compensation.com','SkyClaim — Wizz Air');}
      else{$result=sendViaPhpMail($email,$toName,$subject,$htmlBody);}
      if(!$result['ok']){$failed++;$errors[]=$result['message'];continue;}
      $newStatus='';if($tpl==='claim_submit')$newStatus='form_sent';elseif($tpl==='hibas_id')$newStatus='bad_id_sent';
      if($newStatus){$pdo->prepare("UPDATE wz_passengers SET mail_sent_at=NOW(),mail_template=?,status=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$newStatus,$pid]);
        $pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$pid,$newStatus]);
        if($tpl==='claim_submit'){
          $pdo->prepare("UPDATE wz_passengers SET remarketing_active=1,claim_mail_sent_at=NOW() WHERE id=? AND remarketing_active=0")->execute([$pid]);
          // Also activate holder if this is a sub-passenger
          if(!$pax['is_holder']){
            $pdo->prepare("UPDATE wz_passengers SET remarketing_active=1,claim_mail_sent_at=COALESCE(claim_mail_sent_at,NOW()) WHERE booking_id=? AND is_holder=1 AND remarketing_active=0")->execute([$pax['booking_id']]);
          }
        }
      }
      else{$pdo->prepare("UPDATE wz_passengers SET mail_sent_at=NOW(),mail_template=?,updated_at=NOW() WHERE id=?")->execute([$tpl,$pid]);}
      $ts2=$pdo->prepare("SELECT label FROM mail_templates WHERE slug=?");$ts2->execute([$tpl]);$tRow=$ts2->fetch();
      $pdo->prepare("INSERT INTO mail_history (customer_id,template_slug,template_label) VALUES (?,?,?)")->execute([$pid,$tRow?$tRow['label']:$tpl]);
      $sent++;
      if($sent%10===0)usleep(500000);
    }
    echo json_encode(['ok'=>true,'sent'=>$sent,'failed'=>$failed,'errors'=>array_slice($errors,0,5)]);exit;
  }
  // ===== WZ: BULK STATUS =====
  if($_GET['action']==='wz_bulk_status'){
    $in=json_decode(file_get_contents('php://input'),true);$ids=$in['ids']??[];$status=$in['status']??'';
    if(!is_array($ids)||!$status){echo json_encode(['ok'=>false]);exit;}
    $updated=0;
    foreach($ids as $id){$id=intval($id);if(!$id)continue;$pdo->prepare("UPDATE wz_passengers SET status=?,updated_at=NOW() WHERE id=?")->execute([$status,$id]);$pdo->prepare("INSERT INTO status_history (customer_id,status) VALUES (?,?)")->execute([$id,$status]);$updated++;}
    echo json_encode(['ok'=>true,'updated'=>$updated]);exit;
  }
  // ===== WZ: BULK DELETE =====
  if($_GET['action']==='wz_bulk_delete'){
    $in=json_decode(file_get_contents('php://input'),true);$ids=$in['ids']??[];
    if(!is_array($ids)){echo json_encode(['ok'=>false]);exit;}
    $deleted=0;
    foreach($ids as $id){$id=intval($id);if(!$id)continue;$pdo->prepare("DELETE FROM wz_passengers WHERE id=?")->execute([$id]);$deleted++;}
    echo json_encode(['ok'=>true,'deleted'=>$deleted]);exit;
  }
  // ===== WZ: ADD CUSTOMER =====
  if($_GET['action']==='wz_add_customer'){
    $in=json_decode(file_get_contents('php://input'),true);
    // Account fields
    $accNum=$in['account_number']??'';
    $holderName=$in['holder_name']??'';
    $holderDob=$in['holder_dob']??null;
    $nationality=$in['nationality']??'';
    $phone=$in['phone']??'';
    $address=$in['address']??'';
    $accEmail=$in['account_email']??'';
    $passportNr=$in['passport_number']??'';
    $passportCountry=$in['passport_issued_country']??'';
    $passportExpiry=$in['passport_expiry']??null;
    // Flight fields
    $pnr=$in['pnr']??'';
    $flNum=$in['flight_number']??'';$flDate=$in['flight_date']??'';
    $origin=$in['origin']??'';$dest=$in['destination']??'';
    $reason=$in['reason']??'';$distKm=$in['distance_km']??null;
    if($distKm!==null&&$distKm!=='')$distKm=intval($distKm);else $distKm=null;
    // Passengers array
    $passengers=$in['passengers']??[];
    if(empty($passengers)){echo json_encode(['ok'=>false,'message'=>'At least one passenger required']);exit;}
    $firstPax=$passengers[0];
    if(!trim($firstPax['first_name']??'')||!trim($firstPax['last_name']??'')){echo json_encode(['ok'=>false,'message'=>'First and last name required']);exit;}
    // Find or create account
    $accId=null;
    if($accNum){$chk=$pdo->prepare("SELECT id FROM wz_accounts WHERE account_number=?");$chk->execute([$accNum]);$r=$chk->fetch();if($r)$accId=$r['id'];}
    if(!$accId){
      if(!$accNum)$accNum='WZ-'.strtoupper(substr(md5(($firstPax['first_name']??'').time().rand()),0,8));
      if(!$holderName)$holderName=trim(($firstPax['first_name']??'').' '.($firstPax['last_name']??''));
      $pdo->prepare("INSERT INTO wz_accounts (account_number,holder_name,holder_dob,nationality,phone,address,email,passport_number,passport_issued_country,passport_expiry) VALUES (?,?,?,?,?,?,?,?,?,?)")
        ->execute([$accNum,$holderName,$holderDob?:null,$nationality,$phone,$address,$accEmail?:($firstPax['email']??''),$passportNr,$passportCountry,$passportExpiry?:null]);
      $accId=$pdo->lastInsertId();
    }
    // Find or create booking
    $bkId=null;
    if($pnr&&$flNum&&$flDate){
      $chk=$pdo->prepare("SELECT id FROM wz_bookings WHERE account_id=? AND pnr=? AND flight_number=? AND flight_date=?");
      $chk->execute([$accId,$pnr,$flNum,$flDate]);$r=$chk->fetch();if($r)$bkId=$r['id'];
    }
    if(!$bkId){
      if(!$pnr)$pnr=strtoupper(substr(md5(time().rand()),0,6));
      $originIata='';$destIata='';
      if(preg_match('/\(([A-Z]{3})\)/',$origin,$m))$originIata=$m[1];
      if(preg_match('/\(([A-Z]{3})\)/',$dest,$m))$destIata=$m[1];
      $pdo->prepare("INSERT INTO wz_bookings (account_id,pnr,flight_number,flight_date,origin,origin_iata,destination,destination_iata,flight_status,reason,distance_km) VALUES (?,?,?,?,?,?,?,?,?,?,?)")
        ->execute([$accId,$pnr,$flNum?:'',$flDate?:null,$origin,$originIata,$dest,$destIata,'scheduled',$reason,$distKm]);
      $bkId=$pdo->lastInsertId();
    }
    // Create passengers
    $createdIds=[];
    foreach($passengers as $i=>$p){
      $pfn=trim($p['first_name']??'');$pln=trim($p['last_name']??'');
      if(!$pfn&&!$pln)continue;
      $pem=trim($p['email']??'');$pseat=trim($p['seat']??'');
      $isH=($i===0)?1:0;
      $pdo->prepare("INSERT INTO wz_passengers (booking_id,account_id,passenger_name,first_name,last_name,email,seat,is_holder,status) VALUES (?,?,?,?,?,?,?,?,?)")
        ->execute([$bkId,$accId,$pfn.' '.$pln,$pfn,$pln,$pem,$pseat,$isH,'doc_needed']);
      $createdIds[]=(int)$pdo->lastInsertId();
    }
    echo json_encode(['ok'=>true,'ids'=>$createdIds,'account_id'=>(int)$accId,'booking_id'=>(int)$bkId]);exit;
  }
  // ===== WZ: GENERATE ASSIGNMENT =====
  if($_GET['action']==='wz_generate_assignment'){
    $in=json_decode(file_get_contents('php://input'),true);$pid=$in['id']??0;
    if(!$pid){echo json_encode(['ok'=>false]);exit;}
    // Get passenger + account data
    $ps=$pdo->prepare("SELECT p.*,b.pnr,b.flight_number,b.flight_date,b.origin,b.destination,b.distance_km AS bk_distance_km,a.account_number,a.holder_name,a.address AS acc_address FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id JOIN wz_accounts a ON p.account_id=a.id WHERE p.id=?");
    $ps->execute([$pid]);$pax=$ps->fetch();
    if(!$pax){echo json_encode(['ok'=>false,'message'=>'Passenger not found']);exit;}
    // Build fake customer for generate_assignment.php compatibility
    $addr=$pax['acc_address']??'';
    $parts=preg_split('/[,\n]/',$addr);
    $street=trim($parts[0]??'');$city=trim($parts[1]??'');$postal=trim($parts[2]??'');$country=trim($parts[3]??'');
    // Create temp row in customers table, generate, then delete
    $custId='WZ-'.strtoupper(substr(md5($pid.time()),0,8));
    $pdo->prepare("INSERT INTO customers (customer_id,booking_ref,flight_number,flight_date,departure,arrival,first_name,last_name,email,airline,distance_km,is_main,address_street,address_city,address_postal,address_country,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,1,?,?,?,?,'doc_needed')")
      ->execute([$custId,$pax['pnr'],$pax['flight_number'],$pax['flight_date'],$pax['origin'],$pax['destination'],$pax['first_name']?:$pax['passenger_name'],$pax['last_name']??'',$pax['email']??'','Wizz Air',$pax['bk_distance_km'],$street,$city,$postal,$country]);
    $tempId=$pdo->lastInsertId();
    require_once __DIR__.'/generate_assignment.php';
    $templatePath=__DIR__.'/assignment_template.docx';
    $uploadDir=__DIR__.'/uploads/';
    $result=false;
    if(file_exists($templatePath)){$result=generateAssignment($pdo,$tempId,$uploadDir,$templatePath);}
    if($result){
      $st=$pdo->prepare("SELECT assignment_filename,assignment_path FROM customers WHERE id=?");$st->execute([$tempId]);$r=$st->fetch();
      // Copy assignment to wz_passenger
      $pdo->prepare("UPDATE wz_passengers SET assignment_filename=?,assignment_path=?,updated_at=NOW() WHERE id=?")->execute([$r['assignment_filename'],$r['assignment_path'],$pid]);
      // Clean up temp customer
      $pdo->prepare("DELETE FROM customers WHERE id=?")->execute([$tempId]);
      echo json_encode(['ok'=>true,'filename'=>$r['assignment_filename'],'path'=>$r['assignment_path']]);
    }else{
      $pdo->prepare("DELETE FROM customers WHERE id=?")->execute([$tempId]);
      echo json_encode(['ok'=>false,'message'=>'Generation failed — check address data']);
    }
    exit;
  }
  // ===== WZ: PREVIEW TEMPLATE =====
  if($_GET['action']==='wz_preview_template'){
    $in=json_decode(file_get_contents('php://input'),true);$pid=$in['id']??0;$tpl=$in['template']??'';
    if(!$pid||!$tpl){echo json_encode(['ok'=>false,'message'=>'Missing id or template']);exit;}
    $ps=$pdo->prepare("SELECT p.*,b.pnr,b.flight_number,b.flight_date,b.origin,b.origin_iata,b.destination,b.destination_iata,b.distance_km AS bk_distance_km,b.reason AS bk_reason,a.email AS acc_email FROM wz_passengers p JOIN wz_bookings b ON p.booking_id=b.id JOIN wz_accounts a ON p.account_id=a.id WHERE p.id=?");
    $ps->execute([$pid]);$pax=$ps->fetch();
    if(!$pax){echo json_encode(['ok'=>false,'message'=>'Passenger not found']);exit;}
    $email=$pax['email']?:$pax['acc_email'];
    $fakeCustomer=['id'=>$pid,'first_name'=>$pax['first_name']?:$pax['passenger_name'],'last_name'=>$pax['last_name']??'','email'=>$email,'booking_ref'=>$pax['pnr'],'flight_number'=>$pax['flight_number'],'flight_date'=>$pax['flight_date'],'departure'=>$pax['origin'],'arrival'=>$pax['destination'],'airline'=>'Wizz Air','distance_km'=>$pax['bk_distance_km'],'reason'=>$pax['bk_reason'],'address_street'=>'','address_city'=>'','address_postal'=>'','address_country'=>'','customer_id'=>'WZ-'.$pid,'is_main'=>$pax['is_holder']];
    $allPaxStmt=$pdo->prepare("SELECT first_name,last_name,passenger_name FROM wz_passengers WHERE booking_id=? ORDER BY is_holder DESC");
    $allPaxStmt->execute([$pax['booking_id']]);$allPax=array_map(function($p){return['first_name'=>$p['first_name']?:explode(' ',$p['passenger_name'])[0]??'','last_name'=>$p['last_name']?:implode(' ',array_slice(explode(' ',$p['passenger_name']),1))];},$allPaxStmt->fetchAll());
    require_once __DIR__.'/mailer.php';
    $claimLink=buildWzClaimLink($fakeCustomer,$allPax);
    if($tpl==='claim_submit'){
      $routeStr=($pax['origin_iata']&&$pax['destination_iata'])?' '.$pax['origin_iata'].'-'.$pax['destination_iata']:'';
      $subject="Claim up to €600 for your Wizz Air flight{$routeStr}";
      $html=buildWzNotificationEmail($fakeCustomer,$claimLink,$allPax,true);
      echo json_encode(['ok'=>true,'subject'=>$subject,'body'=>'[HTML email]','is_html'=>true,'html'=>$html,'email'=>$email,'name'=>trim(($pax['first_name']?:'').' '.($pax['last_name']?:''))]);
    }else{
      $ts=$pdo->prepare("SELECT * FROM mail_templates WHERE slug=?");$ts->execute([$tpl]);$t=$ts->fetch();
      if(!$t){echo json_encode(['ok'=>false,'message'=>'Template not found']);exit;}
      $subject=replacePlaceholders($t['subject'],$fakeCustomer,$claimLink,$allPax);
      $body=replacePlaceholders($t['body'],$fakeCustomer,$claimLink,$allPax);
      echo json_encode(['ok'=>true,'subject'=>$subject,'body'=>$body,'is_html'=>false,'html'=>'','email'=>$email,'name'=>trim(($pax['first_name']?:'').' '.($pax['last_name']?:''))]);
    }
    exit;
  }
  // ===== WZ: UPLOAD ASSIGNMENT =====
  if($_GET['action']==='wz_upload_assignment'){
    $id=$_POST['id']??0;
    if($id&&isset($_FILES['file'])&&$_FILES['file']['error']===UPLOAD_ERR_OK){
      $f=$_FILES['file'];$ud=__DIR__.'/uploads/';if(!is_dir($ud))mkdir($ud,0755,true);
      $ext=pathinfo($f['name'],PATHINFO_EXTENSION);$sn="wz_{$id}_assignment_".time().".{$ext}";
      if(move_uploaded_file($f['tmp_name'],$ud.$sn)){
        $pdo->prepare("UPDATE wz_passengers SET assignment_filename=?,assignment_path=?,updated_at=NOW() WHERE id=?")->execute([$f['name'],$sn,$id]);
        echo json_encode(['ok'=>true,'filename'=>$f['name'],'path'=>$sn]);
      }else echo json_encode(['ok'=>false]);
    }else echo json_encode(['ok'=>false]);exit;
  }
  if($_GET['action']==='wz_delete_assignment'){
    $in=json_decode(file_get_contents('php://input'),true);$id=$in['id']??0;
    if($id){$pdo->prepare("UPDATE wz_passengers SET assignment_filename=NULL,assignment_path=NULL,updated_at=NOW() WHERE id=?")->execute([$id]);echo json_encode(['ok'=>true]);}exit;
  }
}

// easyJet flight number aliases: U21455 = EZY1455 = EZS1455 = EJU1455
function easyjetAliases($fn){
  $fn=strtoupper(preg_replace('/\s+/','',$fn));
  $prefixes=['U2','EZY','EZS','EJU'];
  $num='';
  foreach($prefixes as $p){
    if(str_starts_with($fn,$p)){$num=substr($fn,strlen($p));break;}
  }
  if(!$num)return[$fn]; // not easyJet
  $aliases=[];
  foreach($prefixes as $p)$aliases[]=$p.$num;
  return $aliases;
}

function autoFillCustomersFromFlights($pdo){
  // Direct match — always overwrite with flight data
  $pdo->exec("UPDATE customers c INNER JOIN flight_data f ON UPPER(c.flight_number)=f.flight_number AND c.flight_date=f.flight_date SET c.reason=IF(f.reason IS NOT NULL AND f.reason!='',f.reason,c.reason), c.distance_km=IF(f.distance_km IS NOT NULL,f.distance_km,c.distance_km)");
  // easyJet alias match
  $flights=$pdo->query("SELECT * FROM flight_data WHERE flight_aliases!='' AND flight_aliases IS NOT NULL")->fetchAll();
  foreach($flights as $f){
    $aliases=array_map('trim',explode(',',$f['flight_aliases']));
    foreach($aliases as $alias){
      if($alias===$f['flight_number'])continue;
      $sets=[];$params=[];
      if($f['reason']){$sets[]="c.reason=?";$params[]=$f['reason'];}
      if($f['distance_km']){$sets[]="c.distance_km=?";$params[]=$f['distance_km'];}
      if(!empty($sets)){
        $params[]=$alias;$params[]=$f['flight_date'];
        $pdo->prepare("UPDATE customers c SET ".implode(',',$sets)." WHERE UPPER(c.flight_number)=? AND c.flight_date=?")->execute($params);
      }
    }
  }
}

$stmt=$pdo->query("SELECT * FROM customers ORDER BY airline,booking_ref,is_main DESC,id ASC");
$allRows=$stmt->fetchAll();$dataJson=json_encode($allRows,JSON_UNESCAPED_UNICODE);
$tplRows=$pdo->query("SELECT * FROM mail_templates ORDER BY id")->fetchAll();$tplJson=json_encode($tplRows,JSON_UNESCAPED_UNICODE);
$flRows=$pdo->query("SELECT * FROM flight_data ORDER BY flight_date DESC, flight_number ASC")->fetchAll();$flJson=json_encode($flRows,JSON_UNESCAPED_UNICODE);
$futureRows=$pdo->query("SELECT * FROM future_flights ORDER BY flight_date ASC, flight_number ASC")->fetchAll();$futureJson=json_encode($futureRows,JSON_UNESCAPED_UNICODE);

// Wizz Air data
$wzAccounts=$pdo->query("SELECT * FROM wz_accounts ORDER BY holder_name ASC")->fetchAll();$wzAccountsJson=json_encode($wzAccounts,JSON_UNESCAPED_UNICODE);
$wzBookings=$pdo->query("SELECT * FROM wz_bookings ORDER BY flight_date DESC")->fetchAll();$wzBookingsJson=json_encode($wzBookings,JSON_UNESCAPED_UNICODE);
$wzPassengers=$pdo->query("SELECT * FROM wz_passengers ORDER BY is_holder DESC, passenger_name ASC")->fetchAll();$wzPassengersJson=json_encode($wzPassengers,JSON_UNESCAPED_UNICODE);
// Flat view for WZ table (join passengers + bookings + accounts)
$wzFlat=$pdo->query("
  SELECT p.*, 
    b.pnr, b.flight_number, b.flight_date, b.origin, b.origin_iata, b.destination, b.destination_iata, 
    b.flight_status, b.flight_category, b.distance_km AS bk_distance_km, b.cost, b.reason AS bk_reason,
    a.account_number, a.holder_name, a.holder_dob, 
    a.nationality AS acc_nationality, a.phone AS acc_phone, a.address AS acc_address,
    a.passport_number AS acc_passport_number, a.passport_issued_country AS acc_passport_issued_country, 
    a.passport_expiry AS acc_passport_expiry, a.email AS acc_email
  FROM wz_passengers p
  JOIN wz_bookings b ON p.booking_id=b.id
  JOIN wz_accounts a ON p.account_id=a.id
  ORDER BY a.account_number, b.pnr, p.is_holder DESC, p.id ASC
")->fetchAll();$wzFlatJson=json_encode($wzFlat,JSON_UNESCAPED_UNICODE);

?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>SkyClaim — Dashboard</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root{--orange:#FF6B35;--orange-light:#FFF0EB;--navy:#1B2A4A;--white:#FFF;--g50:#F8F9FB;--g100:#F0F2F5;--g200:#E2E5EA;--g300:#C8CDD5;--g400:#9BA3B0;--g500:#6B7280;--g700:#3D4552;--green:#22C55E;--green-light:#ECFDF5;--blue:#3B82F6;--blue-light:#EFF6FF;--yellow:#F59E0B;--yellow-light:#FFFBEB;--red:#EF4444;--red-light:#FEF2F2;--purple:#8B5CF6;--purple-light:#F5F3FF;--r:12px;--rl:16px}
*{margin:0;padding:0;box-sizing:border-box}body{font-family:'DM Sans',sans-serif;background:var(--g50);color:var(--navy);min-height:100vh}h1,h2,h3,h4,h5{font-family:'Plus Jakarta Sans',sans-serif}
.header{background:var(--white);border-bottom:1px solid var(--g200);padding:0 32px;height:64px;display:flex;align-items:center;justify-content:space-between}.header-left{display:flex;align-items:center;gap:20px}.logo{font-family:'Plus Jakarta Sans',sans-serif;font-weight:800;font-size:22px;color:var(--navy);letter-spacing:-.5px}.logo span{color:var(--orange)}
.nav-tabs{display:flex;gap:4px}.nav-tab{padding:8px 16px;border-radius:8px;font-size:13px;font-weight:600;color:var(--g500);cursor:pointer;border:none;background:none;font-family:'DM Sans',sans-serif;transition:all .15s}.nav-tab:hover{background:var(--g100)}.nav-tab.active{background:var(--orange-light);color:var(--orange)}
.main{margin:0;padding:24px 20px 80px}
.page{display:none}.page.active{display:block}
/* Airline selector */
.airline-sel{margin-bottom:16px}.as-wrap{position:relative;display:flex;align-items:center;gap:10px;background:var(--white);border:1.5px solid var(--g200);border-radius:12px;padding:0 16px;height:44px;max-width:360px;transition:all .2s}.as-wrap:focus-within{border-color:var(--orange);box-shadow:0 0 0 4px rgba(255,107,53,.1)}.as-wrap svg{color:var(--g400)}.as-wrap input{border:none;background:none;font-size:14px;font-family:'DM Sans',sans-serif;font-weight:500;color:var(--navy);outline:none;width:100%}.as-wrap input::placeholder{color:var(--g400)}.as-dd{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--white);border:1.5px solid var(--g200);border-radius:12px;box-shadow:0 12px 32px rgba(27,42,74,.15);display:none;z-index:50;overflow:hidden;max-height:260px;overflow-y:auto}.as-dd.show{display:block}.as-item{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;transition:background .12s;border-bottom:1px solid var(--g100);font-size:13px;font-weight:600;color:var(--navy)}.as-item:last-child{border:none}.as-item:hover{background:var(--orange-light)}.as-item.act{color:var(--orange)}.as-item .cnt{margin-left:auto;font-size:11px;font-weight:700;color:var(--g400);background:var(--g100);padding:2px 8px;border-radius:100px}.as-logo{width:20px;height:20px;border-radius:4px;object-fit:contain}
/* Stats */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:12px}.stats.s6{grid-template-columns:repeat(6,1fr)}.sc{background:var(--white);border:1px solid var(--g200);border-radius:var(--r);padding:16px;display:flex;align-items:center;gap:14px}.si{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.si.or{background:var(--orange-light);color:var(--orange)}.si.gr{background:var(--green-light);color:var(--green)}.si.bl{background:var(--blue-light);color:var(--blue)}.si.pu{background:var(--purple-light);color:var(--purple)}.sv{font-family:'Plus Jakarta Sans',sans-serif;font-size:22px;font-weight:800;color:var(--navy)}.sl{font-size:11px;color:var(--g400);margin-top:1px}
/* Table */
.tc{background:var(--white);border:1px solid var(--g200);border-radius:var(--rl);overflow:hidden}.th{padding:16px 20px;border-bottom:1px solid var(--g100);display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.th-l{display:flex;align-items:center;gap:10px}.th-logo{width:24px;height:24px;border-radius:6px;object-fit:contain;border:1px solid var(--g200)}.th h3{font-size:15px;font-weight:700}.th .cnt{background:var(--g100);color:var(--g500);font-size:11px;font-weight:700;padding:3px 8px;border-radius:100px}.th-r{display:flex;align-items:center;gap:8px}
.sb{display:flex;align-items:center;gap:6px;background:var(--g50);border:1.5px solid var(--g200);border-radius:8px;padding:0 10px;height:34px;position:relative}.sb:focus-within{border-color:var(--orange)}.sb svg{color:var(--g400)}.sb input{border:none;background:none;font-size:12px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;width:160px}.sb-x{color:var(--g400);cursor:pointer;font-size:14px;padding:0 2px;line-height:1}.sb-x:hover{color:var(--navy)}
.fb{height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);background:var(--white);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--g500);cursor:pointer;display:flex;align-items:center;gap:5px}.fb:hover{background:var(--g50)}.fb.act{border-color:var(--orange);color:var(--orange);background:var(--orange-light)}
.sfw{position:relative}.sfd{position:absolute;top:calc(100% + 4px);right:0;width:230px;background:var(--white);border:1.5px solid var(--g200);border-radius:12px;box-shadow:0 12px 32px rgba(27,42,74,.15);display:none;z-index:50;overflow:hidden}.sfd.show{display:block}.sfi{display:flex;align-items:center;gap:8px;padding:10px 14px;cursor:pointer;font-size:12px;font-weight:600;color:var(--g700);border-bottom:1px solid var(--g100)}.sfi:last-child{border:none}.sfi:hover{background:var(--g50)}.sfi.act{color:var(--orange)}.sfd .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
th.srt{cursor:pointer;user-select:none;white-space:nowrap}th.srt:hover{color:var(--orange)}th.srt::after{content:'';display:inline-block;margin-left:3px;font-size:9px;color:var(--g400)}th.srt.asc::after{content:'▲'}th.srt.desc::after{content:'▼'}
.tw{overflow-x:auto}table{width:100%;border-collapse:collapse;font-size:11px;table-layout:auto}thead th{text-align:left;padding:8px 6px;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--g400);background:var(--g50);border-bottom:1px solid var(--g200);white-space:nowrap}tbody tr{border-bottom:1px solid var(--g100)}tbody tr:hover{background:var(--g50)}td{padding:7px 6px;color:var(--g700);white-space:nowrap}
td.nm{font-weight:600;color:var(--navy)}td.bk{font-family:'Plus Jakarta Sans',sans-serif;font-weight:700;color:var(--orange);font-size:12px}td.cid{white-space:nowrap}.cid-t{font-family:'Plus Jakarta Sans',sans-serif;font-weight:800;font-size:11px;color:var(--navy);background:rgba(27,42,74,.06);padding:2px 6px;border-radius:5px;letter-spacing:.4px}td.fl{font-weight:600}td.dt{color:var(--g500);font-size:11px}td.dst{font-size:12px;font-weight:600}
.comp{display:inline-block;padding:3px 8px;border-radius:5px;font-size:12px;font-weight:800;font-family:'Plus Jakarta Sans',sans-serif;background:var(--blue-light);color:var(--blue)}
.rtag{display:inline-block;padding:2px 6px;border-radius:5px;font-size:10px;font-weight:600}.rtag.del{background:var(--yellow-light);color:var(--yellow)}.rtag.can{background:var(--red-light);color:var(--red)}.rtag.ovb{background:var(--purple-light);color:var(--purple)}
/* Status */
select.stb{padding:4px 8px;border-radius:100px;font-size:10px;font-weight:700;border:1.5px solid;cursor:pointer;font-family:'DM Sans',sans-serif}
.st-doc_needed{background:var(--orange-light);color:var(--orange);border-color:rgba(255,107,53,.3)}
.st-form_sent{background:var(--g100);color:var(--g500);border-color:var(--g200)}
.st-bad_id_sent{background:var(--red-light);color:var(--red);border-color:rgba(239,68,68,.3)}
.st-form_send{background:var(--orange-light);color:var(--orange);border-color:rgba(255,107,53,.3)}
.st-beadva{background:var(--green-light);color:var(--green);border-color:rgba(34,197,94,.3)}
.st-beadva_sajat{background:#FFFBEB;color:#D97706;border-color:rgba(217,119,6,.3)}
.st-beadva_assign{background:#EFF6FF;color:#3B82F6;border-color:rgba(59,130,246,.3)}
.st-beadva_airhelp{background:#F5F3FF;color:#8B5CF6;border-color:rgba(139,92,246,.3)}
.st-jovahagyva{background:#ECFDF5;color:#059669;border-color:rgba(5,150,105,.3)}
.st-kifizetve{background:#EFF6FF;color:#2563EB;border-color:rgba(37,99,235,.3)}
.st-elutasitva{background:#FEF2F2;color:#DC2626;border-color:rgba(220,38,38,.3)}
/* Doc cells */
.dc{display:flex;align-items:center;gap:4px}.dib{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:7px;border:none;cursor:pointer;background:transparent;padding:0;text-decoration:none}.dib.uv{color:var(--orange)}.dib.uv:hover{color:var(--orange);background:var(--orange-light)}.dib.vw{color:var(--green)}.dib.vw:hover{background:var(--green-light)}.ddb{width:20px;height:20px;border-radius:5px;border:none;background:var(--red-light);color:var(--red);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}.ddb:hover{background:var(--red);color:var(--white)}.dub{display:inline-flex;align-items:center;gap:3px;padding:3px 8px;border-radius:7px;font-size:10px;font-weight:600;background:var(--blue-light);color:var(--blue);border:1.5px dashed rgba(59,130,246,.4);cursor:pointer;white-space:nowrap;position:relative;overflow:hidden}.dub:hover{background:var(--blue);color:var(--white)}.dub input[type="file"]{position:absolute;inset:0;opacity:0;cursor:pointer}
.gen-btn{display:inline-flex;align-items:center;gap:3px;padding:3px 8px;border-radius:7px;font-size:9px;font-weight:600;background:var(--blue-light);color:var(--blue);border:1.5px solid rgba(59,130,246,.3);cursor:pointer;white-space:nowrap;transition:all .15s}.gen-btn:hover{background:var(--blue);color:var(--white)}
.prvw-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:7px;font-size:10px;font-weight:700;border:none;cursor:pointer;white-space:nowrap;background:var(--orange-light);color:var(--orange)}.prvw-btn:hover{background:var(--orange);color:var(--white)}
/* Mail */
.mail-sel{font-size:10px;padding:3px 6px;border-radius:6px;border:1px solid var(--g200);font-family:'DM Sans',sans-serif;color:var(--g700);cursor:pointer;background:var(--white);max-width:120px}
.mb{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:7px;font-size:10px;font-weight:700;border:none;cursor:pointer;white-space:nowrap}
.mb.rdy{background:var(--blue-light);color:var(--blue)}.mb.rdy:hover{background:var(--blue);color:var(--white)}
.mb.snt{background:var(--g100);color:var(--g500);cursor:default;position:relative}
.mb.snt .mi{display:none;position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);background:var(--navy);color:var(--white);font-size:10px;padding:5px 10px;border-radius:7px;white-space:nowrap;box-shadow:0 4px 12px rgba(27,42,74,.2);z-index:10}
.mb.snt .mi::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:4px solid transparent;border-top-color:var(--navy)}
.mb.snt:hover .mi{display:block}
/* Address */
td.addr{font-size:11px;color:var(--g500);max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle}
/* Row types */
tbody tr.mr{border-bottom-color:transparent;background:#FFFFFF;border-top:2px solid var(--g200)}tbody tr.mr td{padding-top:14px;padding-bottom:10px}tbody tr.mr td.nm{font-size:13px;font-weight:800}tbody tr.mr td.bk{font-size:13px;font-weight:800}.mbdg{font-size:8px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--orange);background:var(--orange-light);padding:1px 5px;border-radius:3px;margin-left:4px;vertical-align:middle}
tbody tr.sr{background:#F0F2F5}tbody tr.sr td{padding-top:7px;padding-bottom:7px;font-size:11px}tbody tr.sr td.nm{padding-left:28px;font-size:12px;font-weight:600;color:var(--g700)}.sc-c{color:var(--orange);font-size:12px;margin-right:3px;opacity:.5}
tbody tr.gl{border-bottom:2px solid var(--g200)}tbody tr.solo{border-top:2px solid var(--g200);border-bottom:2px solid var(--g200)}
.lnk-b{display:inline-block;padding:3px 8px;border-radius:5px;font-size:10px;font-weight:700;background:var(--orange-light);color:var(--orange);text-decoration:none}.lnk-b:hover{background:var(--orange);color:var(--white)}.lnk-c{border:none;background:none;cursor:pointer;font-size:12px;padding:1px 3px;border-radius:3px}.lnk-c:hover{background:var(--g100)}
.cp{cursor:pointer;border-radius:3px;padding:1px 3px;margin:-1px -3px;transition:background .12s}.cp:hover{background:var(--orange-light)}
.st-wrap{position:relative;display:inline-block}
.hist-tip{display:none}
/* Floating tooltip appended to body */
.float-tip{position:fixed;background:var(--white);color:var(--navy);font-size:11px;padding:16px 18px;border-radius:14px;white-space:normal;box-shadow:0 8px 30px rgba(27,42,74,.18);border:1px solid var(--g200);z-index:9999;min-width:440px;max-width:520px;max-height:360px;overflow-y:auto}
.ni{position:relative;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:6px;cursor:pointer;color:var(--g300);transition:all .15s}.ni.has{color:var(--blue);background:var(--blue-light)}.ni:hover{color:var(--navy);background:var(--g100)}.ni.has:hover{color:var(--blue);background:rgba(59,130,246,.15)}
.ni-tip{display:none;position:fixed;background:var(--navy);color:var(--white);font-size:12px;padding:10px 14px;border-radius:10px;white-space:pre-wrap;max-width:320px;min-width:100px;box-shadow:0 8px 28px rgba(27,42,74,.3);z-index:99999;line-height:1.6;word-break:break-word;text-align:left;font-weight:400;pointer-events:none}.ni-tip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:var(--navy)}
.float-tip .ft-cols{display:flex;gap:16px}
.float-tip .ft-col{flex:1;min-width:0}
.float-tip .ht-row{display:flex;align-items:flex-start;gap:8px;padding:6px 0;border-bottom:1px solid var(--g100)}
.float-tip .ht-row:last-child{border:none}
.ht-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;margin-top:3px}
.ht-dot.mail{background:var(--blue)}.ht-dot.status{background:var(--orange)}
.ht-info{flex:1;min-width:0}
.ht-val{font-weight:700;font-size:11px;color:var(--navy);display:block}
.ht-date{font-size:10px;color:var(--g400);display:block;margin-top:1px}
.ht-title{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.6px;color:var(--g400);margin-bottom:6px;padding-bottom:6px;border-bottom:1.5px solid var(--g100);display:flex;align-items:center;gap:6px}
.ht-title svg{flex-shrink:0}
.ht-empty{color:var(--g400);font-style:italic;font-size:11px;padding:4px 0}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--navy);color:var(--white);font-size:12px;font-weight:600;padding:8px 16px;border-radius:8px;box-shadow:0 8px 24px rgba(27,42,74,.25);display:flex;align-items:center;gap:6px;opacity:0;pointer-events:none;transition:all .3s;z-index:999}.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.tf{padding:12px 20px;border-top:1px solid var(--g100);font-size:12px;color:var(--g400)}
/* Templates page */
.tpl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px}
.tpl-card{background:var(--white);border:1px solid var(--g200);border-radius:14px;padding:20px;display:flex;flex-direction:column}.tpl-card h4{font-size:15px;font-weight:700;margin-bottom:2px;color:var(--navy)}.tpl-card .slug{font-size:10px;color:var(--g400);margin-bottom:12px;font-family:monospace}.tpl-card label{font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:4px}.tpl-card input,.tpl-card textarea{width:100%;border:1.5px solid var(--g200);border-radius:8px;padding:8px 12px;font-size:12px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;margin-bottom:10px}.tpl-card textarea{height:140px;resize:vertical;line-height:1.5}.tpl-card input:focus,.tpl-card textarea:focus{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,107,53,.08)}
.tpl-actions{display:flex;gap:8px;margin-top:auto;padding-top:8px}
.tpl-save{padding:7px 16px;border-radius:8px;border:none;background:var(--orange);color:var(--white);font-size:12px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;flex:1}.tpl-save:hover{background:#E55A2B}
.tpl-copy{padding:7px 16px;border-radius:8px;border:1.5px solid var(--g200);background:var(--white);color:var(--g500);font-size:12px;font-weight:600;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;justify-content:center;gap:4px}.tpl-copy:hover{background:var(--g50);border-color:var(--g300)}
.tpl-hint{font-size:11px;color:var(--g400);margin-bottom:14px}
/* Charts */
.chart-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px}
.chart-card{background:var(--white);border:1px solid var(--g200);border-radius:14px;padding:20px;overflow:hidden}
.chart-card h4{font-size:14px;font-weight:700;color:var(--navy);margin-bottom:12px}
.chart-wrap{position:relative;height:280px;width:100%}
@media(max-width:900px){.chart-grid{grid-template-columns:1fr}}
/* Template preview modal */
.tpl-preview{background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;font-size:12px;line-height:1.7;color:var(--navy);white-space:pre-wrap;max-height:400px;overflow-y:auto;font-family:'DM Sans',sans-serif}
@media(max-width:768px){.stats{grid-template-columns:repeat(2,1fr)}.stats.s6{grid-template-columns:repeat(3,1fr)}.main{padding:16px 16px 60px}}
/* Edit button */
.edit-btn{width:28px;height:28px;border-radius:7px;border:1.5px solid var(--g200);background:var(--white);color:var(--g400);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;transition:all .15s}.edit-btn:hover{border-color:var(--orange);color:var(--orange);background:var(--orange-light)}
/* Edit modal */
.em-overlay{position:fixed;inset:0;background:rgba(27,42,74,.4);backdrop-filter:blur(4px);display:none;align-items:center;justify-content:center;z-index:1000;padding:24px}.em-overlay.show{display:flex}
.em-box{background:var(--white);border-radius:16px;box-shadow:0 20px 60px rgba(27,42,74,.2);width:100%;max-width:600px;max-height:90vh;overflow-y:auto;animation:emIn .25s ease}
@keyframes emIn{from{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:none}}
@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
.em-head{padding:20px 24px;border-bottom:1px solid var(--g100);display:flex;align-items:center;justify-content:space-between}.em-head h3{font-size:17px;font-weight:800;color:var(--navy)}.em-close{width:32px;height:32px;border-radius:8px;border:none;background:var(--g100);color:var(--g500);cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center}.em-close:hover{background:var(--g200)}
.em-body{padding:24px}
.em-section{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:var(--g400);margin-bottom:10px;margin-top:16px;padding-bottom:6px;border-bottom:1px solid var(--g100)}.em-section:first-child{margin-top:0}
.em-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.em-grid .full{grid-column:1/-1}
.em-fg{display:flex;flex-direction:column;gap:4px}.em-fg label{font-size:11px;font-weight:600;color:var(--g500)}.em-fg input{height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none}.em-fg input:focus{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,107,53,.1)}
.em-foot{padding:16px 24px;border-top:1px solid var(--g100);display:flex;gap:10px;justify-content:flex-end}
.em-save{padding:10px 24px;border-radius:10px;border:none;background:var(--orange);color:var(--white);font-size:14px;font-weight:700;font-family:'Plus Jakarta Sans',sans-serif;cursor:pointer}.em-save:hover{background:#E55A2B}
.em-cancel{padding:10px 24px;border-radius:10px;border:1.5px solid var(--g200);background:var(--white);color:var(--g500);font-size:14px;font-weight:600;font-family:'DM Sans',sans-serif;cursor:pointer}.em-cancel:hover{background:var(--g50)}
/* Checkbox */
.row-cb{width:16px;height:16px;accent-color:var(--orange);cursor:pointer;flex-shrink:0}
/* Bulk action bar */
.bulk-bar{display:none;padding:12px 20px;background:var(--orange-light);border-bottom:1px solid rgba(255,107,53,.2);align-items:center;gap:12px;flex-wrap:wrap}.bulk-bar.show{display:flex}.bulk-bar .bb-count{font-size:13px;font-weight:700;color:var(--orange)}.bulk-bar .bb-btn{padding:6px 16px;border-radius:8px;border:none;font-size:12px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:5px}.bb-send{background:var(--orange);color:var(--white)}.bb-send:hover{background:#E55A2B}
.bb-tpl{background:var(--yellow);color:var(--white)}.bb-tpl:hover{background:#D97706}
.bb-status{background:var(--blue);color:var(--white)}.bb-status:hover{background:#2563EB}
.bb-gen{background:var(--purple);color:var(--white)}.bb-gen:hover{background:#7C3AED}
.bb-del{background:var(--red);color:var(--white)}.bb-del:hover{background:#DC2626}
.bb-export{background:#059669;color:var(--white)}.bb-export:hover{background:#047857}
.bb-clear{background:var(--white);color:var(--g500);border:1px solid var(--g200)}.bb-clear:hover{background:var(--g50)}
/* Pagination */
.pag{display:flex;align-items:center;justify-content:center;gap:4px;padding:12px 0}.pag-btn{width:32px;height:32px;border-radius:8px;border:1px solid var(--g200);background:var(--white);color:var(--g500);font-size:12px;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;font-family:'DM Sans',sans-serif}.pag-btn:hover{background:var(--g50);border-color:var(--g300)}.pag-btn.act{background:var(--orange);color:var(--white);border-color:var(--orange)}.pag-btn:disabled{opacity:.3;cursor:default}.pag-info{font-size:12px;color:var(--g400);margin:0 8px}
</style>
</head>
<body>
<header class="header">
  <div class="header-left">
    <div class="logo">Sky<span>Claim</span></div>
    <div class="nav-tabs">
      <button class="nav-tab active" onclick="showPage('customers')">Customers</button>
      <button class="nav-tab" onclick="showPage('future')">Future</button>
      <button class="nav-tab" onclick="showPage('remarketing')">Remarketing</button>
      <button class="nav-tab" onclick="showPage('templates')">Mail Sablonok</button>
      <button class="nav-tab" onclick="showPage('stats')">Statistics</button>
      <button class="nav-tab" onclick="showPage('flights')">Flights</button>
      <button class="nav-tab" onclick="showPage('not_eligible')">Not Eligible</button>
      <div style="margin-left:auto;display:flex;gap:4px;align-items:center">
        <label class="nav-tab" style="cursor:pointer;display:flex;align-items:center;gap:5px;position:relative;overflow:hidden"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>easyJet Import CSV<input type="file" accept=".csv" onchange="importCSV(this)" style="position:absolute;inset:0;opacity:0;cursor:pointer"></label>
        <label class="nav-tab" style="cursor:pointer;display:flex;align-items:center;gap:5px;position:relative;overflow:hidden"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>WizzAir Import CSV<input type="file" accept=".csv" onchange="importWzCSV(this)" style="position:absolute;inset:0;opacity:0;cursor:pointer"></label>
        <a href="login.php?logout=1" style="padding:6px 14px;border-radius:8px;font-size:12px;font-weight:600;color:var(--g400);text-decoration:none;border:1px solid var(--g200);display:flex;align-items:center;gap:5px;font-family:'DM Sans',sans-serif"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>Logout</a>
      </div>
    </div>
  </div>
</header>
<div class="main">

<!-- ===== CUSTOMERS PAGE ===== -->
<div class="page active" id="page_customers">
  <div class="airline-sel"><div class="as-wrap" id="asW"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.8 19.2L16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.4-.1.9.3 1.1L11 12l-2 3H6l-1 1 3 2 2 3 1-1v-3l3-2 3.5 7.3c.3.4.7.5 1.1.3l.5-.3c.4-.2.6-.7.5-1.1z"/></svg><input type="text" id="asIn" placeholder="Search airline..." oninput="filtAD()" onfocus="showAD()" autocomplete="off"><div class="as-dd" id="asDD"></div></div></div>

  <!-- Empty state when no airline selected -->
  <div id="custEmpty" style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:80px 20px;text-align:center">
    <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="var(--g300)" stroke-width="1.5" style="margin-bottom:16px"><path d="M17.8 19.2L16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.4-.1.9.3 1.1L11 12l-2 3H6l-1 1 3 2 2 3 1-1v-3l3-2 3.5 7.3c.3.4.7.5 1.1.3l.5-.3c.4-.2.6-.7.5-1.1z"/></svg>
    <p style="font-size:15px;color:var(--g400)">Válassz légitársaságot a fenti keresőben</p>
  </div>

  <!-- easyJet / generic table view -->
  <div id="custViewEJ" style="display:none">
    <div class="stats" id="ejStats">
      <div class="sc"><div class="si or"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div><div class="sv" id="sT">0</div><div class="sl">Total Customers</div></div></div>
      <div class="sc"><div class="si bl"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sA">€0</div><div class="sl">Total Amount</div></div></div>
      <div class="sc"><div class="si pu"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><path d="M14 2v6h6"/></svg></div><div><div class="sv" id="sI">0</div><div class="sl">ID Uploaded</div></div></div>
      <div class="sc"><div class="si gr"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg></div><div><div class="sv" id="sB">0</div><div class="sl">Beadva</div></div></div>
    </div>
    <div class="tc">
      <div class="th">
        <div class="th-l"><img class="th-logo" id="tLogo" src="" style="display:none"><h3 id="tTitle">All Airlines</h3><span class="cnt" id="rCnt">0</span></div>
        <div class="th-r">
          <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Keresés..." id="sIn" oninput="filt();togSearchX()"><span class="sb-x" id="sInX" onclick="document.getElementById('sIn').value='';filt();togSearchX()" style="display:none">✕</span></div>
          <select id="ejStatusFilter" onchange="filt()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">All Status</option>
            <option value="doc_needed">Adatbekérő kiküldeni</option>
            <option value="form_sent">Adatbekérő kiküldve</option>
            <option value="bad_id_sent">Hibás ID, kiküldve</option>
            <option value="form_send">Claim beadni</option>
            <option value="beadva_sajat">Beadva Saját F.</option>
            <option value="beadva_assign">Beadva Assign.</option>
            <option value="beadva_airhelp">Beadva Airhelp</option>
            <option value="jovahagyva">Jóváhagyva</option>
            <option value="kifizetve">Kifizetve</option>
            <option value="elutasitva">Elutasítva</option>
          </select>
          <select id="ejReasonFilter" onchange="filt()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">All Reasons</option>
            <option value="delay">Delayed</option>
            <option value="cancel">Cancelled</option>
            <option value="none">No reason</option>
          </select>
          <select id="ejIdFilter" onchange="filt()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">ID Doc: All</option>
            <option value="yes">Uploaded ✓</option>
            <option value="no">Missing ✗</option>
          </select>
          <button class="fb" id="sortResetBtn" onclick="resetSort()" style="display:none" title="Reset sort"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 105.17-12.36L1 10"/></svg><span>Reset</span></button>
          <button class="fb" onclick="showAddCustomer()" style="background:var(--orange);color:var(--white);border-color:var(--orange)"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg><span>Add Customer</span></button>
        </div>
      </div>
      <div class="bulk-bar" id="bulkBar">
        <span class="bb-count" id="bbCount">0 selected</span>
        <button class="bb-btn" style="background:var(--g100);color:var(--navy)" onclick="selectAllFiltered()" id="bbSelAll">Select All</button>
        <button class="bb-btn bb-tpl" onclick="bulkSetTemplate()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Set Mail Template</button>
        <button class="bb-btn bb-send" onclick="bulkSend()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Send Selected Mails</button>
        <button class="bb-btn bb-status" onclick="bulkStatus()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>Change Status</button>
        <button class="bb-btn bb-gen" onclick="bulkGenAssignment()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>Generate Assignments</button>
        <button class="bb-btn bb-export" onclick="bulkExport()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Export TXT</button>
        <button class="bb-btn bb-export" onclick="bulkExportCSV()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>Export CSV</button>
        <button class="bb-btn bb-del" onclick="bulkDelete()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Delete</button>
        <button class="bb-btn bb-clear" onclick="clearSel()">Clear</button>
      </div>
      <div class="tw"><table><thead><tr>
        <th style="width:30px"><input type="checkbox" class="row-cb" id="selAll" onchange="toggleAll(this.checked)"></th><th class="srt" onclick="sortCol('cid')">ID</th><th>Link</th><th class="srt" onclick="sortCol('f')">First Name</th><th class="srt" onclick="sortCol('l')">Last Name</th><th>Email</th><th>Address</th><th class="srt" onclick="sortCol('bk')">Booking Ref.</th><th class="srt" onclick="sortCol('fl')">Flight Number</th><th>Seat</th><th class="srt" onclick="sortCol('dt')">Date</th><th>Departure</th><th>Arrival</th><th class="srt" onclick="sortCol('rsn')">Reason</th><th class="srt" onclick="sortCol('dist')">Length</th><th>Calc. Dist.</th><th class="srt" onclick="sortCol('comp')">Comp.</th><th class="srt" onclick="sortCol('ah')">AirHelp</th><th class="srt" onclick="sortCol('ahSrc')">Source</th><th>ID Doc</th><th>Travel Doc.</th><th>Assignment</th><th>Mail Sablon</th><th>Mail</th><th>Claim Mail</th><th class="srt" onclick="sortCol('st')">Status</th><th>Jegyzetek</th><th class="srt" onclick="sortCol('upd')">Updated</th><th></th>
      </tr></thead><tbody id="tB"></tbody></table></div>
      <div class="tf" id="tF"><div class="pag" id="pagArea"></div></div>
    </div>
  </div>

  <!-- Wizz Air table view (inside customers page) -->
  <div id="custViewWZ" style="display:none">
    <div class="stats" id="wzStats">
      <div class="sc"><div class="si" style="background:#FDE8F3;color:#E5007D"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div><div class="sv" id="wzST">0</div><div class="sl">Total Customers</div></div></div>
      <div class="sc"><div class="si bl"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="wzSA">€0</div><div class="sl">Total Amount</div></div></div>
      <div class="sc"><div class="si pu"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><path d="M14 2v6h6"/></svg></div><div><div class="sv" id="wzSI">0</div><div class="sl">ID Uploaded</div></div></div>
      <div class="sc"><div class="si gr"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg></div><div><div class="sv" id="wzSB">0</div><div class="sl">Beadva</div></div></div>
    </div>
    <div class="tc">
      <div class="th">
        <div class="th-l">
          <img src="Wizz_Air_Logo.png" style="width:24px;height:24px;border-radius:5px;margin-right:4px" onerror="this.style.display='none'">
          <h3 style="color:#1B1B1B">Wizz Air</h3><span class="cnt" id="wzCnt">0</span>
        </div>
        <div class="th-r">
          <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Keresés..." id="wzSearch" oninput="renderWz()"></div>
          <select id="wzStatusFilter" onchange="renderWz()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">All Status</option>
            <option value="doc_needed">Adatbekérő kiküldeni</option>
            <option value="form_sent">Adatbekérő kiküldve</option>
            <option value="bad_id_sent">Hibás ID, kiküldve</option>
            <option value="form_send">Claim beadni</option>
            <option value="beadva_sajat">Beadva Saját F.</option>
            <option value="beadva_assign">Beadva Assign.</option>
            <option value="beadva_airhelp">Beadva Airhelp</option>
            <option value="jovahagyva">Jóváhagyva</option>
            <option value="kifizetve">Kifizetve</option>
            <option value="elutasitva">Elutasítva</option>
          </select>
          <select id="wzReasonFilter" onchange="renderWz()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">All Reasons</option>
            <option value="delay">Delayed</option>
            <option value="cancel">Cancelled</option>
            <option value="none">No reason</option>
          </select>
          <select id="wzIdFilter" onchange="renderWz()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">ID Doc: All</option>
            <option value="yes">Uploaded ✓</option>
            <option value="no">Missing ✗</option>
          </select>
          <select id="wzCheckinFilter" onchange="renderWz()" style="height:34px;padding:0 10px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
            <option value="">Checkin: All</option>
            <option value="checked_in">Checked in ✓</option>
            <option value="not_checked_in">Not checked in</option>
          </select>
          <button onclick="showWzAddCustomer()" style="padding:6px 14px;border-radius:8px;border:none;background:#E5007D;color:var(--white);font-size:12px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:5px"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Customer</button>
        </div>
      </div>
      <div class="bulk-bar" id="wzBulkBar">
        <span class="bb-count" id="wzBbCount">0 selected</span>
        <button class="bb-btn" style="background:var(--g100);color:var(--navy)" onclick="wzSelectAllFiltered()" id="wzBbSelAll">Select All</button>
        <button class="bb-btn bb-tpl" onclick="wzBulkSetTemplate()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Set Template</button>
        <button class="bb-btn bb-send" onclick="wzBulkSend()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Send Mails</button>
        <button class="bb-btn bb-status" onclick="wzBulkStatus()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>Change Status</button>
        <button class="bb-btn bb-gen" onclick="wzBulkGenAssign()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>Generate Assignments</button>
        <button class="bb-btn bb-del" onclick="wzBulkDelete()"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Delete</button>
        <button class="bb-btn bb-clear" onclick="wzClearSel()">Clear</button>
      </div>
      <div class="tw"><table><thead><tr>
        <th style="width:30px"><input type="checkbox" class="row-cb" id="wzSelAll" onchange="wzToggleAll(this.checked)"></th>
        <th>ID</th><th>Link</th><th>Acc. Nr.</th><th>First Name</th><th>Last Name</th><th>Birth, Nationality</th><th>Passport</th><th>Email</th><th>Phone</th><th>Address</th><th>Booking Ref</th><th>Flight Number</th><th>Seat</th><th>Checkin</th><th>Date</th><th>Departure</th><th>Arrival</th><th>Reason</th><th>Distance</th><th>Comp.</th><th>AirHelp</th><th>Source</th><th>ID Doc</th><th>Travel Doc</th><th>Assignment</th><th>Mail Sablon</th><th>Mail</th><th>Claim Mail</th><th>Status</th><th>Jegyzetek</th><th>Updated</th><th></th>
      </tr></thead><tbody id="wzTB"></tbody></table></div>
      <div class="tf"><div class="pag" id="wzPagArea"></div></div>
    </div>
  </div>
</div>

<!-- ===== FUTURE FLIGHTS PAGE ===== -->
<div class="page" id="page_future">
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:12px">
    <h2>Future Flights</h2>
    <div style="display:flex;gap:8px;align-items:center">
      <label style="padding:6px 14px;border-radius:8px;font-size:12px;font-weight:600;background:var(--orange);color:var(--white);cursor:pointer;display:flex;align-items:center;gap:5px;font-family:'DM Sans',sans-serif;position:relative;overflow:hidden"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Import CSV<input type="file" accept=".csv,.txt" onchange="importFutureCSV(this)" style="position:absolute;inset:0;opacity:0;cursor:pointer"></label>
      <button onclick="showAddFutureFlight()" style="padding:6px 14px;border-radius:8px;font-size:12px;font-weight:600;background:var(--blue);color:var(--white);border:none;cursor:pointer;display:flex;align-items:center;gap:5px;font-family:'DM Sans',sans-serif"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Flight</button>
    </div>
  </div>
  <div style="display:flex;gap:12px;margin-bottom:16px;align-items:center;flex-wrap:wrap">
    <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Search flights..." id="futSearch" oninput="renderFuture()"></div>
    <select id="futAirFilter" onchange="renderFuture()" style="height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
      <option value="">All Airlines</option>
    </select>
    <span class="cnt" id="futCnt">0</span>
  </div>
  <div class="tc">
    <div class="tw"><table><thead><tr>
      <th>Checker</th><th class="srt" onclick="sortFuture('flight_date')" style="cursor:pointer;user-select:none">Date</th><th>Airline</th><th>Flight Number</th><th>Departure</th><th>Arrival</th><th>Status</th><th>Calc. Dist.</th><th>Passengers</th><th>Notes</th><th></th>
    </tr></thead><tbody id="futTB"></tbody></table></div>
    <div class="tf"><div class="pag" id="futPagArea"></div></div>
  </div>
</div>

<!-- ===== REMARKETING PAGE ===== -->
<div class="page" id="page_remarketing">
  <h2 style="margin-bottom:16px">Remarketing Tracking</h2>
  
  <!-- Stats cards -->
  <div class="stats" style="margin-bottom:20px">
    <div class="sc"><div class="si gr"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg></div><div><div class="sv" id="rmActCnt">0</div><div class="sl">Active</div></div></div>
    <div class="sc"><div class="si or"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg></div><div><div class="sv" id="rmSentCnt">0</div><div class="sl">Emails Sent</div></div></div>
    <div class="sc"><div class="si bl"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></div><div><div class="sv" id="rmConvCnt">0</div><div class="sl">ID Uploaded (converted)</div></div></div>
    <div class="sc"><div class="si pu"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></div><div><div class="sv" id="rmPendCnt">0</div><div class="sl">Pending (waiting)</div></div></div>
  </div>
  
  <!-- Filter -->
  <div style="display:flex;gap:8px;margin-bottom:16px;align-items:center;flex-wrap:wrap">
    <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Search..." id="rmSearch" oninput="renderRmPage()"></div>
    <select id="rmAirlineFilter" onchange="renderRmPage()" style="height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
      <option value="">All Airlines</option>
      <option value="easyJet">easyJet</option>
      <option value="Wizz Air">Wizz Air</option>
    </select>
    <select id="rmIdFilter" onchange="renderRmPage()" style="height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
      <option value="">ID: All</option>
      <option value="yes">ID Uploaded ✓</option>
      <option value="no">ID Missing ✗</option>
    </select>
    <select id="rmStatusFilter" onchange="renderRmPage()" style="height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
      <option value="">All Status</option>
      <option value="active">Active</option>
      <option value="stopped">Stopped</option>
    </select>
    <select id="rmStepFilter" onchange="renderRmPage()" style="height:34px;padding:0 12px;border-radius:8px;border:1.5px solid var(--g200);font-size:12px;font-weight:600;font-family:'DM Sans',sans-serif;color:var(--navy);cursor:pointer;background:var(--white)">
      <option value="">All Steps</option>
      <option value="1">Step 1 (1d)</option>
      <option value="2">Step 2 (3d)</option>
      <option value="3">Step 3 (6d)</option>
      <option value="4">Step 4 (9d)</option>
      <option value="5">Step 5 (12d)</option>
    </select>
  </div>
  
  <!-- Table -->
  <div class="tc">
    <div class="tw"><table><thead><tr>
      <th>Customer</th><th>Email</th><th>Booking</th><th>Flight</th><th>Route</th><th>Claim Sent</th>
      <th>Open</th><th>Click</th>
      <th>1d</th><th>3d</th><th>6d</th><th>9d</th><th>12d</th>
      <th>ID Uploaded</th><th>Status</th><th>Actions</th>
    </tr></thead><tbody id="rmTB"></tbody></table></div>
    <div class="tf"><div class="pag" id="rmPagArea"></div></div>
  </div>
</div>

<!-- ===== NOT ELIGIBLE PAGE ===== -->
<div class="page" id="page_not_eligible">
  <div class="tc">
    <div class="th">
      <div class="th-l"><h3>Not Eligible Customers</h3><span class="cnt" id="neRCnt">0</span></div>
      <div class="th-r">
        <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Keresés..." id="neSearch" oninput="renderNE()"></div>
      </div>
    </div>
    <div class="tw"><table><thead><tr>
      <th>ID</th><th>First Name</th><th>Last Name</th><th>Email</th><th>Booking Ref.</th><th>Flight Number</th><th>Date</th><th>Departure</th><th>Arrival</th><th>Reason</th><th>Length</th><th>AirHelp</th><th>AirHelp Note</th><th>Status</th><th>Updated</th><th></th>
    </tr></thead><tbody id="neTB"></tbody></table></div>
    <div class="tf"><div class="pag" id="nePagArea"></div></div>
  </div>
</div>

<!-- ===== TEMPLATES PAGE ===== -->
<!-- ===== STATISTICS PAGE ===== -->
<div class="page" id="page_stats">
  <h2 style="margin-bottom:20px">Statistics</h2>
  <div class="stats">
    <div class="sc"><div class="si or"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div><div class="sv" id="sT">0</div><div class="sl">Total Customers</div></div></div>
    <div class="sc"><div class="si bl"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sA">€0</div><div class="sl">Total Amount</div></div></div>
    <div class="sc"><div class="si pu"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg></div><div><div class="sv" id="sI">0</div><div class="sl">ID Uploaded</div></div></div>
    <div class="sc"><div class="si gr"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg></div><div><div class="sv" id="sB">0</div><div class="sl">Beadva</div></div></div>
  </div>
  <div class="stats s6">
    <div class="sc"><div class="si" style="background:#ECFDF5;color:#059669"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg></div><div><div class="sv" id="sJC">0</div><div class="sl">Jóváhagyva</div></div></div>
    <div class="sc"><div class="si" style="background:#ECFDF5;color:#059669"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sJA">€0</div><div class="sl">Jóváhagyva (€)</div></div></div>
    <div class="sc"><div class="si" style="background:#EFF6FF;color:#2563EB"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sKC">0</div><div class="sl">Kifizetve</div></div></div>
    <div class="sc"><div class="si" style="background:#EFF6FF;color:#2563EB"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sKA">€0</div><div class="sl">Kifizetve (€)</div></div></div>
    <div class="sc"><div class="si" style="background:#FEF2F2;color:#DC2626"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg></div><div><div class="sv" id="sEC">0</div><div class="sl">Elutasítva</div></div></div>
    <div class="sc"><div class="si" style="background:#FEF2F2;color:#DC2626"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg></div><div><div class="sv" id="sEA">€0</div><div class="sl">Elutasítva (€)</div></div></div>
  </div>
  <div class="chart-grid">
    <div class="chart-card"><h4>Status Distribution</h4><div class="chart-wrap"><canvas id="chartStatus"></canvas></div></div>
    <div class="chart-card"><h4>Compensation Breakdown</h4><div class="chart-wrap"><canvas id="chartComp"></canvas></div></div>
  </div>
  <div class="chart-grid">
    <div class="chart-card"><h4>Airlines</h4><div class="chart-wrap"><canvas id="chartAirlines"></canvas></div></div>
    <div class="chart-card"><h4>Monthly Claims</h4><div class="chart-wrap"><canvas id="chartMonthly"></canvas></div></div>
  </div>
</div>

<!-- ===== TEMPLATES PAGE (tiles) ===== -->
<div class="page" id="page_templates">
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:12px">
    <h2>Mail Sablonok</h2>
    <button onclick="showAddTemplate()" style="padding:8px 18px;border-radius:8px;border:none;background:var(--orange);color:var(--white);font-size:13px;font-weight:700;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;display:flex;align-items:center;gap:6px"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>New Template</button>
  </div>
  <p class="tpl-hint">Változók: <code>{{NAME}}</code>, <code>{{FIRST_NAME}}</code>, <code>{{LAST_NAME}}</code>, <code>{{FLIGHT}}</code>, <code>{{DATE}}</code>, <code>{{DEP}}</code>, <code>{{ARR}}</code>, <code>{{BOOKING}}</code>, <code>{{CLAIM_LINK}}</code>, <code>{{CUSTOMER_ID}}</code></p>
  <div id="tplArea" class="tpl-grid"></div>
</div>

<div class="page" id="page_flights">
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:12px">
    <h2>Flight Database</h2>
    <div style="display:flex;gap:8px;align-items:center">
      <div class="sb"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg><input type="text" placeholder="Search flights..." id="flSearch" oninput="flCurPage=1;renderFlights()"></div>
      <label style="padding:6px 14px;border-radius:8px;font-size:12px;font-weight:600;background:var(--orange);color:var(--white);cursor:pointer;display:flex;align-items:center;gap:5px;font-family:'DM Sans',sans-serif;position:relative;overflow:hidden"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Import Flights<input type="file" accept=".csv,.txt" onchange="importFlightsCSV(this)" style="position:absolute;inset:0;opacity:0;cursor:pointer"></label>
      <label style="padding:6px 14px;border-radius:8px;font-size:12px;font-weight:600;background:var(--blue);color:var(--white);cursor:pointer;display:flex;align-items:center;gap:5px;font-family:'DM Sans',sans-serif;position:relative;overflow:hidden"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg>Import AirHelp<input type="file" accept=".txt" onchange="importAirhelp(this)" style="position:absolute;inset:0;opacity:0;cursor:pointer"></label>
    </div>
  </div>
  <div style="font-size:11px;color:var(--g400);margin-bottom:12px">CSV/TXT format: <code>DATE;FlightNumber;Reason;Length</code> (semicolon or comma separated). Header row optional. Reason: number (delay min), "Cancelled", "Diverted", "N/A". Length: km number or "N/A".</div>
  <div class="stats s6">
    <div class="sc"><div class="si or"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.8 19.2L16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.4-.1.9.3 1.1L11 12l-2 3H6l-1 1 3 2 2 3 1-1v-3l3-2 3.5 7.3c.3.4.7.5 1.1.3l.5-.3c.4-.2.6-.7.5-1.1z"/></svg></div><div><div class="sv" id="flTotal">0</div><div class="sl">Total Flights</div></div></div>
    <div class="sc"><div class="si" style="background:var(--orange-light);color:var(--orange)"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></div><div><div class="sv" id="flDelayed">0</div><div class="sl">Delayed</div></div></div>
    <div class="sc"><div class="si" style="background:#FEF2F2;color:#DC2626"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg></div><div><div class="sv" id="flCancelled">0</div><div class="sl">Cancelled</div></div></div>
    <div class="sc"><div class="si" style="background:#ECFDF5;color:#059669"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg></div><div><div class="sv" id="flEligible">0</div><div class="sl">AirHelp Eligible</div></div></div>
    <div class="sc"><div class="si" style="background:#FEF2F2;color:#DC2626"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="18" y1="6" x2="6" y2="18"/></svg></div><div><div class="sv" id="flNotEligible">0</div><div class="sl">Not Eligible</div></div></div>
  </div>
  <div class="tw"><table><thead><tr>
    <th>Date</th><th>Flight Number</th><th>Route</th><th>Reason</th><th>Length</th><th>AirHelp</th><th>Source</th><th>AirHelp Note</th><th>Customers</th><th></th>
  </tr></thead><tbody id="flTB"></tbody></table></div>
  <div class="tf"><div class="pag" id="flPagArea"></div></div>
</div>


</div>
<div class="toast" id="toast"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#22C55E" stroke-width="2.5"><path d="M5 12l5 5L20 7"/></svg><span id="toastT"></span></div>
<div class="em-overlay" id="editModal" onclick="closeEdit()"></div>

<script>
const raw=<?php echo $dataJson;?>;
const tpls=<?php echo $tplJson;?>;
let flData=<?php echo $flJson;?>;
let futureData=<?php echo $futureJson;?>;
let wzAccounts=<?php echo $wzAccountsJson;?>;
let wzBookings=<?php echo $wzBookingsJson;?>;
let wzPassengers=<?php echo $wzPassengersJson;?>;
let wzFlat=<?php echo $wzFlatJson;?>;
const CLAIM_FORM_URL=<?php echo json_encode($claimFormUrl);?>;
const WZ_CLAIM_FORM_URL=<?php echo json_encode($wzClaimFormUrl);?>;
// Normalize date to YYYY-MM-DD
function normDate(d){if(!d)return'';const m=String(d).match(/(\d{4})-(\d{1,2})-(\d{1,2})/);if(m)return m[1]+'-'+m[2].padStart(2,'0')+'-'+m[3].padStart(2,'0');return String(d).trim()}
// Normalize easyJet flight number to base number (digits only)
function ezBaseNum(fn){
  fn=(fn||'').toUpperCase().replace(/\s+/g,'');
  const m=fn.match(/^(?:U2|EZY|EZS|EJU)(\d+)$/);
  return m?m[1]:null;
}
// Build flMap by first grouping easyJet aliases, then merging best data
const flMap={};
(function buildFlMap(){
  const groups={};
  flData.forEach(f=>{
    const bn=ezBaseNum(f.flight_number);
    const nd=normDate(f.flight_date);
    const gk=nd+'_'+(bn?'EZ'+bn:f.flight_number);
    if(!groups[gk])groups[gk]=[];
    groups[gk].push(f);
  });
  Object.values(groups).forEach(grp=>{
    grp.sort((a,b)=>(parseInt(b.id)||0)-(parseInt(a.id)||0));
    // Only AirHelp import records count (airhelp_source set)
    const ahRecs=grp.filter(f=>f.airhelp_source&&f.airhelp_source!=='');
    // ELIGIBLE always wins over NOT ELIGIBLE
    const ahRec=ahRecs.find(f=>f.airhelp_eligible==='ELIGIBLE')||ahRecs[0]||{};
    const rsnRec=grp.find(f=>f.reason)||{};
    const distRec=grp.find(f=>f.distance_km)||{};
    const entry={
      reason:rsnRec.reason||'',
      dist:parseInt(distRec.distance_km)||0,
      ah:ahRec.airhelp_eligible||'',
      ahSrc:ahRec.airhelp_source||'',
      ahNote:ahRec.airhelp_note||''
    };
    const allNums=new Set();
    grp.forEach(f=>{
      allNums.add(f.flight_number);
      const bn2=ezBaseNum(f.flight_number);
      if(bn2){['U2','EZY','EZS','EJU'].forEach(p=>allNums.add(p+bn2))}
      if(f.flight_aliases){f.flight_aliases.split(',').forEach(a=>{a=a.trim();if(a)allNums.add(a)})}
    });
    const dt=normDate(grp[0].flight_date);
    allNums.forEach(fn=>{flMap[fn+'_'+dt]=entry});
  });
})();
const LOGOS={'easyJet':'EasyJet-Logo_wine.png','Emirates':'https://logo.clearbit.com/emirates.com','Lufthansa':'https://logo.clearbit.com/lufthansa.com','LOT Airlines':'https://logo.clearbit.com/lot.com','Ryanair':'https://logo.clearbit.com/ryanair.com','Wizz Air':'Wizz_Air_Logo.png'};
const STS=['doc_needed','form_sent','bad_id_sent','form_send','beadva_sajat','beadva_assign','beadva_airhelp','jovahagyva','kifizetve','elutasitva'];
const SLB={created:'Created',doc_needed:'Adatbekérő kiküldeni',form_sent:'Adatbekérő kiküldve',bad_id_sent:'Hibás ID, kiküldve',form_send:'Claim beadni',beadva_sajat:'Beadva Saját F.',beadva_assign:'Beadva Assign.',beadva_airhelp:'Beadva Airhelp',jovahagyva:'Jóváhagyva',kifizetve:'Kifizetve',elutasitva:'Elutasítva'};
const MI=`<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>`;
const PI=`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>`;
let curAir='',curSF='';
// Lookup flight data with easyJet alias support
function flLookup(fn,dt){
  fn=(fn||'').toUpperCase().replace(/\s+/g,'');
  dt=normDate(dt);
  return flMap[fn+'_'+dt]||{};
}
const D=raw.map(r=>{const fm=flLookup(r.flight_number,r.flight_date);return{id:r.id,cid:r.customer_id,f:r.first_name,l:r.last_name,bk:r.booking_ref,fl:r.flight_number,seat:r.seat||'',dt:r.flight_date,dep:r.departure,arr:r.arrival,rsn:r.reason||fm.reason||'',air:r.airline||'easyJet',dist:parseInt(r.distance_km)||fm.dist||0,ah:fm.ah||'',ahSrc:fm.ahSrc||'',ahNote:fm.ahNote||'',main:parseInt(r.is_main)===1,idF:r.id_doc_filename||'',idP:r.id_doc_path||'',idV:parseInt(r.id_doc_viewed||0),trF:r.travel_doc_filename||'',trP:r.travel_doc_path||'',trV:parseInt(r.travel_doc_viewed||0),asF:r.assignment_filename||'',asP:r.assignment_path||'',st:r.status||'doc_needed',ms:r.mail_sent_at||'',mt:r.mail_template||'',mts:r.mail_template||'',aS:r.address_street||'',aC:r.address_city||'',aP:r.address_postal||'',aCo:r.address_country||'',em:r.email||'',cm:r.claim_method||'',rmActive:parseInt(r.remarketing_active||0),rmSent:r.claim_mail_sent_at||'',upd:r.updated_at,notes:r.notes||''}});

// Distance lookup map
let distMap={};
fetch('/distancekm.json').then(r=>r.json()).then(j=>{
  if(j.distances){j.distances.forEach(d=>{distMap[d.from+'_'+d.to]=d.km;distMap[d.to+'_'+d.from]=d.km})}
  filt(); // re-render with distances
}).catch(()=>{});

function iata(s){const m=(s||'').match(/\(([A-Z]{3})\)/);return m?m[1]:''}
function calcDist(dep,arr){const d=iata(dep),a=iata(arr);if(!d||!a)return 0;return distMap[d+'_'+a]||0}
function calcComp(km){if(!km)return'';if(km<=1500)return'€250';if(km<=3500)return'€400';return'€600'}
function cc2(km){if(!km)return 0;if(km<=1500)return 250;if(km<=3500)return 400;return 600}
const airs=[...new Set(D.map(r=>r.air))];

function cc(d){if(!d)return 0;if(d<=1500)return 250;if(d<=3500)return 400;return 600}
function cL(d){return d?'€'+cc(d):''}
function cC(d){if(!d)return'';if(d<=1500)return'c250';if(d<=3500)return'c400';return'c600'}
function gD(){let d=curAir?D.filter(r=>r.air===curAir):D;return d.filter(r=>r.ah!=='NOT ELIGIBLE')}
function getCompKm(r){const cd=calcDist(r.dep,r.arr);return cd||r.dist||0}
function uS(){const d=gD();document.getElementById('sT').textContent=d.length;let t=0;d.forEach(r=>{const km=getCompKm(r);if(km)t+=cc2(km)});document.getElementById('sA').textContent='€'+t.toLocaleString();document.getElementById('sI').textContent=d.filter(r=>r.idF).length;document.getElementById('sB').textContent=d.filter(r=>r.st.startsWith('beadva')).length;
  const jc=d.filter(r=>r.st==='jovahagyva');document.getElementById('sJC').textContent=jc.length;let ja=0;jc.forEach(r=>{const km=getCompKm(r);if(km)ja+=cc2(km)});document.getElementById('sJA').textContent='€'+ja.toLocaleString();
  const kc=d.filter(r=>r.st==='kifizetve');document.getElementById('sKC').textContent=kc.length;let ka=0;kc.forEach(r=>{const km=getCompKm(r);if(km)ka+=cc2(km)});document.getElementById('sKA').textContent='€'+ka.toLocaleString();
  const ec=d.filter(r=>r.st==='elutasitva');document.getElementById('sEC').textContent=ec.length;let ea=0;ec.forEach(r=>{const km=getCompKm(r);if(km)ea+=cc2(km)});document.getElementById('sEA').textContent='€'+ea.toLocaleString()}
function fmtReason(r){if(!r)return'';r=String(r).trim();if(/^\d+$/.test(r))return'Delayed ('+r+' min)';if(r.toLowerCase()==='cancelled'||r.toLowerCase()==='canceled')return'Cancelled';return r}
function rC(r){const f=fmtReason(r).toLowerCase();if(f.includes('delay'))return'del';if(f.includes('cancel'))return'can';return f.includes('over')?'ovb':''}
function fD(d){if(!d)return'';d=String(d).trim();const m=d.match(/(\d{4})-(\d{2})-(\d{2})/);if(m)return m[1]+'.'+m[2]+'.'+m[3];return d}
function fDT(d){if(!d)return'';try{const dt=new Date(d.replace(' ','T'));const y=dt.getFullYear();const m=String(dt.getMonth()+1).padStart(2,'0');const dd=String(dt.getDate()).padStart(2,'0');const h=String(dt.getHours()).padStart(2,'0');const mi=String(dt.getMinutes()).padStart(2,'0');return y+'.'+m+'.'+dd+' '+h+':'+mi}catch{return d}}
let cT;function cp(t){navigator.clipboard.writeText(t).then(()=>{document.getElementById('toastT').textContent='Copied';document.getElementById('toast').classList.add('show');clearTimeout(cT);cT=setTimeout(()=>document.getElementById('toast').classList.remove('show'),1500)})}
function toast(t){document.getElementById('toastT').textContent=t;document.getElementById('toast').classList.add('show');clearTimeout(cT);cT=setTimeout(()=>document.getElementById('toast').classList.remove('show'),1500)}
function togSearchX(){document.getElementById('sInX').style.display=document.getElementById('sIn').value?'':'none'}

// Pages
function showPage(p){document.querySelectorAll('.page').forEach(e=>e.classList.remove('active'));document.getElementById('page_'+p).classList.add('active');document.querySelectorAll('.nav-tab').forEach(e=>e.classList.remove('active'));event.target.classList.add('active');if(p==='templates')renderTpls();if(p==='flights')renderFlights();if(p==='stats'){uS();renderCharts()}if(p==='not_eligible')renderNE();if(p==='future')renderFuture();if(p==='remarketing')renderRmPage(true)}

// Airline selector for customers page — picks which table view to show
let custAirlineMode=''; // '' = nothing selected, 'Wizz Air' = WZ view, other = easyJet/generic

function selectCustAirline(air){
  custAirlineMode=air;
  const emptyEl=document.getElementById('custEmpty');
  const ejView=document.getElementById('custViewEJ');
  const wzView=document.getElementById('custViewWZ');
  
  if(!air){
    // No airline selected — show empty state
    emptyEl.style.display='flex';ejView.style.display='none';wzView.style.display='none';
    return;
  }
  
  emptyEl.style.display='none';
  
  if(air==='Wizz Air'){
    ejView.style.display='none';wzView.style.display='block';
    renderWz();
  }else{
    wzView.style.display='none';ejView.style.display='block';
    curAir=air;
    const logo=LOGOS[air]||'';
    document.getElementById('tLogo').src=logo;document.getElementById('tLogo').style.display=logo?'':'none';
    document.getElementById('tTitle').textContent=air;
    uS();filt();
  }
  // Update search input display
  document.getElementById('asIn').value=air;
  document.getElementById('asDD').classList.remove('show');
}

// Airline — build full list, always include easyJet + Wizz Air
const allAirlines=(function(){
  const set=new Set(['easyJet','Wizz Air']);
  airs.forEach(a=>set.add(a));
  return [...set].sort();
})();
function swAir(n){selectCustAirline(n)}
function showAD(){rAD(allAirlines);document.getElementById('asDD').classList.add('show')}
function filtAD(){const q=document.getElementById('asIn').value.toLowerCase();const filtered=allAirlines.filter(a=>a.toLowerCase().includes(q));rAD(filtered.length?filtered:allAirlines);document.getElementById('asDD').classList.add('show')}
function rAD(list){const dd=document.getElementById('asDD');let h='';list.forEach(a=>{const isWz=a==='Wizz Air';const c=isWz?WZ.length:D.filter(r=>r.air===a).length;const lg=LOGOS[a]?`<img class="as-logo" src="${LOGOS[a]}" onerror="this.style.display='none'">`:'';const color=isWz?'color:#E5007D':'';h+=`<div class="as-item ${a===custAirlineMode?'act':''}" style="${color}" onclick="swAir('${a.replace(/'/g,"\\'")}')">${lg} ${a}<span class="cnt">${c}</span></div>`});dd.innerHTML=h}
document.addEventListener('click',e=>{if(!e.target.closest('.as-wrap'))document.getElementById('asDD').classList.remove('show')});

function stBdg(id,s){return`<select class="stb st-${s}" onchange="chSt(${id},this.value)">${STS.map(x=>`<option value="${x}" ${x===s?'selected':''}>${SLB[x]}</option>`).join('')}</select>`}
const CM_OPTS=[{key:'',label:''},{key:'assignment',label:'Assignment'},{key:'sajat_fiok',label:'Saját fiók'},{key:'airhelp',label:'Airhelp'}];
const CM_COLORS={assignment:'#3B82F6',sajat_fiok:'#F59E0B',airhelp:'#8B5CF6'};
function cmSel(id,val,show){
  if(!show)return'';
  return`<select class="cmb" style="font-size:10px;padding:2px 6px;border-radius:5px;border:1px solid var(--g200);background:${val?CM_COLORS[val]||'var(--g100)':'var(--white)'};color:${val?'#fff':'var(--g500)'};font-weight:${val?'700':'400'};cursor:pointer;font-family:'DM Sans',sans-serif" onchange="chCm(${id},this.value)">${CM_OPTS.map(o=>`<option value="${o.key}" ${o.key===val?'selected':''}>${o.label}</option>`).join('')}</select>`}
async function chCm(id,val){
  await fetch('?action=update_field',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:'claim_method',value:val})});
  const r=D.find(x=>x.id==id);if(r)r.cm=val;
  rT(getPageData());toast('Claim method updated');
}
// Notes
function notesC(id,val,show){
  if(!show)return'';
  const has=val&&val.trim();
  const ico='<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>';
  if(!has) return`<span class="ni" onclick="editNote(event,${id})">${ico}</span>`;
  return`<span class="ni has" onclick="editNote(event,${id})" onmouseenter="showNoteTip(event,${id})" onmouseleave="hideNoteTip()">${ico}</span>`;
}
function showNoteTip(ev,id){
  const r=D.find(x=>x.id==id);if(!r||!r.notes)return;
  let tip=document.getElementById('noteTip');
  if(!tip){tip=document.createElement('div');tip.id='noteTip';tip.className='ni-tip';document.body.appendChild(tip);}
  tip.textContent=r.notes;
  tip.style.display='block';
  const rect=ev.currentTarget.getBoundingClientRect();
  tip.style.left=rect.left+rect.width/2-tip.offsetWidth/2+'px';
  tip.style.top=rect.top-tip.offsetHeight-10+'px';
  // Keep within viewport
  const tr=tip.getBoundingClientRect();
  if(tr.left<8)tip.style.left='8px';
  if(tr.right>window.innerWidth-8)tip.style.left=window.innerWidth-8-tip.offsetWidth+'px';
  if(tr.top<8){tip.style.top=rect.bottom+10+'px';tip.style.setProperty('--arrow','top');} 
}
function hideNoteTip(){const tip=document.getElementById('noteTip');if(tip)tip.style.display='none';}
function editNote(ev,id){
  ev.stopPropagation();hideNoteTip();
  const r=D.find(x=>x.id==id);if(!r)return;
  const cur=r.notes||'';
  const old=document.getElementById('noteEditor');if(old)old.remove();
  const div=document.createElement('div');div.id='noteEditor';
  div.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(27,42,74,.35);z-index:99998;display:flex;align-items:center;justify-content:center';
  div.onclick=function(e){if(e.target===div)div.remove()};
  div.innerHTML=`<div style="background:var(--white);border-radius:18px;box-shadow:0 24px 64px rgba(27,42,74,.28);width:460px;overflow:hidden" onclick="event.stopPropagation()">
    <div style="padding:18px 24px;border-bottom:1px solid var(--g200);display:flex;align-items:center;justify-content:space-between">
      <span style="font-weight:800;font-size:15px;color:var(--navy)">Jegyzetek — ${esc(r.f)} ${esc(r.l)}</span>
      <button onclick="document.getElementById('noteEditor').remove()" style="width:28px;height:28px;border-radius:8px;border:none;background:var(--g100);color:var(--g500);cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center">✕</button>
    </div>
    <div style="padding:20px 24px">
      <textarea id="noteTA" style="width:100%;min-height:160px;border:1.5px solid var(--g200);border-radius:10px;padding:12px 14px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);resize:vertical;outline:none;line-height:1.6" placeholder="Jegyzet hozzáadása...">${esc(cur)}</textarea>
      <div style="display:flex;gap:8px;margin-top:14px;justify-content:flex-end">
        ${cur?`<button onclick="saveNote(${id},'')" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:1px solid var(--red);background:var(--red-light);color:var(--red);cursor:pointer;font-family:'DM Sans',sans-serif">Törlés</button>`:''}
        <button onclick="document.getElementById('noteEditor').remove()" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:1px solid var(--g200);background:var(--white);color:var(--g500);cursor:pointer;font-family:'DM Sans',sans-serif">Mégse</button>
        <button onclick="saveNote(${id},document.getElementById('noteTA').value)" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:none;background:var(--orange);color:var(--white);cursor:pointer;font-family:'DM Sans',sans-serif">Mentés</button>
      </div>
    </div>
  </div>`;
  document.body.appendChild(div);
  const ta=document.getElementById('noteTA');ta.focus();ta.setSelectionRange(ta.value.length,ta.value.length);
}
async function saveNote(id,val){
  document.getElementById('noteEditor').remove();
  const r=D.find(x=>x.id==id);if(r)r.notes=val;
  rT(getPageData());toast(val?'Jegyzet mentve':'Jegyzet törölve');
  await fetch('?action=update_field',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:'notes',value:val})});
}
async function chSt(id,ns){const r=D.find(x=>x.id==id);if(r)r.st=ns;delete histCache['hist_'+id];uS();filt();await fetch('?action=update_status',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,status:ns})})}

function docC(id,dt,fn,fp,vw){if(fn){const vc=vw?'vw':'uv';const url=fp?('uploads/'+fp):'#';return`<div class="dc"><a href="${url}" target="_blank" class="dib ${vc}" onclick="mV(${id},'${dt}')" title="${fn}">${PI}</a><button class="ddb" onclick="dD(${id},'${dt}')"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>`}return`<div class="dc"><label class="dub"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Upload<input type="file" accept=".pdf,.jpg,.jpeg,.png" onchange="uD(${id},'${dt}',this)"></label></div>`}
async function mV(id,dt){const r=D.find(x=>x.id==id);if(!r)return;if(dt==='id')r.idV=1;else r.trV=1;const res=await fetch('?action=mark_viewed',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,doc_type:dt})});const j=await res.json();if(j.new_status&&dt==='id'){r.st=j.new_status;uS()}filt()}
async function dD(id,dt){const r=D.find(x=>x.id==id);if(r){if(dt==='id'){r.idF='';r.idP='';r.idV=0;if(r.st==='form_send'||r.st==='bad_id_sent')r.st='doc_needed'}else{r.trF='';r.trP='';r.trV=0}}uS();filt();await fetch('?action=delete_doc',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,doc_type:dt})})}
async function uD(id,dt,inp){if(!inp.files||!inp.files[0])return;const f=inp.files[0];const r=D.find(x=>x.id==id);if(r){if(dt==='id'){r.idF=f.name;r.idV=0}else{r.trF=f.name;r.trV=0}}filt();const fd=new FormData();fd.append('id',id);fd.append('doc_type',dt);fd.append('file',f);await fetch('?action=upload_doc',{method:'POST',body:fd})}

// Assignment
function asC(id,fn,fp,hasAddr){if(fn&&fp){const url='uploads/'+fp;return`<div class="dc"><a href="${url}" target="_blank" class="dib vw" title="${fn}">${PI}</a><button class="ddb" onclick="dAs(${id})"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg></button></div>`}let btns=`<label class="dub" style="font-size:9px;padding:3px 6px"><svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Upload<input type="file" accept=".pdf,.docx" onchange="uAs(${id},this)"></label>`;if(hasAddr)btns+=`<button class="gen-btn" onclick="genAs(${id})" title="Generate from current data"><svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 12 15 15"/></svg>Generate</button>`;return`<div class="dc" style="gap:3px">${btns}</div>`}
async function dAs(id){const r=D.find(x=>x.id==id);if(r){r.asF='';r.asP=''}filt();await fetch('?action=delete_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})})}
async function uAs(id,inp){if(!inp.files||!inp.files[0])return;const f=inp.files[0];const fd=new FormData();fd.append('id',id);fd.append('file',f);const res=await fetch('?action=upload_assignment',{method:'POST',body:fd});const j=await res.json();if(j.ok){const r=D.find(x=>x.id==id);if(r){r.asF=j.filename||f.name;r.asP=j.path||'';if(j.new_status){r.st=j.new_status;delete histCache['hist_'+id]}}}uS();filt()}
async function genAs(id){const r=D.find(x=>x.id==id);if(!r)return;if(!r.aS&&!r.aC){toast('No address — fill address first');return}const res=await fetch('?action=generate_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});const j=await res.json();if(j.ok){r.asF=j.filename||'Assignment.pdf';r.asP=j.path||'';if(j.new_status){r.st=j.new_status;delete histCache['hist_'+id]}uS();filt();toast('Assignment generated!')}else{toast(j.msg||'Generation failed')}}

// Mail
function mailTplSel(id,cur){return`<select class="mail-sel" onchange="setMailTpl(${id},this.value)"><option value="">—</option>${tpls.map(t=>`<option value="${t.slug}" ${cur===t.slug?'selected':''}>${t.label}</option>`).join('')}</select>`}
function setMailTpl(id,v){const r=D.find(x=>x.id==id);if(r){r.mt=v;r.mts=''}fetch('?action=set_mail_template',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:v})});rT(getPageData())}
function mailC(id,ms,mt,lastSentTpl,isMain,isGrp){if(!isMain&&isGrp)return'';if(!mt)return'';if(ms&&mt===lastSentTpl){return`<button class="mb snt">${MI} Sent</button>`}return`<button class="mb rdy" onclick="sendM(${id})">${MI} Send</button>`}
async function sendM(id){
  const r=D.find(x=>x.id==id);
  if(!r||!r.mt){toast('Select a mail template first');return}
  if(!r.em){toast('No email address — add email first');return}
  
  // Load preview
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:680px;max-height:90vh;display:flex;flex-direction:column">
    <div class="em-head" style="flex-shrink:0"><h3>Preview & Send Email</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body" style="flex:1;overflow:auto;text-align:center;padding:40px">
      <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--orange)" stroke-width="2" style="animation:spin 1s linear infinite"><path d="M21 12a9 9 0 11-6.219-8.56"/></svg>
      <p style="margin-top:8px;font-size:13px;color:var(--g500)">Loading preview...</p>
    </div></div>`;
  m.classList.add('show');
  
  try{
    const res=await fetch('?action=preview_template',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:r.mt})});
    const j=await res.json();
    if(!j.ok){toast(j.message||'Preview failed');closeEdit();return}
    
    const isHtml=j.is_html;
    const bodySection=isHtml
      ?`<div style="margin-top:12px;background:var(--white);border:1px solid var(--g200);border-radius:8px;overflow:hidden"><iframe id="sendPreviewFrame" style="width:100%;height:420px;border:none" sandbox="allow-same-origin"></iframe></div>
        <p style="margin-top:6px;font-size:10px;color:var(--g400);text-align:left">HTML email — content from email-notification.html template</p>`
      :`<div style="margin-top:12px;text-align:left">
          <label style="font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:4px">Body</label>
          <textarea id="sendPreviewBody" style="width:100%;min-height:260px;border:1.5px solid var(--g200);border-radius:8px;padding:12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);resize:vertical;line-height:1.6">${esc(j.body)}</textarea>
        </div>`;
    
    m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:680px;max-height:90vh;display:flex;flex-direction:column">
      <div class="em-head" style="flex-shrink:0"><h3>Preview & Send Email</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
      <div style="flex-shrink:0;padding:12px 20px;background:var(--g50);border-bottom:1px solid var(--g100);display:flex;align-items:center;gap:8px;flex-wrap:wrap">
        <span style="font-size:11px;color:var(--g400)">To:</span><span style="font-size:12px;font-weight:600;color:var(--navy)">${esc(j.email||'no email')}</span>
        <span style="font-size:11px;color:var(--g400);margin-left:8px">Recipient:</span><span style="font-size:12px;font-weight:500;color:var(--navy)">${esc(j.name)}</span>
      </div>
      <div class="em-body" style="flex:1;overflow:auto;">
        <div style="text-align:left">
          <label style="font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:4px">Subject</label>
          <input type="text" id="sendPreviewSubject" value="${esc(j.subject)}" style="width:100%;height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none">
        </div>
        ${bodySection}
      </div>
      <div class="em-foot" style="flex-shrink:0">
        <button class="em-cancel" onclick="closeEdit()">Cancel</button>
        <button class="em-save" onclick="doSendAfterPreview(${id},'${r.mt}',${isHtml})" style="display:flex;align-items:center;gap:6px">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
          Send Email
        </button>
      </div>
    </div>`;
    
    if(isHtml){
      setTimeout(()=>{
        const fr=document.getElementById('sendPreviewFrame');
        if(fr&&fr.contentDocument){fr.contentDocument.open();fr.contentDocument.write(j.html);fr.contentDocument.close()}
      },50);
    }
  }catch(e){toast('Preview failed');closeEdit()}
}

async function doSendAfterPreview(id,tpl,isHtml){
  const subject=document.getElementById('sendPreviewSubject').value;
  const body=isHtml?'':( document.getElementById('sendPreviewBody')?.value||'');
  const r=D.find(x=>x.id==id);
  
  closeEdit();
  const res=await fetch('?action=send_custom_mail',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:tpl,subject:subject,body:body})});
  const j=await res.json();
  if(j.ok){
    if(r){r.ms=j.mail_sent_at;r.mts=tpl;delete histCache['hist_'+id];if(tpl==='claim_submit'){r.st='form_sent';r.rmActive=1;r.rmSent=j.mail_sent_at}else if(tpl==='hibas_id')r.st='bad_id_sent'}
    rmLoaded=false;uS();filt();toast('Mail sent!')
  }else{toast(j.message||'Email sending failed')}
}

async function previewClaimMail(id){
  const r=D.find(x=>x.id==id);if(!r)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:720px;max-height:90vh">
    <div class="em-head"><h3>Claim Notification Preview — ${esc(r.f)} ${esc(r.l)}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body" style="padding:16px;text-align:center">
      <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--orange)" stroke-width="2" style="animation:spin 1s linear infinite"><path d="M21 12a9 9 0 11-6.219-8.56"/></svg>
      <p style="margin-top:8px;font-size:13px;color:var(--g500)">Loading email preview...</p>
    </div></div>`;
  m.classList.add('show');
  try{
    const res=await fetch('?action=preview_email',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
    const j=await res.json();
    if(j.ok){
      m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:720px;max-height:90vh;display:flex;flex-direction:column">
        <div class="em-head" style="flex-shrink:0"><h3>Claim Notification Preview — ${esc(r.f)} ${esc(r.l)}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
        <div style="flex-shrink:0;padding:12px 20px;background:var(--g50);border-bottom:1px solid var(--g100);display:flex;align-items:center;gap:8px;flex-wrap:wrap">
          <span style="font-size:11px;color:var(--g400)">To:</span><span style="font-size:12px;font-weight:600;color:var(--navy)">${esc(r.em)||'<no email>'}</span>
          <span style="font-size:11px;color:var(--g400);margin-left:12px">Booking:</span><span style="font-size:12px;font-weight:700;color:var(--orange)">${esc(r.bk)}</span>
          <span style="font-size:11px;color:var(--g400);margin-left:12px">Claim link:</span><a href="${j.claim_link}" target="_blank" style="font-size:11px;color:var(--blue);word-break:break-all">${j.claim_link.substring(0,80)}...</a>
        </div>
        <div style="flex:1;overflow:auto;padding:0">
          <iframe id="previewFrame" style="width:100%;height:600px;border:none" sandbox="allow-same-origin"></iframe>
        </div>
        <div class="em-foot" style="flex-shrink:0">
          <button class="em-cancel" onclick="closeEdit()">Close</button>
        </div>
      </div>`;
      setTimeout(()=>{
        const fr=document.getElementById('previewFrame');
        if(fr&&fr.contentDocument){fr.contentDocument.open();fr.contentDocument.write(j.html);fr.contentDocument.close()}
      },50);
    }else{toast(j.message||'Preview failed');closeEdit()}
  }catch(e){toast('Preview failed');closeEdit()}
}

// History tooltip loader
const histCache={};
let floatTip=null;let floatTimeout=null;
function hideHist(){floatTimeout=setTimeout(()=>{if(floatTip){floatTip.remove();floatTip=null}},200)}
async function showHist(ev,id){
  clearTimeout(floatTimeout);
  if(floatTip){floatTip.remove();floatTip=null}
  const rect=ev.currentTarget.getBoundingClientRect();
  const tip=document.createElement('div');tip.className='float-tip';
  // Position below, keep in viewport
  let top=rect.bottom+8;
  let left=rect.left+rect.width/2-220;
  if(left<8)left=8;if(left+460>window.innerWidth)left=window.innerWidth-468;
  if(top+300>window.innerHeight)top=rect.top-310; // flip up if no room
  tip.style.top=top+'px';tip.style.left=left+'px';
  tip.innerHTML='<div style="color:var(--g400);font-size:10px;text-align:center">Loading history...</div>';
  tip.onmouseenter=()=>clearTimeout(floatTimeout);
  tip.onmouseleave=()=>hideHist();
  document.body.appendChild(tip);floatTip=tip;

  const ck='hist_'+id;
  if(histCache[ck]){tip.innerHTML=histCache[ck];return}
  try{
    const res=await fetch('?action=get_history',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
    const j=await res.json();if(!j.ok)return;
    let mailHtml='<div class="ht-title"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Mail History</div>';
    if(j.mails.length===0)mailHtml+='<div class="ht-empty">No mails sent</div>';
    else j.mails.forEach(m=>{mailHtml+=`<div class="ht-row"><span class="ht-dot mail"></span><div class="ht-info"><span class="ht-val">${m.template_label}</span><span class="ht-date">${fDT(m.sent_at)}</span></div></div>`});
    let stHtml='<div class="ht-title"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>Status History</div>';
    if(j.statuses.length===0)stHtml+='<div class="ht-empty">No changes</div>';
    else j.statuses.forEach(s=>{stHtml+=`<div class="ht-row"><span class="ht-dot status"></span><div class="ht-info"><span class="ht-val">${SLB[s.status]||s.status}</span><span class="ht-date">${fDT(s.changed_at)}</span></div></div>`});
    const html=`<div class="ft-cols"><div class="ft-col">${mailHtml}</div><div class="ft-col" style="border-left:1px solid var(--g100);padding-left:16px">${stHtml}</div></div>`;
    histCache[ck]=html;
    if(floatTip===tip)tip.innerHTML=html;
  }catch(e){}}

function genUrl(bk,grp){const m=grp.find(r=>r.main)||grp[0];const pn=grp.map(r=>(r.f+'_'+r.l).replace(/\s/g,'_')).join(',');const dc=(m.dep.match(/\(([A-Z]+)\)/)||['',''])[1];const ac=(m.arr.match(/\(([A-Z]+)\)/)||['',''])[1];const dci=m.dep.replace(/\s*\([A-Z]+\)\s*/,'').trim();const aci=m.arr.replace(/\s*\([A-Z]+\)\s*/,'').trim();return CLAIM_FORM_URL+'?'+new URLSearchParams({booking:bk,flight:m.fl,date:m.dt,from:dc,fromCity:dci,to:ac,toCity:aci,reason:fmtReason(m.rsn),pax:pn}).toString()}

// Edit modal — opens for entire booking group
function openEdit(bk,fl,dt){
  // Group by booking_ref + flight_number + flight_date to avoid mixing different flights
  const grp=D.filter(x=>x.bk===bk && x.fl===fl && x.dt===dt);
  if(!grp.length)return;
  const main=grp.find(x=>x.main)||grp[0];
  const m=document.getElementById('editModal');
  const grpKey=bk+'|'+fl+'|'+dt;
  let paxHtml=grp.map((r,i)=>{
    const isMain=r.main;
    const delBtn=`<button onclick="delPaxInEdit(${r.id})" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Delete</button>`;
    return`
      <div id="paxCard_${r.id}" style="background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px">
        <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
          <span style="font-size:14px;font-weight:800;color:var(--navy)">${r.f} ${r.l}</span>
          ${isMain?'<span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--orange);background:var(--orange-light);padding:2px 6px;border-radius:4px">Main</span>':'<span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>'}
          ${delBtn}
        </div>
        <div class="em-grid">
          <div class="em-fg"><label>Customer ID</label><input id="ef_cid_${i}" value="${esc(r.cid)}"></div>
          <div class="em-fg"><label>First Name</label><input id="ef_f_${i}" value="${esc(r.f)}"></div>
          <div class="em-fg"><label>Last Name</label><input id="ef_l_${i}" value="${esc(r.l)}"></div>
          <div class="em-fg"><label>Airline</label><input id="ef_air_${i}" value="${esc(r.air)}"></div>
          <div class="em-fg"><label>Email</label><input id="ef_em_${i}" value="${esc(r.em)}" type="email"></div>
          <div class="em-fg"><label>Seat</label><input id="ef_seat_${i}" value="${esc(r.seat)}" placeholder="e.g. 14A"></div>
        </div>
        <div style="margin-top:10px"><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--g400);margin-bottom:6px">Address</div>
        <div class="em-grid">
          <div class="em-fg full"><label>Street & Number</label><input id="ef_aS_${i}" value="${esc(r.aS)}"></div>
          <div class="em-fg"><label>City</label><input id="ef_aC_${i}" value="${esc(r.aC)}"></div>
          <div class="em-fg"><label>Postal Code</label><input id="ef_aP_${i}" value="${esc(r.aP)}"></div>
          <div class="em-fg full"><label>Country</label><input id="ef_aCo_${i}" value="${esc(r.aCo)}"></div>
        </div></div>
      </div>`}).join('');

  m.innerHTML=`
  <div class="em-box" onclick="event.stopPropagation()">
    <div class="em-head"><h3>Edit Booking — ${esc(bk)}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <div class="em-section">Flight Details</div>
      <div class="em-grid">
        <div class="em-fg"><label>Booking Ref</label><input id="ef_bk" value="${esc(main.bk)}"></div>
        <div class="em-fg"><label>Flight Number</label><input id="ef_fl" value="${esc(main.fl)}"></div>
        <div class="em-fg"><label>Date</label><input type="date" id="ef_dt" value="${main.dt}"></div>
        <div class="em-fg"><label>Departure</label><input id="ef_dep" value="${esc(main.dep)}"></div>
        <div class="em-fg"><label>Arrival</label><input id="ef_arr" value="${esc(main.arr)}"></div>
        <div class="em-fg"><label>Reason</label><input id="ef_rsn" value="${esc(main.rsn)}"></div>
        <div class="em-fg"><label>Distance (km)</label><input type="number" id="ef_dist" value="${main.dist||''}"></div>
      </div>
      <div class="em-section">Passengers (${grp.length})</div>
      <div id="editPaxList">${paxHtml}</div>
      <button onclick="addPaxCardInEdit('${esc(bk)}')" style="margin-top:8px;width:100%;padding:10px;border-radius:8px;border:1.5px dashed var(--g300);background:var(--white);color:var(--g500);font-size:13px;font-weight:600;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;justify-content:center;gap:6px;transition:all .15s" onmouseover="this.style.borderColor='var(--orange)';this.style.color='var(--orange)';this.style.background='var(--orange-light)'" onmouseout="this.style.borderColor='var(--g300)';this.style.color='var(--g500)';this.style.background='var(--white)'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Passenger</button>
    </div>
    <div class="em-foot"><button class="em-save" onclick="saveGroupEdit('${esc(bk)}','${esc(fl)}','${esc(dt)}')">Save Changes</button><button class="em-cancel" onclick="closeEdit()">Cancel</button></div>
  </div>`;
  m.classList.add('show')}
function esc(s){return String(s||'').replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/</g,'&lt;')}
function closeEdit(){document.getElementById('editModal').classList.remove('show')}

let ncPaxCount=1;
function showAddCustomer(){
  ncPaxCount=1;
  const airlineOpts=['easyJet','Ryanair','Wizz Air','Lufthansa','British Airways','Air France','KLM','Vueling','Emirates','LOT Airlines','Other'];
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:700px">
    <div class="em-head"><h3>Add New Customer</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <div class="em-section">Flight Details</div>
      <div class="em-grid">
        <div class="em-fg"><label>Booking Ref *</label><input id="nc_bk" placeholder="ABC1234"></div>
        <div class="em-fg"><label>Flight Number</label><input id="nc_fl" placeholder="U2 1234"></div>
        <div class="em-fg"><label>Date</label><input type="date" id="nc_dt"></div>
        <div class="em-fg"><label>Airline *</label>
          <select id="nc_air" style="height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;background:var(--white);cursor:pointer">
            ${airlineOpts.map(a=>`<option value="${a}" ${a===(curAir||'easyJet')?'selected':''}>${a}</option>`).join('')}
          </select>
        </div>
        <div class="em-fg"><label>Departure</label><input id="nc_dep" placeholder="Budapest (BUD)"></div>
        <div class="em-fg"><label>Arrival</label><input id="nc_arr" placeholder="London (LTN)"></div>
        <div class="em-fg"><label>Reason</label><input id="nc_rsn" placeholder="Delayed (195 min)"></div>
        <div class="em-fg"><label>Distance (km)</label><input type="number" id="nc_dist" placeholder="1450"></div>
      </div>
      <div class="em-section">Passengers</div>
      <div id="ncPaxList">
        <div class="nc-pax" data-idx="0" style="background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px">
          <div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">
            <span style="font-size:12px;font-weight:800;color:var(--orange)">Passenger 1</span>
            <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--orange);background:var(--orange-light);padding:2px 6px;border-radius:4px">Main</span>
          </div>
          <div class="em-grid">
            <div class="em-fg"><label>First Name *</label><input id="nc_fn_0" placeholder="John"></div>
            <div class="em-fg"><label>Last Name *</label><input id="nc_ln_0" placeholder="Doe"></div>
            <div class="em-fg"><label>Email</label><input id="nc_em_0" type="email" placeholder="john@example.com"></div>
            <div class="em-fg"><label>Seat</label><input id="nc_seat_0" placeholder="14A"></div>
          </div>
          <div style="margin-top:10px"><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--g400);margin-bottom:6px">Address</div>
          <div class="em-grid">
            <div class="em-fg full"><label>Street & Number</label><input id="nc_aS_0" placeholder="123 Main Street"></div>
            <div class="em-fg"><label>City</label><input id="nc_aC_0" placeholder="London"></div>
            <div class="em-fg"><label>Postal Code</label><input id="nc_aP_0" placeholder="E1 6AN"></div>
            <div class="em-fg full"><label>Country</label><input id="nc_aCo_0" placeholder="United Kingdom"></div>
          </div></div>
        </div>
      </div>
      <button onclick="ncAddPax()" style="margin-top:4px;width:100%;padding:10px;border-radius:8px;border:1.5px dashed var(--g300);background:var(--white);color:var(--g500);font-size:13px;font-weight:600;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;justify-content:center;gap:6px;transition:all .15s" onmouseover="this.style.borderColor='var(--orange)';this.style.color='var(--orange)';this.style.background='var(--orange-light)'" onmouseout="this.style.borderColor='var(--g300)';this.style.color='var(--g500)';this.style.background='var(--white)'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Passenger</button>
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" onclick="doAddCustomer()">Add Customer</button>
    </div></div>`;
  m.classList.add('show');
}

function ncAddPax(){
  const idx=ncPaxCount++;
  const list=document.getElementById('ncPaxList');
  const div=document.createElement('div');
  div.className='nc-pax';div.setAttribute('data-idx',idx);
  div.style.cssText='background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px';
  div.innerHTML=`
    <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
      <span style="font-size:14px;font-weight:800;color:var(--g500)">New Passenger</span>
      <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>
      <button onclick="this.closest('.nc-pax').remove()" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Remove</button>
    </div>
    <div class="em-grid">
      <div class="em-fg"><label>First Name *</label><input id="nc_fn_${idx}"></div>
      <div class="em-fg"><label>Last Name *</label><input id="nc_ln_${idx}"></div>
      <div class="em-fg"><label>Email</label><input id="nc_em_${idx}" type="email"></div>
      <div class="em-fg"><label>Seat</label><input id="nc_seat_${idx}"></div>
    </div>
    <div style="margin-top:10px"><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--g400);margin-bottom:6px">Address</div>
    <div class="em-grid">
      <div class="em-fg full"><label>Street & Number</label><input id="nc_aS_${idx}"></div>
      <div class="em-fg"><label>City</label><input id="nc_aC_${idx}"></div>
      <div class="em-fg"><label>Postal Code</label><input id="nc_aP_${idx}"></div>
      <div class="em-fg full"><label>Country</label><input id="nc_aCo_${idx}"></div>
    </div></div>`;
  list.appendChild(div);
  div.scrollIntoView({behavior:'smooth',block:'center'});
}

async function doAddCustomer(){
  const bk=document.getElementById('nc_bk').value.trim();
  if(!bk){toast('Booking ref is required');return}
  const flightData={
    flight_number:document.getElementById('nc_fl').value.trim(),
    flight_date:document.getElementById('nc_dt').value,
    departure:document.getElementById('nc_dep').value.trim(),
    arrival:document.getElementById('nc_arr').value.trim(),
    airline:document.getElementById('nc_air').value.trim()||'easyJet',
    reason:document.getElementById('nc_rsn').value.trim(),
    distance_km:document.getElementById('nc_dist').value||null
  };
  // Collect all passengers
  const paxCards=document.querySelectorAll('#ncPaxList .nc-pax');
  let first=true;let addedCount=0;let mainId=null;
  for(const card of paxCards){
    const idx=card.getAttribute('data-idx');
    const fn=(document.getElementById('nc_fn_'+idx)?.value||'').trim();
    const ln=(document.getElementById('nc_ln_'+idx)?.value||'').trim();
    if(!fn||!ln){if(first){toast('First passenger name required');return}continue;}
    const em=(document.getElementById('nc_em_'+idx)?.value||'').trim();
    const aS=(document.getElementById('nc_aS_'+idx)?.value||'').trim();
    const aC=(document.getElementById('nc_aC_'+idx)?.value||'').trim();
    const aP=(document.getElementById('nc_aP_'+idx)?.value||'').trim();
    const aCo=(document.getElementById('nc_aCo_'+idx)?.value||'').trim();
    if(first){
      const payload={first_name:fn,last_name:ln,booking_ref:bk,email:em,...flightData};
      const res=await fetch('?action=add_customer',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
      const j=await res.json();
      if(!j.ok){toast(j.message||'Failed');return}
      mainId=j.id;
      // Save address for main passenger
      if(aS||aC||aP||aCo){
        const addrFields={address_street:aS,address_city:aC,address_postal:aP,address_country:aCo};
        for(const[k,v] of Object.entries(addrFields)){
          if(v)await fetch('?action=update_field',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:mainId,field:k,value:v})});
        }
      }
      addedCount++;first=false;
    }else{
      const res=await fetch('?action=add_sub_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({booking_ref:bk,first_name:fn,last_name:ln,email:em})});
      const j=await res.json();
      if(j.ok){
        // Save address for sub passenger
        if((aS||aC||aP||aCo)&&j.id){
          const addrFields={address_street:aS,address_city:aC,address_postal:aP,address_country:aCo};
          for(const[k,v] of Object.entries(addrFields)){
            if(v)await fetch('?action=update_field',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:j.id,field:k,value:v})});
          }
        }
        addedCount++;
      }
    }
  }
  closeEdit();toast(addedCount+' passenger(s) added!');
  setTimeout(()=>location.reload(),500);
}

let editNewPaxIdx=100;
function addPaxCardInEdit(bk){
  const idx=editNewPaxIdx++;
  const list=document.getElementById('editPaxList');
  const div=document.createElement('div');
  div.id='paxCard_new_'+idx;
  div.className='newPaxCard';
  div.setAttribute('data-bk',bk);
  div.setAttribute('data-idx',idx);
  div.style.cssText='background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px';
  div.innerHTML=`
    <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
      <span style="font-size:14px;font-weight:800;color:var(--g500)">New Passenger</span>
      <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>
      <button onclick="this.closest('.newPaxCard').remove()" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Remove</button>
    </div>
    <div class="em-grid">
      <div class="em-fg"><label>First Name *</label><input id="ef_newf_${idx}"></div>
      <div class="em-fg"><label>Last Name *</label><input id="ef_newl_${idx}"></div>
      <div class="em-fg"><label>Email</label><input id="ef_newem_${idx}" type="email"></div>
      <div class="em-fg"><label>Seat</label><input id="ef_newseat_${idx}"></div>
    </div>
    <div style="margin-top:10px"><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--g400);margin-bottom:6px">Address</div>
    <div class="em-grid">
      <div class="em-fg full"><label>Street & Number</label><input id="ef_newaS_${idx}"></div>
      <div class="em-fg"><label>City</label><input id="ef_newaC_${idx}"></div>
      <div class="em-fg"><label>Postal Code</label><input id="ef_newaP_${idx}"></div>
      <div class="em-fg full"><label>Country</label><input id="ef_newaCo_${idx}"></div>
    </div></div>`;
  list.appendChild(div);
  div.scrollIntoView({behavior:'smooth',block:'center'});
}
async function delPaxInEdit(id){
  const r=D.find(x=>x.id==id);if(!r)return;
  if(!confirm('Delete '+r.f+' '+r.l+'? This removes all their data and documents.'))return;
  await fetch('?action=delete_customer',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
  const idx=D.findIndex(x=>x.id==id);if(idx>-1)D.splice(idx,1);
  const card=document.getElementById('paxCard_'+id);if(card)card.remove();
  uS();filt();toast(r.f+' '+r.l+' deleted');
}
async function saveGroupEdit(bk,fl,dt){
  const grp=D.filter(x=>x.bk===bk && x.fl===fl && x.dt===dt);if(!grp.length)return;
  // Shared flight fields
  const shared={booking_ref:document.getElementById('ef_bk').value,flight_number:document.getElementById('ef_fl').value,flight_date:document.getElementById('ef_dt').value,departure:document.getElementById('ef_dep').value,arrival:document.getElementById('ef_arr').value,reason:document.getElementById('ef_rsn').value,distance_km:document.getElementById('ef_dist').value};
  const promises=[];
  grp.forEach((r,i)=>{
    const pf={customer_id:document.getElementById('ef_cid_'+i).value,first_name:document.getElementById('ef_f_'+i).value,last_name:document.getElementById('ef_l_'+i).value,airline:document.getElementById('ef_air_'+i).value,email:document.getElementById('ef_em_'+i).value,seat:document.getElementById('ef_seat_'+i).value,address_street:document.getElementById('ef_aS_'+i).value,address_city:document.getElementById('ef_aC_'+i).value,address_postal:document.getElementById('ef_aP_'+i).value,address_country:document.getElementById('ef_aCo_'+i).value};
    const all={...shared,...pf};
    Object.entries(all).forEach(([k,v])=>{promises.push(fetch('?action=update_field',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id,field:k,value:v})}))});
    r.cid=pf.customer_id;r.f=pf.first_name;r.l=pf.last_name;r.air=pf.airline;r.em=pf.email;r.seat=pf.seat;r.aS=pf.address_street;r.aC=pf.address_city;r.aP=pf.address_postal;r.aCo=pf.address_country;
    r.bk=shared.booking_ref;r.fl=shared.flight_number;r.dt=shared.flight_date;r.dep=shared.departure;r.arr=shared.arrival;r.rsn=shared.reason;r.dist=parseInt(shared.distance_km)||0;
  });
  // Save new passengers added inline
  const newCards=document.querySelectorAll('.newPaxCard');
  let newPaxCount=0;
  for(const card of newCards){
    const idx=card.getAttribute('data-idx');
    const fn=(document.getElementById('ef_newf_'+idx)?.value||'').trim();
    const ln=(document.getElementById('ef_newl_'+idx)?.value||'').trim();
    const em=(document.getElementById('ef_newem_'+idx)?.value||'').trim();
    if(!fn||!ln)continue;
    promises.push(fetch('?action=add_sub_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({booking_ref:shared.booking_ref||bk,first_name:fn,last_name:ln,email:em})}));
    newPaxCount++;
  }
  await Promise.all(promises);
  closeEdit();uS();filt();
  if(newPaxCount>0){toast('Saved + '+newPaxCount+' new passenger(s) added!');setTimeout(()=>location.reload(),500)}
  else{toast('Booking updated!')}
}

let curPage=1;const PER_PAGE=50;let selected=new Set();let filteredData=[];

// Clickable copy wrapper
function k(v){if(!v)return'';const e=String(v).replace(/'/g,"\\'");return`<span class="cp" onclick="cp('${e}')">${v}</span>`}

// Selection
function toggleAll(checked){const pageData=getPageData();pageData.forEach(r=>{if(checked)selected.add(r.id);else selected.delete(r.id)});rT(getPageData());updBulk()}
function selectAllFiltered(){filteredData.forEach(r=>{selected.add(r.id)});rT(getPageData());updBulk()}
function toggleSel(id,checked){if(checked)selected.add(id);else selected.delete(id);updBulk()}
function clearSel(){selected.clear();document.getElementById('selAll').checked=false;rT(getPageData());updBulk()}
function updBulk(){const bar=document.getElementById('bulkBar');const cnt=selected.size;document.getElementById('bbCount').textContent=cnt+' selected';bar.classList.toggle('show',cnt>0);const total=filteredData.length;document.getElementById('bbSelAll').textContent=cnt<total?'Select All ('+total+')':'All Selected'}

// Bulk send
// Get all customer IDs in booking groups of selected main passengers
function getSelectedAll(){
  const keys=new Set();
  selected.forEach(id=>{const r=D.find(x=>x.id==id);if(r)keys.add(r.bk+'|'+r.fl+'|'+r.dt)});
  return D.filter(r=>keys.has(r.bk+'|'+r.fl+'|'+r.dt));
}

// Custom confirm modal (replaces ugly browser confirm)
let _pendingCallback=null;
function confirmAction(title,msg,btnText,btnClass,callback){
  _pendingCallback=callback;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:420px">
    <div class="em-head"><h3>${title}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body"><p style="font-size:14px;color:var(--g500);line-height:1.6">${msg}</p></div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" style="background:var(${btnClass})" onclick="runPending()">${btnText}</button>
    </div></div>`;
  m.classList.add('show')}
async function runPending(){closeEdit();if(_pendingCallback){const cb=_pendingCallback;_pendingCallback=null;await cb()}}

async function bulkSetTemplate(){
  if(selected.size===0)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:420px">
    <div class="em-head"><h3>Set Mail Template</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <p style="font-size:13px;color:var(--g500);margin-bottom:12px">Select mail template for <strong>${getSelectedAll().length}</strong> customers:</p>
      <label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600" onmouseover="this.style.background='var(--g50)'" onmouseout="this.style.background=''">
        <input type="radio" name="btpl" value="" style="accent-color:var(--orange)"> <span style="color:var(--g400)">— None (clear)</span>
      </label>
      ${tpls.map(t=>`<label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600" onmouseover="this.style.background='var(--g50)'" onmouseout="this.style.background=''">
        <input type="radio" name="btpl" value="${t.slug}" style="accent-color:var(--orange)"> ${t.label}
      </label>`).join('')}
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" onclick="doBulkSetTemplate()">Apply</button>
    </div></div>`;
  m.classList.add('show')}

async function doBulkSetTemplate(){
  const radio=document.querySelector('input[name=btpl]:checked');
  if(!radio){toast('Select a template');return}
  const slug=radio.value;closeEdit();
  const all=getSelectedAll();
  // Set template on main passengers (mail template is set on main, sub-passengers inherit)
  const mains=all.filter(r=>r.main||(all.filter(x=>x.bk===r.bk).length===1));
  mains.forEach(r=>{
    r.mt=slug;
    // Also set on all co-passengers in same booking
    D.filter(x=>x.bk===r.bk).forEach(x=>{x.mt=slug});
  });
  selected.clear();document.getElementById('selAll').checked=false;updBulk();filt();
  const tplLabel=slug?(tpls.find(t=>t.slug===slug)?.label||slug):'cleared';
  toast(mains.length+' customers set to "'+tplLabel+'"')}

async function bulkSend(){
  const all=getSelectedAll();
  const items=[];
  all.forEach(r=>{
    // Use main passenger's template for sub-passengers too
    const main=D.find(x=>x.bk===r.bk&&x.main)||r;
    if(main.mt)items.push({id:r.id,template:main.mt})
  });
  if(items.length===0){toast('Set mail templates first');return}
  // Check for missing emails
  const noEmail=all.filter(r=>!r.em && r.main);
  const emailWarning=noEmail.length>0?`<br><br><span style="color:var(--red);font-size:12px">⚠ ${noEmail.length} customer(s) have no email address and will be skipped.</span>`:'';
  confirmAction('Send Mails',`Send <strong>${items.length}</strong> emails via SendGrid to selected customers?${emailWarning}`,'Send Mails','--orange',async()=>{
    const res=await fetch('?action=bulk_send_mail',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ids:items})});
    const j=await res.json();
    if(j.ok){
      items.forEach(item=>{const r=D.find(x=>x.id==item.id);if(r){r.ms=new Date().toISOString();r.mts=item.template;r.mt=item.template;delete histCache['hist_'+r.id];if(item.template==='claim_submit'){r.st='form_sent';r.rmActive=1}else if(item.template==='hibas_id')r.st='bad_id_sent'}});
      rmLoaded=false;selected.clear();document.getElementById('selAll').checked=false;updBulk();uS();filt();
      let msg=j.sent+' mails sent!';
      if(j.failed>0)msg+=' ('+j.failed+' failed)';
      toast(msg)}
  })
}

async function bulkStatus(){
  if(selected.size===0)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:420px">
    <div class="em-head"><h3>Change Status</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <p style="font-size:13px;color:var(--g500);margin-bottom:12px">Select new status for <strong>${getSelectedAll().length}</strong> customers:</p>
      ${STS.map(s=>`<label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600" onmouseover="this.style.background='var(--g50)'" onmouseout="this.style.background=''">
        <input type="radio" name="bst" value="${s}" style="accent-color:var(--orange)"> ${SLB[s]}
      </label>`).join('')}
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" onclick="doBulkStatus()">Apply</button>
    </div></div>`;
  m.classList.add('show')}

async function doBulkStatus(){
  const radio=document.querySelector('input[name=bst]:checked');
  if(!radio){toast('Select a status');return}
  const status=radio.value;closeEdit();
  const all=getSelectedAll();
  const promises=[];
  all.forEach(r=>{
    promises.push(fetch('?action=update_status',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id,status:status})}));
    r.st=status;delete histCache['hist_'+r.id]
  });
  await Promise.all(promises);
  selected.clear();document.getElementById('selAll').checked=false;updBulk();uS();filt();toast(all.length+' customers updated!')
}

async function bulkGenAssignment(){
  if(selected.size===0)return;
  const all=getSelectedAll();
  const withAddr=all.filter(r=>r.aS||r.aC);
  if(withAddr.length===0){toast('No selected customers have addresses');return}
  confirmAction('Generate Assignments',`Generate assignment PDFs for <strong>${withAddr.length}</strong> customers?`,'Generate','--purple',async()=>{
    let ok=0;
    for(const r of withAddr){
      try{
        const res=await fetch('?action=generate_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id})});
        const j=await res.json();
        if(j.ok){r.asF=j.filename;r.asP=j.path;ok++}
      }catch(e){}
    }
    selected.clear();document.getElementById('selAll').checked=false;updBulk();filt();toast(ok+' assignments generated!')
  })
}

function bulkExport(){
  const all=getSelectedAll();
  if(all.length===0){toast('Select customers first');return}
  // Deduplicate by booking+flight+date (one line per unique flight)
  const seen=new Set();
  const lines=[];
  all.forEach(r=>{
    const key=r.dt+'|'+r.fl+'|'+r.dep+'|'+r.arr;
    if(seen.has(key))return;
    seen.add(key);
    // Extract IATA codes from "Budapest (BUD)" format
    const depIata=(r.dep.match(/\(([A-Z]{3})\)/)||['',''])[1]||r.dep;
    const arrIata=(r.arr.match(/\(([A-Z]{3})\)/)||['',''])[1]||r.arr;
    // Format reason: number → "cancelled" or delay minutes, etc.
    let reason=r.rsn||'';
    if(/^\d+$/.test(reason)){reason=reason+' min delay'}
    else if(reason.toLowerCase().includes('cancel')){reason='cancelled'}
    else{reason=reason.toLowerCase()}
    // Format: 2023-07-29|U2 3540|cancelled|CTA|MXP
    // Add space in flight number if missing (EZY1234 → EZY 1234, U21234 → U2 1234)
    let fl=r.fl||'';
    if(/^[A-Z]{2,3}\d+$/.test(fl)){fl=fl.replace(/^([A-Z]{2,3})(\d+)$/,'$1 $2')}
    lines.push(r.dt+'|'+fl+'|'+reason+'|'+depIata+'|'+arrIata);
  });
  if(lines.length===0){toast('No flight data to export');return}
  const txt=lines.join('\n');
  // Download as .txt
  const blob=new Blob([txt],{type:'text/plain'});
  const url=URL.createObjectURL(blob);
  const a=document.createElement('a');
  a.href=url;a.download='export_flights_'+new Date().toISOString().slice(0,10)+'.txt';
  document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);
  toast(lines.length+' flights exported');
}

function bulkExportCSV(){
  const all=getSelectedAll();
  if(all.length===0){toast('Select customers first');return}
  // CSV header — same columns as import CSV expects
  const header=['Booking Number','Flight Number','Date','Departure','Arrival','First Name','Last Name','Email','Address','City','ZIP','Country','Seat','Distance (km)','Reason','Passenger Type'];
  const rows=[header.join(',')];
  all.forEach(r=>{
    const csvVal=v=>{
      v=String(v||'');
      if(v.includes(',')||v.includes('"')||v.includes('\n')){return'"'+v.replace(/"/g,'""')+'"'}
      return v;
    };
    rows.push([
      csvVal(r.bk),
      csvVal(r.fl),
      csvVal(r.dt),
      csvVal(r.dep),
      csvVal(r.arr),
      csvVal(r.f),
      csvVal(r.l),
      csvVal(r.em),
      csvVal(r.aS),
      csvVal(r.aC),
      csvVal(r.aP),
      csvVal(r.aCo),
      csvVal(r.seat),
      csvVal(r.dist||''),
      csvVal(r.rsn),
      csvVal(r.main?'Main':'Sub')
    ].join(','));
  });
  const csv='\uFEFF'+rows.join('\n'); // BOM for Excel UTF-8
  const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});
  const url=URL.createObjectURL(blob);
  const a=document.createElement('a');
  a.href=url;a.download='export_customers_'+new Date().toISOString().slice(0,10)+'.csv';
  document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);
  toast(all.length+' customers exported to CSV');
}

async function bulkDelete(){
  if(selected.size===0)return;
  const all=getSelectedAll();
  confirmAction('Delete Customers',`<span style="color:var(--red);font-weight:700">Permanently delete ${all.length} customers?</span><br><br>This will remove all their data, documents, and history. This cannot be undone.`,'Delete','--red',async()=>{
    const ids=all.map(r=>r.id);
    await fetch('?action=bulk_delete',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ids:ids})});
    all.forEach(r=>{const idx=D.findIndex(x=>x.id==r.id);if(idx>-1)D.splice(idx,1)});
    selected.clear();document.getElementById('selAll').checked=false;updBulk();uS();filt();toast(all.length+' customers deleted!')
  })
}

// Pagination
function getPageData(){const start=(curPage-1)*PER_PAGE;return filteredData.slice(start,start+PER_PAGE)}
function renderPag(total){
  const pages=Math.ceil(total/PER_PAGE);const area=document.getElementById('pagArea');
  if(pages<=1){area.innerHTML=`<span class="pag-info">${total} records</span>`;return}
  let h=`<button class="pag-btn" onclick="goPage(${curPage-1})" ${curPage<=1?'disabled':''}>&lt;</button>`;
  const start=Math.max(1,curPage-3);const end=Math.min(pages,curPage+3);
  if(start>1)h+=`<button class="pag-btn" onclick="goPage(1)">1</button>`;
  if(start>2)h+=`<span class="pag-info">...</span>`;
  for(let i=start;i<=end;i++)h+=`<button class="pag-btn ${i===curPage?'act':''}" onclick="goPage(${i})">${i}</button>`;
  if(end<pages-1)h+=`<span class="pag-info">...</span>`;
  if(end<pages)h+=`<button class="pag-btn" onclick="goPage(${pages})">${pages}</button>`;
  h+=`<button class="pag-btn" onclick="goPage(${curPage+1})" ${curPage>=pages?'disabled':''}>&gt;</button>`;
  h+=`<span class="pag-info">${(curPage-1)*PER_PAGE+1}–${Math.min(curPage*PER_PAGE,total)} of ${total}</span>`;
  area.innerHTML=h}
function goPage(p){const pages=Math.ceil(filteredData.length/PER_PAGE);if(p<1||p>pages)return;curPage=p;rT(getPageData());renderPag(filteredData.length);window.scrollTo({top:document.querySelector('.tc').offsetTop-80,behavior:'smooth'})}

function rT(data){const tb=document.getElementById('tB');const gr={};data.forEach(r=>{const gk=r.bk+'|'+r.fl+'|'+r.dt;if(!gr[gk])gr[gk]=[];gr[gk].push(r)});let h='';const seen=new Set();
data.forEach(row=>{if(seen.has(row.id))return;const gk=row.bk+'|'+row.fl+'|'+row.dt;const g=gr[gk];const ig=g.length>1;const cu=genUrl(row.bk,g);
g.forEach((r,i)=>{seen.add(r.id);const im=r.main;const is=ig&&!im;const il=i===g.length-1;let cl=ig?(im?'mr':'sr'):'solo';if(ig&&il)cl+=' gl';
const eu=cu.replace(/'/g,"\\'");const lc=(im||!ig)?`<span style="display:flex;align-items:center;gap:3px;white-space:nowrap"><a href="${cu}" target="_blank" class="lnk-b">Open</a><button class="lnk-c" onclick="event.preventDefault();cp('${eu}')">📋</button></span>`:'';
const addr=[r.aS,r.aP,r.aC,r.aCo].filter(Boolean).join(', ');
const showCb=(im||!ig);
const trStyle=
  !ig ? 'border-top:6px solid rgba(255,107,53,0.28);border-bottom:6px solid rgba(255,107,53,0.28);background:var(--white)' :
  (im) ? 'border-top:6px solid rgba(255,107,53,0.28);background:var(--white)' :
  (il) ? 'border-bottom:6px solid rgba(255,107,53,0.28);background:#FAFBFC' :
  'background:#FAFBFC';
h+=`<tr class="${cl}" style="${trStyle}">`;
h+=`<td>${showCb?`<input type="checkbox" class="row-cb" ${selected.has(r.id)?'checked':''} onchange="toggleSel(${r.id},this.checked)">`:''}</td>`;
h+=`<td class="cid">${im||!ig?`<span class="cid-t cp" onclick="cp('${r.cid}')">${r.cid}</span>`:`<span class="cid-t cp" onclick="cp('${r.cid}')" style="opacity:0.35">${r.cid}</span>`}</td>`;
h+=`<td>${lc}</td>`;
h+=`<td class="nm">${is?'<span class=sc-c>└</span>':''}${k(r.f)}${im&&ig?'<span class=mbdg>Main</span>':''}</td>`;
h+=`<td class="nm">${is?'<span class=sc-c>└</span>':''}${k(r.l)}</td>`;
h+=`<td style="font-size:11px;color:var(--g500)">${k(r.em)}</td>`;
h+=`<td class="addr" title="${addr}"><span class="cp" onclick="cp('${addr.replace(/'/g,"\\'")}')">${r.aCo||r.aC||r.aS||''}</span></td>`;
h+=`<td class="bk">${is?'':k(r.bk)}</td>`;
h+=`<td class="fl">${is?'':(() => {
  const fn=r.fl.toUpperCase().replace(/\s+/g,'');
  const bn=ezBaseNum(fn);
  if(bn){
    const aliases=['U2'+bn,'EZY'+bn,'EZS'+bn,'EJU'+bn].filter(a=>a!==fn);
    const matchedAlias=aliases.find(a=>flMap[a+'_'+r.dt]);
    const other=matchedAlias||aliases[0];
    if(other&&other!==fn)return k(fn)+`<div style="font-size:9px;color:var(--g400)">${other}</div>`;
  }
  return k(fn);
})()}</td>`;
h+=`<td>${k(r.seat)}</td>`;
h+=`<td class="dt">${is?'':k(fD(r.dt))}</td>`;
h+=`<td>${is?'':k(r.dep)}</td>`;
h+=`<td>${is?'':k(r.arr)}</td>`;
h+=`<td>${is?'':(r.rsn?`<span class="rtag ${rC(r.rsn)} cp" onclick="cp('${fmtReason(r.rsn).replace(/'/g,"\\'")}')">${fmtReason(r.rsn)}</span>`:'')}</td>`;
h+=`<td class="dst">${is?'':(r.dist?k(r.dist.toLocaleString()+' km'):'')}</td>`;
const cd=calcDist(r.dep||((ig?(g.find(x=>x.main)||g[0]):r).dep),r.arr||((ig?(g.find(x=>x.main)||g[0]):r).arr));
h+=`<td class="dst">${is?'':(cd?k(Math.round(cd).toLocaleString()+' km'):'')}</td>`;
const compKm=cd||r.dist||(ig?(g.find(x=>x.main)||g[0]).dist:0)||0;
h+=`<td>${compKm?`<span class="comp cp" onclick="cp('${calcComp(compKm)}')">${calcComp(compKm)}</span>`:''}</td>`;
const ahVal=r.ah;
const ahNote=r.ahNote;
const ahTip=ahNote?ahNote.replace(/"/g,'&quot;'):'';
h+=`<td>${ahVal==='ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#ECFDF5;color:#059669;cursor:default" title="${ahTip}">ELIGIBLE</span>`:ahVal==='NOT ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#FEF2F2;color:#DC2626;cursor:default" title="${ahTip}">NOT ELIGIBLE</span>`:''}</td>`;
const srcVal=r.ahSrc;
h+=`<td>${srcVal?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:600;background:${srcVal==='SELECTED'?'#EFF6FF':'#FDF4FF'};color:${srcVal==='SELECTED'?'#2563EB':'#9333EA'}">${srcVal}</span>`:''}</td>`;
h+=`<td>${docC(r.id,'id',r.idF,r.idP,r.idV)}</td>`;
h+=`<td>${docC(r.id,'travel',r.trF,r.trP,r.trV)}</td>`;
h+=`<td>${asC(r.id,r.asF,r.asP,!!(r.aS||r.aC))}</td>`;
h+=`<td>${(im||!ig)?mailTplSel(r.id,r.mt):''}</td>`;
h+=`<td>${mailC(r.id,r.ms,r.mt,r.mts,im||!ig,ig)}</td>`;
h+=`<td>${(im||!ig)?`<button class="prvw-btn" onclick="previewClaimMail(${r.id})" title="Preview claim notification email"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>`:''}</td>`;
h+=`<td>${is?'':stBdg(r.id,r.st)}</td>`;
h+=`<td>${notesC(r.id,r.notes,im||!ig)}</td>`;
h+=`<td class="dt" ${is?'':`onmouseenter="showHist(event,${r.id})" onmouseleave="hideHist()" style="cursor:pointer"`}>${is?'':k(fDT(r.upd))}</td>`;
h+=`<td>${(im||!ig)?`<button class="edit-btn" onclick="openEdit('${r.bk.replace(/'/g,"\\'")}','${(r.fl||'').replace(/'/g,"\\'")}','${r.dt||''}')"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg></button>`:''}</td>`;
h+=`</tr>`})});
tb.innerHTML=h;document.getElementById('rCnt').textContent=filteredData.length}

// Column sorting
let sortKey='',sortDir=0; // 0=none, 1=asc, -1=desc
function sortCol(key){
  if(sortKey===key){sortDir=sortDir===1?-1:sortDir===-1?0:1}
  else{sortKey=key;sortDir=1}
  // Update header visuals
  document.querySelectorAll('th.srt').forEach(th=>{th.classList.remove('asc','desc')});
  if(sortDir!==0){
    const thEls=document.querySelectorAll('th.srt');
    thEls.forEach(th=>{if(th.getAttribute('onclick')?.includes("'"+key+"'"))th.classList.add(sortDir===1?'asc':'desc')});
  }
  document.getElementById('sortResetBtn').style.display=sortDir?'':'none';
  filt();
}
function resetSort(){sortKey='';sortDir=0;document.querySelectorAll('th.srt').forEach(th=>{th.classList.remove('asc','desc')});document.getElementById('sortResetBtn').style.display='none';filt()}
function applySortToData(data){
  if(!sortKey||!sortDir)return data;
  const sorted=[...data];
  sorted.sort((a,b)=>{
    let va,vb;
    if(sortKey==='comp'){va=getCompKm(a);vb=getCompKm(b)}
    else if(sortKey==='dist'){va=a.dist||0;vb=b.dist||0}
    else if(sortKey==='dt'||sortKey==='upd'){va=a[sortKey]||'';vb=b[sortKey]||''}
    else{va=(a[sortKey]||'').toString().toLowerCase();vb=(b[sortKey]||'').toString().toLowerCase()}
    if(typeof va==='number'&&typeof vb==='number')return(va-vb)*sortDir;
    if(va<vb)return-1*sortDir;if(va>vb)return 1*sortDir;return 0;
  });
  return sorted;
}

function filt(){const q=document.getElementById('sIn').value.toLowerCase();let f=gD();
  // Inline select filters
  const stF=document.getElementById('ejStatusFilter')?.value||'';
  const rsnF=document.getElementById('ejReasonFilter')?.value||'';
  const idF=document.getElementById('ejIdFilter')?.value||'';
  if(stF)f=f.filter(r=>r.st===stF);
  if(rsnF==='delay')f=f.filter(r=>r.rsn&&/^\d+$/.test(r.rsn.trim()));
  if(rsnF==='cancel')f=f.filter(r=>r.rsn&&r.rsn.toLowerCase().includes('cancel'));
  if(rsnF==='none')f=f.filter(r=>!r.rsn);
  if(idF==='yes')f=f.filter(r=>r.idF);
  if(idF==='no')f=f.filter(r=>!r.idF);
  if(q){const mb=new Set();f.forEach(r=>{if(r.f.toLowerCase().includes(q)||r.l.toLowerCase().includes(q)||r.bk.toLowerCase().includes(q)||r.fl.toLowerCase().includes(q)||r.dep.toLowerCase().includes(q)||r.arr.toLowerCase().includes(q)||(r.cid&&r.cid.toLowerCase().includes(q)))mb.add(r.bk)});f=f.filter(r=>mb.has(r.bk))}f=applySortToData(f);filteredData=f;curPage=1;rT(getPageData());renderPag(f.length)}
const FILTER_CATS={
  'Status':{items:[
    {key:'doc_needed',label:'Adatbekérő kiküldeni',color:'var(--orange)'},
    {key:'form_sent',label:'Adatbekérő kiküldve',color:'var(--g400)'},
    {key:'bad_id_sent',label:'Hibás ID, kiküldve',color:'var(--red)'},
    {key:'form_send',label:'Claim beadni',color:'var(--orange)'},
    {key:'beadva_sajat',label:'Beadva Saját F.',color:'#D97706'},
    {key:'beadva_assign',label:'Beadva Assign.',color:'#3B82F6'},
    {key:'beadva_airhelp',label:'Beadva Airhelp',color:'#8B5CF6'},
    {key:'jovahagyva',label:'Jóváhagyva',color:'#059669'},
    {key:'kifizetve',label:'Kifizetve',color:'#2563EB'},
    {key:'elutasitva',label:'Elutasítva',color:'#DC2626'}
  ]},
  'AirHelp':{items:[
    {key:'ah_eligible',label:'Eligible',color:'#059669'},
    {key:'ah_none',label:'No data',color:'var(--g300)'}
  ]},
  'Source':{items:[
    {key:'src_selected',label:'Selected',color:'#2563EB'},
    {key:'src_manual',label:'Manual',color:'#9333EA'},
    {key:'src_none',label:'No data',color:'var(--g300)'}
  ]},
  'Reason':{items:[
    {key:'rsn_delay',label:'Delayed',color:'var(--orange)'},
    {key:'rsn_cancel',label:'Cancelled',color:'#DC2626'},
    {key:'rsn_none',label:'No reason',color:'var(--g300)'}
  ]},
  'Beadva':{items:[
    {key:'cm_assignment',label:'Assignment',color:'#3B82F6'},
    {key:'cm_sajat',label:'Saját fiók',color:'#F59E0B'},
    {key:'cm_airhelp',label:'Airhelp',color:'#8B5CF6'},
    {key:'cm_none',label:'Nincs megadva',color:'var(--g300)'}
  ]}
};
let activeFilters={};
function getFilterCount(){let c=0;Object.values(activeFilters).forEach(a=>{c+=a.length});return c}
function getFilterLabel(){
  const parts=[];
  Object.entries(activeFilters).forEach(([cat,keys])=>{
    if(!keys.length)return;
    const c=FILTER_CATS[cat];
    const labels=keys.map(k=>{const it=c.items.find(i=>i.key===k);return it?it.label:k});
    parts.push(labels.join(', '));
  });
  return parts.join(' + ')||'All';
}
function togSF(){const dd=document.getElementById('sfDD');dd.classList.toggle('show');if(dd.classList.contains('show'))renderFilterL1()}
function renderFilterL1(){
  let h='<div class="sfi" onclick="clearFilters()" style="font-weight:600"><span class="dot" style="background:var(--g400)"></span>Clear All Filters</div>';
  h+='<div style="border-top:1px solid var(--g200);margin:4px 0"></div>';
  Object.keys(FILTER_CATS).forEach(cat=>{
    const cnt=(activeFilters[cat]||[]).length;
    h+=`<div class="sfi" onclick="event.stopPropagation();renderFilterL2('${cat}')"><span style="flex:1">${cat}${cnt?` <span style="background:var(--orange);color:#fff;border-radius:10px;padding:1px 6px;font-size:9px;font-weight:700;margin-left:4px">${cnt}</span>`:''}</span><span style="color:var(--g400);font-size:10px">▸</span></div>`;
  });
  document.getElementById('sfDD').innerHTML=h;
}
function renderFilterL2(cat){
  const c=FILTER_CATS[cat];
  const sel=activeFilters[cat]||[];
  let h=`<div class="sfi" onclick="event.stopPropagation();renderFilterL1()" style="color:var(--g400);font-size:11px">◂ ${cat}</div>`;
  h+='<div style="border-top:1px solid var(--g200);margin:4px 0"></div>';
  c.items.forEach(it=>{
    const checked=sel.includes(it.key);
    h+=`<div class="sfi" onclick="event.stopPropagation();toggleFilter('${cat}','${it.key}');" style="cursor:pointer">
      <input type="checkbox" ${checked?'checked':''} style="accent-color:var(--orange);margin-right:6px;pointer-events:none">
      <span class="dot" style="background:${it.color}"></span>${it.label}</div>`;
  });
  document.getElementById('sfDD').innerHTML=h;
}
function toggleFilter(cat,key){
  if(!activeFilters[cat])activeFilters[cat]=[];
  const idx=activeFilters[cat].indexOf(key);
  if(idx>-1)activeFilters[cat].splice(idx,1);else activeFilters[cat].push(key);
  if(!activeFilters[cat].length)delete activeFilters[cat];
  updateFilterBtn();
  renderFilterL2(cat);
  filt();
}
function clearFilters(){
  activeFilters={};
  updateFilterBtn();
  document.getElementById('sfDD').classList.remove('show');
  filt();
}
function updateFilterBtn(){
  const cnt=getFilterCount();
  const label=getFilterLabel();
  document.getElementById('sfLbl').textContent=cnt?label:'All';
  document.getElementById('sfBtn').classList.toggle('act',cnt>0);
}

// Templates page

// Remarketing — 5-step inline display
const RM_STEPS=[{step:1,days:1,label:'1 napos'},{step:2,days:3,label:'3 napos'},{step:3,days:6,label:'6 napos'},{step:4,days:9,label:'9 napos'},{step:5,days:12,label:'12 napos'}];
const rmCache={};

function rmBdg(r){
  if(!r.main)return'';
  const cid='rm_'+r.id;
  if(r.rmSent&&rmCache[cid]===undefined){setTimeout(()=>loadRmLogs(r.id),0)}
  const logs=rmCache[cid]||[];
  return rmRender(r,logs);
}

function rmRender(r,logs){
  const logByStep={};(logs||[]).forEach(l=>{if(l.send_ok==1)logByStep[l.step]=l});
  let h='<div style="display:flex;flex-direction:column;gap:3px;font-size:10px;line-height:1.3;white-space:nowrap">';
  RM_STEPS.forEach(s=>{
    const log=logByStep[s.step];
    if(log){
      const dt=log.sent_at?fDT(log.sent_at):'';
      h+=`<div style="color:#059669;font-weight:700;cursor:default" title="Kiküldve: ${dt}">✓ ${s.label}</div>`;
    }else{
      let tip='Még nem küldve';
      if(r.rmSent&&r.rmActive){
        const exp=new Date(r.rmSent);exp.setDate(exp.getDate()+s.days);
        tip='Várható: '+fD(exp.toISOString().slice(0,10));
      }else if(r.rmSent&&!r.rmActive){
        tip=r.idF?'Leállítva — ID feltöltve':'Leállítva';
      }
      h+=`<div style="color:#C8CDD5;cursor:default" title="${tip}">○ ${s.label}</div>`;
    }
  });
  h+='</div>';
  return h;
}

async function loadRmLogs(id){
  const cid='rm_'+id;
  if(rmCache[cid])return;
  try{
    const res=await fetch('?action=get_remarketing_logs',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
    const j=await res.json();
    rmCache[cid]=j.ok?j.logs:[];
  }catch(e){rmCache[cid]=[];}
  // Re-render just this cell
  const r=D.find(x=>x.id==id);
  if(!r)return;
  const cells=document.querySelectorAll(`[data-rmid="${id}"]`);
  cells.forEach(cell=>{cell.innerHTML=rmRender(r,rmCache[cid])});
}

// Future Flights
const FUT_PER_PAGE=50;
let futCurPage=1;
let futSortDir=1; // 1=asc, -1=desc
function sortFuture(key){
  futSortDir=futSortDir===1?-1:1;
  // Update header arrow
  document.querySelectorAll('#page_future th.srt').forEach(th=>{th.classList.remove('asc','desc')});
  if(futSortDir===1)event.target.classList.add('asc');else event.target.classList.add('desc');
  renderFuture();
}
function renderFuture(){
  const q=(document.getElementById('futSearch')?.value||'').toLowerCase();
  const airFilter=document.getElementById('futAirFilter')?.value||'';
  // Populate airline filter
  const airSel=document.getElementById('futAirFilter');
  const airlines=[...new Set(futureData.map(f=>f.airline).filter(Boolean))].sort();
  const curFutAir=airSel.value;
  airSel.innerHTML='<option value="">All Airlines</option>'+airlines.map(a=>`<option value="${a}" ${a===curFutAir?'selected':''}>${a}</option>`).join('');
  let data=[...futureData];
  if(airFilter)data=data.filter(f=>f.airline===airFilter);
  if(q)data=data.filter(f=>(f.flight_number||'').toLowerCase().includes(q)||(f.departure||'').toLowerCase().includes(q)||(f.arrival||'').toLowerCase().includes(q)||(f.departure_iata||'').toLowerCase().includes(q)||(f.arrival_iata||'').toLowerCase().includes(q));
  // Sort by date
  data.sort((a,b)=>{const da=a.flight_date||'';const db=b.flight_date||'';return da<db?-1*futSortDir:da>db?1*futSortDir:0});
  document.getElementById('futCnt').textContent=data.length+' flights';
  const pages=Math.ceil(data.length/FUT_PER_PAGE);
  if(futCurPage>pages)futCurPage=1;
  const start=(futCurPage-1)*FUT_PER_PAGE;
  const pageData=data.slice(start,start+FUT_PER_PAGE);
  const tb=document.getElementById('futTB');
  let h='';
  pageData.forEach(f=>{
    const depIata=f.departure_iata||(f.departure.match(/\(([A-Z]{3})\)/)||['',''])[1]||'';
    const arrIata=f.arrival_iata||(f.arrival.match(/\(([A-Z]{3})\)/)||['',''])[1]||'';
    const cd=depIata&&arrIata?(distMap[depIata+'_'+arrIata]||0):0;
    const stColor=f.status==='cancelled'?'var(--red)':f.status==='delayed'?'var(--orange)':f.status==='scheduled'?'var(--blue)':'var(--green)';
    const stBg=f.status==='cancelled'?'var(--red-light)':f.status==='delayed'?'var(--orange-light)':f.status==='scheduled'?'var(--blue-light)':'var(--green-light)';
    const pax=parseInt(f.passengers)||0;
    h+=`<tr>`;
    h+=`<td><button class="gen-btn" onclick="toast('Checker coming soon')" title="Check flight status">Check</button></td>`;
    h+=`<td class="dt">${k(fD(f.flight_date))}</td>`;
    h+=`<td>${k(f.airline)}</td>`;
    h+=`<td class="fl" style="font-weight:600">${k(f.flight_number)}</td>`;
    h+=`<td>${k(f.departure)}</td>`;
    h+=`<td>${k(f.arrival)}</td>`;
    h+=`<td><select style="padding:3px 8px;border-radius:100px;font-size:10px;font-weight:700;border:1.5px solid;cursor:pointer;font-family:'DM Sans',sans-serif;background:${stBg};color:${stColor};border-color:${stColor}" onchange="updateFutField(${f.id},'status',this.value);renderFuture()">
      <option value="scheduled" ${f.status==='scheduled'?'selected':''}>Scheduled</option>
      <option value="delayed" ${f.status==='delayed'?'selected':''}>Delayed</option>
      <option value="cancelled" ${f.status==='cancelled'?'selected':''}>Cancelled</option>
      <option value="on_time" ${f.status==='on_time'?'selected':''}>On Time</option>
    </select></td>`;
    h+=`<td class="dst">${cd?k(Math.round(cd).toLocaleString()+' km'):''}</td>`;
    h+=`<td style="text-align:center;font-weight:600;color:${pax?'var(--navy)':'var(--g300)'}">${pax||'—'}</td>`;
    h+=`<td style="max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis" title="${esc(f.notes||'')}">${k(f.notes||'')}</td>`;
    h+=`<td><button class="edit-btn" onclick="deleteFutureFlight(${f.id})" title="Delete"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--red)" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg></button></td>`;
    h+=`</tr>`;
  });
  tb.innerHTML=h;
  // Pagination
  const pagArea=document.getElementById('futPagArea');
  if(pages<=1){pagArea.innerHTML=`<span class="pag-info">${data.length} flights</span>`;return}
  let ph=`<button class="pag-btn" onclick="futCurPage--;renderFuture()" ${futCurPage<=1?'disabled':''}>&lt;</button>`;
  for(let i=1;i<=pages;i++)ph+=`<button class="pag-btn ${i===futCurPage?'act':''}" onclick="futCurPage=${i};renderFuture()">${i}</button>`;
  ph+=`<button class="pag-btn" onclick="futCurPage++;renderFuture()" ${futCurPage>=pages?'disabled':''}>&gt;</button>`;
  ph+=`<span class="pag-info">${start+1}–${Math.min(start+FUT_PER_PAGE,data.length)} of ${data.length}</span>`;
  pagArea.innerHTML=ph;
}
async function deleteFutureFlight(id){
  if(!confirm('Delete this future flight?'))return;
  await fetch('?action=delete_future_flight',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
  futureData=futureData.filter(f=>f.id!=id);renderFuture();toast('Flight deleted');
}
async function updateFutField(id,field,val){
  await fetch('?action=update_future_flight',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:field,value:val})});
  const f=futureData.find(x=>x.id==id);if(f)f[field]=val;
}

// ========================================
// ===== WIZZ AIR MODULE — FULL JS =====
// ========================================

const WZ_PER_PAGE=50;
let wzCurPage=1;
let wzSelected=new Set();
let wzFilteredData=[];

// Build flat data for WZ table
// WZ claim URL generator
function wzGenUrl(r,grp){
  const pn=grp.map(x=>((x.fn||x.paxName.split(' ')[0]||'')+'_'+(x.ln||x.paxName.split(' ').slice(1).join(' ')||'')).replace(/\s/g,'_')).join(',');
  const depIata=r.originIata||(r.origin.match(/\(([A-Z]+)\)/)||['',''])[1]||'';
  const arrIata=r.destIata||(r.dest.match(/\(([A-Z]+)\)/)||['',''])[1]||'';
  const depCity=r.origin.replace(/\s*\([A-Z]+\)\s*/,'').trim();
  const arrCity=r.dest.replace(/\s*\([A-Z]+\)\s*/,'').trim();
  return WZ_CLAIM_FORM_URL+'?'+new URLSearchParams({booking:r.pnr,flight:r.fl,date:r.dt,from:depIata,fromCity:depCity,to:arrIata,toCity:arrCity,reason:fmtReason(r.reason),pax:pn}).toString();
}

function wzBuildFlat(){
  return wzFlat.map(r=>{
    const dist=parseInt(r.bk_distance_km)||0;
    const compKm=dist||calcDist(r.origin||'',r.destination||'')||0;
    const flKey=(r.flight_number||'').toUpperCase().replace(/\s+/g,'')+'_'+normDate(r.flight_date);
    const flInfo=flMap[flKey]||{};
    return {
      id:r.id, bkId:r.booking_id, accId:r.account_id,
      // Account-level fields
      accNr:r.account_number||'', holderName:r.holder_name||'',
      holderDob:r.holder_dob||'', 
      accNat:r.acc_nationality||'',
      accPpNr:r.acc_passport_number||'', accPpCo:r.acc_passport_issued_country||'', accPpExp:r.acc_passport_expiry||'',
      accEmail:r.acc_email||'', accPhone:r.acc_phone||'', accAddress:r.acc_address||'',
      // Passenger-level fields
      fn:r.first_name||'', ln:r.last_name||'', paxName:r.passenger_name||'',
      email:r.email||r.acc_email||'',
      paxDob:r.dob||'', paxNat:r.nationality||'',
      paxPpNr:r.passport_number||'', paxPpCo:r.passport_issued_country||'', paxPpExp:r.passport_expiry||'',
      paxPhone:r.phone||'', paxAddr:r.address||'',
      // Booking/flight
      pnr:r.pnr||'', fl:r.flight_number||'', dt:r.flight_date||'',
      origin:r.origin||'', originIata:r.origin_iata||'',
      dest:r.destination||'', destIata:r.destination_iata||'',
      reason:r.bk_reason||flInfo.reason||'', dist:dist, compKm:compKm,
      seat:r.seat||'', checkin:r.checkin_status||'', isHolder:parseInt(r.is_holder)||0,
      idF:r.id_doc_filename||'', idP:r.id_doc_path||'', idV:parseInt(r.id_doc_viewed||0),
      trF:r.travel_doc_filename||'', trP:r.travel_doc_path||'', trV:parseInt(r.travel_doc_viewed||0),
      asF:r.assignment_filename||'', asP:r.assignment_path||'',
      ms:r.mail_sent_at||'', mt:r.mail_template||'', mts:r.mail_template||'',
      st:r.status||'doc_needed', cm:r.claim_method||'', notes:r.notes||'',
      rmActive:parseInt(r.remarketing_active||0), rmSent:r.claim_mail_sent_at||'',
      ah:flInfo.ah||'', ahSrc:flInfo.ahSrc||'', ahNote:flInfo.ahNote||'',
      upd:r.updated_at||''
    };
  });
}
let WZ=wzBuildFlat();

// Selection
function wzToggleAll(checked){const pd=wzGetPageData();pd.forEach(r=>{if(checked)wzSelected.add(r.id);else wzSelected.delete(r.id)});wzRenderTable(pd);wzUpdBulk()}
function wzSelectAllFiltered(){wzFilteredData.forEach(r=>{wzSelected.add(r.id)});wzRenderTable(wzGetPageData());wzUpdBulk()}
function wzToggleSel(id,checked){if(checked)wzSelected.add(id);else wzSelected.delete(id);wzUpdBulk()}
function wzClearSel(){wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzRenderTable(wzGetPageData());wzUpdBulk()}
function wzUpdBulk(){
  const bar=document.getElementById('wzBulkBar');
  const cnt=wzSelected.size;
  document.getElementById('wzBbCount').textContent=cnt+' selected';
  bar.classList.toggle('show',cnt>0);
  document.getElementById('wzBbSelAll').textContent=cnt<wzFilteredData.length?'Select All ('+wzFilteredData.length+')':'All Selected';
}
function wzGetPageData(){const s=(wzCurPage-1)*WZ_PER_PAGE;return wzFilteredData.slice(s,s+WZ_PER_PAGE)}

// Doc cell helper (reuses same pattern as main)
function wzDocC(id,dt,fn,fp,vw){
  if(fn){
    const url='uploads/'+fp;
    const viewCls=vw?'vw':'uv';
    const viewAction=vw?`window.open('${url}','_blank')`:`fetch('?action=wz_mark_viewed',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:${id},doc_type:'${dt}'})}).then(()=>{const r=WZ.find(x=>x.id==${id});if(r)r.${dt==='id'?'idV':'trV'}=1;renderWz()});window.open('${url}','_blank')`;
    return `<div class="dc"><a class="dib ${viewCls}" href="javascript:void(0)" onclick="${viewAction}" title="${esc(fn)}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg></a><button class="ddb" onclick="wzDelDoc(${id},'${dt}')"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>`;
  }
  return `<label class="dub">Upload<input type="file" onchange="wzUpDoc(${id},'${dt}',this)"></label>`;
}
async function wzUpDoc(id,dt,inp){
  const f=inp.files[0];if(!f)return;
  const fd=new FormData();fd.append('id',id);fd.append('doc_type',dt);fd.append('file',f);
  const res=await fetch('?action=wz_upload_doc',{method:'POST',body:fd});
  const j=await res.json();
  if(j.ok){const r=WZ.find(x=>x.id==id);if(r){if(dt==='id'){r.idF=j.filename;r.idP=j.path}else{r.trF=j.filename;r.trP=j.path}}renderWz();toast('Uploaded!')}
}
async function wzDelDoc(id,dt){
  if(!confirm('Delete this document?'))return;
  await fetch('?action=wz_delete_doc',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,doc_type:dt})});
  const r=WZ.find(x=>x.id==id);if(r){if(dt==='id'){r.idF='';r.idP='';r.idV=0}else{r.trF='';r.trP='';r.trV=0}}renderWz();toast('Deleted');
}

// Assignment cell
function wzAsC(id,fn,fp,hasAddr){
  if(fn){
    const url='uploads/'+fp;
    return `<div class="dc"><a class="dib vw" href="${url}" target="_blank" title="${esc(fn)}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg></a><button class="ddb" onclick="wzDelAssign(${id})"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>`;
  }
  let h=`<label class="dub" style="margin-right:4px">Upload<input type="file" onchange="wzUpAssign(${id},this)"></label>`;
  if(hasAddr)h+=`<button class="gen-btn" onclick="wzGenAssign(${id})"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>Gen</button>`;
  return h;
}
async function wzUpAssign(id,inp){
  const f=inp.files[0];if(!f)return;
  const fd=new FormData();fd.append('id',id);fd.append('file',f);
  const res=await fetch('?action=wz_upload_assignment',{method:'POST',body:fd});
  const j=await res.json();
  if(j.ok){const r=WZ.find(x=>x.id==id);if(r){r.asF=j.filename;r.asP=j.path}renderWz();toast('Uploaded!')}
}
async function wzDelAssign(id){
  if(!confirm('Delete assignment?'))return;
  await fetch('?action=wz_delete_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
  const r=WZ.find(x=>x.id==id);if(r){r.asF='';r.asP=''}renderWz();toast('Deleted');
}
async function wzGenAssign(id){
  toast('Generating...');
  const res=await fetch('?action=wz_generate_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
  const j=await res.json();
  if(j.ok){const r=WZ.find(x=>x.id==id);if(r){r.asF=j.filename;r.asP=j.path}renderWz();toast('Assignment generated!')}
  else{toast(j.message||'Generation failed')}
}

// Mail template selector
function wzMailTplSel(id,mt){
  return `<select class="mail-sel" onchange="wzSetTpl(${id},this.value)"><option value="">—</option>${tpls.map(t=>`<option value="${t.slug}" ${t.slug===mt?'selected':''}>${t.label}</option>`).join('')}</select>`;
}
async function wzSetTpl(id,tpl){
  await fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:'mail_template',value:tpl})});
  const r=WZ.find(x=>x.id==id);if(r){r.mt=tpl;r.mts=''}renderWz();
}

// Mail cell: Send button with preview — shows Send if template set and either never sent or template changed since last send
function wzMailC(id,ms,mt,mts){
  if(!mt)return'';
  if(ms&&mt===mts)return`<button class="mb snt">${MI} Sent<span class="mi">Sent: ${fDT(ms)}</span></button>`;
  return`<button class="mb rdy" onclick="wzSendPreview(${id})">${MI} Send</button>`;
}

// Send with Preview modal
async function wzSendPreview(id){
  const r=WZ.find(x=>x.id==id);if(!r||!r.mt)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:680px;max-height:90vh;display:flex;flex-direction:column">
    <div class="em-head" style="flex-shrink:0"><h3>Preview & Send Email</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body" style="flex:1;overflow:auto;text-align:center;padding:40px">
      <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--purple)" stroke-width="2" style="animation:spin 1s linear infinite"><path d="M21 12a9 9 0 11-6.219-8.56"/></svg>
      <p style="margin-top:8px;font-size:13px;color:var(--g500)">Loading preview...</p>
    </div></div>`;
  m.classList.add('show');
  try{
    const res=await fetch('?action=wz_preview_template',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:r.mt})});
    const j=await res.json();
    if(!j.ok){toast(j.message||'Preview failed');closeEdit();return}
    const isHtml=j.is_html;
    const bodySection=isHtml
      ?`<div style="margin-top:12px;background:var(--white);border:1px solid var(--g200);border-radius:8px;overflow:hidden"><iframe id="wzPreviewFrame" style="width:100%;height:420px;border:none" sandbox="allow-same-origin"></iframe></div>`
      :`<div style="margin-top:12px;text-align:left"><label style="font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:4px">Body</label>
        <textarea id="wzPreviewBody" style="width:100%;min-height:260px;border:1.5px solid var(--g200);border-radius:8px;padding:12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);resize:vertical;line-height:1.6">${esc(j.body)}</textarea></div>`;
    m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:680px;max-height:90vh;display:flex;flex-direction:column">
      <div class="em-head" style="flex-shrink:0"><h3 style="color:#E5007D">Preview &amp; Send — Wizz Air</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
      <div style="flex-shrink:0;padding:12px 20px;background:var(--g50);border-bottom:1px solid var(--g100);display:flex;align-items:center;gap:8px;flex-wrap:wrap">
        <span style="font-size:11px;color:var(--g400)">To:</span><span style="font-size:12px;font-weight:600;color:var(--navy)">${esc(j.email||'no email')}</span>
        <span style="font-size:11px;color:var(--g400);margin-left:8px">Name:</span><span style="font-size:12px;font-weight:500;color:var(--navy)">${esc(j.name)}</span>
      </div>
      <div class="em-body" style="flex:1;overflow:auto">
        <div style="text-align:left"><label style="font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:4px">Subject</label>
          <input type="text" id="wzPreviewSubject" value="${esc(j.subject)}" style="width:100%;height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none">
        </div>
        ${bodySection}
      </div>
      <div class="em-foot" style="flex-shrink:0">
        <button class="em-cancel" onclick="closeEdit()">Cancel</button>
        <button class="em-save" style="background:#E5007D" onclick="wzDoSend(${id},'${r.mt}',${isHtml})">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
          Send Email
        </button>
      </div></div>`;
    if(isHtml){setTimeout(()=>{const fr=document.getElementById('wzPreviewFrame');if(fr&&fr.contentDocument){fr.contentDocument.open();fr.contentDocument.write(j.html);fr.contentDocument.close()}},50)}
  }catch(e){toast('Preview failed');closeEdit()}
}

async function wzDoSend(id,tpl,isHtml){
  closeEdit();toast('Sending...');
  const res=await fetch('?action=wz_send_mail',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:tpl})});
  const j=await res.json();
  if(j.ok){const r=WZ.find(x=>x.id==id);if(r){r.ms=j.mail_sent_at;r.rmActive=1;r.rmSent=j.mail_sent_at;if(j.new_status)r.st=j.new_status}rmLoaded=false;renderWz();toast('Mail sent!')}
  else{toast(j.message||'Send failed')}
}

// Status dropdown
function wzStBdg(id,s){
  return `<select class="stb st-${s}" onchange="wzChSt(${id},this.value)">${STS.map(x=>`<option value="${x}" ${x===s?'selected':''}>${SLB[x]}</option>`).join('')}</select>`;
}
async function wzChSt(id,s){
  await fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:'status',value:s})});
  // Log status change to history
  await fetch('?action=wz_log_status',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,status:s})});
  const r=WZ.find(x=>x.id==id);if(r)r.st=s;renderWz();
}

// ===== BULK OPERATIONS =====
function wzGetSelectedAll(){return WZ.filter(r=>wzSelected.has(r.id))}

async function wzBulkSetTemplate(){
  if(wzSelected.size===0)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:420px">
    <div class="em-head"><h3 style="color:#E5007D">Set Mail Template</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <p style="font-size:13px;color:var(--g500);margin-bottom:12px">Select template for <strong>${wzGetSelectedAll().length}</strong> passengers:</p>
      <label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600">
        <input type="radio" name="wztpl" value="" style="accent-color:#E5007D"> <span style="color:var(--g400)">— None (clear)</span>
      </label>
      ${tpls.map(t=>`<label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600">
        <input type="radio" name="wztpl" value="${t.slug}" style="accent-color:#E5007D"> ${t.label}
      </label>`).join('')}
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" style="background:#E5007D" onclick="wzDoBulkSetTpl()">Apply</button>
    </div></div>`;
  m.classList.add('show');
}
async function wzDoBulkSetTpl(){
  const radio=document.querySelector('input[name=wztpl]:checked');
  if(!radio){toast('Select a template');return}
  const slug=radio.value;closeEdit();
  const all=wzGetSelectedAll();
  const promises=all.map(r=>fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id,field:'mail_template',value:slug})}));
  await Promise.all(promises);
  all.forEach(r=>{r.mt=slug});
  wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzUpdBulk();renderWz();
  toast(all.length+' passengers updated');
}

async function wzBulkSend(){
  const all=wzGetSelectedAll();
  const items=all.filter(r=>r.mt&&!r.ms).map(r=>({id:r.id,template:r.mt}));
  if(items.length===0){toast('No sendable items — set templates first or check already sent');return}
  confirmAction('Send Mails',`Send <strong>${items.length}</strong> emails to Wizz Air passengers?`,'Send Mails','--purple',async()=>{
    const res=await fetch('?action=wz_bulk_send_mail',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ids:items})});
    const j=await res.json();
    if(j.ok){
      items.forEach(item=>{const r=WZ.find(x=>x.id==item.id);if(r){r.ms=new Date().toISOString();if(item.template==='claim_submit'){r.st='form_sent';r.rmActive=1}else if(item.template==='hibas_id')r.st='bad_id_sent'}});
      rmLoaded=false;wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzUpdBulk();renderWz();
      let msg=j.sent+' mails sent!';if(j.failed>0)msg+=' ('+j.failed+' failed)';toast(msg);
    }
  });
}

async function wzBulkStatus(){
  if(wzSelected.size===0)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:420px">
    <div class="em-head"><h3 style="color:#E5007D">Change Status</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <p style="font-size:13px;color:var(--g500);margin-bottom:12px">Select status for <strong>${wzGetSelectedAll().length}</strong> passengers:</p>
      ${STS.map(s=>`<label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;cursor:pointer;border:1.5px solid var(--g200);margin-bottom:6px;font-size:13px;font-weight:600">
        <input type="radio" name="wzst" value="${s}" style="accent-color:#E5007D"> ${SLB[s]}
      </label>`).join('')}
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" style="background:#E5007D" onclick="wzDoBulkStatus()">Apply</button>
    </div></div>`;
  m.classList.add('show');
}
async function wzDoBulkStatus(){
  const radio=document.querySelector('input[name=wzst]:checked');
  if(!radio){toast('Select a status');return}
  const status=radio.value;closeEdit();
  const all=wzGetSelectedAll();
  const ids=all.map(r=>r.id);
  await fetch('?action=wz_bulk_status',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ids:ids,status:status})});
  all.forEach(r=>{r.st=status});
  wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzUpdBulk();renderWz();toast(all.length+' updated');
}

async function wzBulkGenAssign(){
  if(wzSelected.size===0)return;
  const all=wzGetSelectedAll();
  confirmAction('Generate Assignments',`Generate assignment PDFs for <strong>${all.length}</strong> passengers?`,'Generate','--purple',async()=>{
    let ok=0;
    for(const r of all){
      try{const res=await fetch('?action=wz_generate_assignment',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id})});
        const j=await res.json();if(j.ok){r.asF=j.filename;r.asP=j.path;ok++}}catch(e){}
    }
    wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzUpdBulk();renderWz();toast(ok+' assignments generated!');
  });
}

async function wzBulkDelete(){
  if(wzSelected.size===0)return;
  const all=wzGetSelectedAll();
  confirmAction('Delete Passengers',`<span style="color:var(--red);font-weight:700">Permanently delete ${all.length} passengers?</span><br>This cannot be undone.`,'Delete','--red',async()=>{
    const ids=all.map(r=>r.id);
    await fetch('?action=wz_bulk_delete',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ids:ids})});
    // Remove from local data
    ids.forEach(id=>{const i=WZ.findIndex(x=>x.id==id);if(i>-1)WZ.splice(i,1);const j=wzFlat.findIndex(x=>x.id==id);if(j>-1)wzFlat.splice(j,1)});
    wzSelected.clear();document.getElementById('wzSelAll').checked=false;wzUpdBulk();renderWz();toast(all.length+' deleted');
  });
}

// ===== ADD CUSTOMER MODAL =====
let wzAddPaxCount=1;
function showWzAddCustomer(){
  wzAddPaxCount=1;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:750px">
    <div class="em-head"><h3 style="color:#E5007D">Add Wizz Air Customer</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <div class="em-section">Flight Details</div>
      <div class="em-grid">
        <div class="em-fg"><label>PNR / Booking Ref *</label><input id="wza_pnr" placeholder="ABC123 (auto if empty)"></div>
        <div class="em-fg"><label>Flight Number</label><input id="wza_fl" placeholder="W6 1045"></div>
        <div class="em-fg"><label>Date</label><input type="date" id="wza_dt"></div>
        <div class="em-fg"><label>Departure</label><input id="wza_orig" placeholder="Budapest (BUD)"></div>
        <div class="em-fg"><label>Arrival</label><input id="wza_dest" placeholder="London Luton (LTN)"></div>
        <div class="em-fg"><label>Reason</label><input id="wza_rsn" placeholder="Delayed (195 min)"></div>
        <div class="em-fg"><label>Distance (km)</label><input type="number" id="wza_dist" placeholder="1450"></div>
      </div>
      <div class="em-section">Account Holder</div>
      <div class="em-grid">
        <div class="em-fg"><label>Account Number</label><input id="wza_accnr" placeholder="WZ-12345678 (auto)"></div>
        <div class="em-fg"><label>First Name</label><input id="wza_hfn" placeholder="Maria"></div>
        <div class="em-fg"><label>Last Name</label><input id="wza_hln" placeholder="Kovacs"></div>
        <div class="em-fg"><label>Date of Birth</label><input type="date" id="wza_dob"></div>
        <div class="em-fg"><label>Nationality</label><input id="wza_nat" placeholder="Hungarian"></div>
        <div class="em-fg"><label>Passport Number</label><input id="wza_ppnr" placeholder="HU12345678"></div>
        <div class="em-fg"><label>Passport Country</label><input id="wza_ppco" placeholder="Hungary"></div>
        <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wza_ppex"></div>
        <div class="em-fg"><label>Email</label><input id="wza_accem" placeholder="email@example.com" type="email"></div>
        <div class="em-fg"><label>Phone</label><input id="wza_phone" placeholder="+36301234567"></div>
        <div class="em-fg full"><label>Address</label><input id="wza_addr" placeholder="Váci út 45, 1134 Budapest, Hungary"></div>
      </div>
      <div class="em-section">Passengers</div>
      <div id="wzaPaxList">
        <div class="wza-pax" data-idx="0" style="background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px">
          <div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">
            <span style="font-size:14px;font-weight:800;color:#E5007D">Passenger 1</span>
            <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:#E5007D;background:#FDE8F3;padding:2px 6px;border-radius:4px">Main</span>
          </div>
          <div class="em-grid">
            <div class="em-fg"><label>First Name *</label><input id="wza_fn_0" placeholder="Maria"></div>
            <div class="em-fg"><label>Last Name *</label><input id="wza_ln_0" placeholder="Kovacs"></div>
            <div class="em-fg"><label>Date of Birth</label><input type="date" id="wza_pdob_0"></div>
            <div class="em-fg"><label>Nationality</label><input id="wza_pnat_0" placeholder="Hungarian"></div>
            <div class="em-fg"><label>Passport Number</label><input id="wza_pppnr_0"></div>
            <div class="em-fg"><label>Passport Country</label><input id="wza_pppco_0"></div>
            <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wza_pppex_0"></div>
            <div class="em-fg"><label>Email</label><input id="wza_em_0" placeholder="email@example.com" type="email"></div>
            <div class="em-fg"><label>Phone</label><input id="wza_pph_0"></div>
            <div class="em-fg full"><label>Address</label><input id="wza_paddr_0"></div>
            <div class="em-fg"><label>Seat</label><input id="wza_seat_0" placeholder="14A"></div>
            <div class="em-fg"><label>Checkin Status</label>
              <select id="wza_chk_0" style="height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;background:var(--white)">
                <option value="">—</option><option value="checked_in">Checked In</option><option value="not_checked_in">Not Checked In</option>
              </select>
            </div>
          </div>
        </div>
      </div>
      <button onclick="wzaAddPax()" style="margin-top:4px;width:100%;padding:10px;border-radius:8px;border:1.5px dashed var(--g300);background:var(--white);color:var(--g500);font-size:13px;font-weight:600;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;justify-content:center;gap:6px;transition:all .15s" onmouseover="this.style.borderColor='#E5007D';this.style.color='#E5007D';this.style.background='#FDE8F3'" onmouseout="this.style.borderColor='var(--g300)';this.style.color='var(--g500)';this.style.background='var(--white)'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Passenger</button>
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" style="background:#E5007D" onclick="wzDoAddCustomer()">Add Customer</button>
    </div></div>`;
  m.classList.add('show');
}

function wzaAddPax(){
  const idx=wzAddPaxCount++;
  const list=document.getElementById('wzaPaxList');
  const div=document.createElement('div');
  div.className='wza-pax';div.setAttribute('data-idx',idx);
  div.style.cssText='background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px';
  div.innerHTML=`
    <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
      <span style="font-size:14px;font-weight:800;color:var(--g500)">New Passenger</span>
      <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>
      <button onclick="this.closest('.wza-pax').remove()" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Remove</button>
    </div>
    <div class="em-grid">
      <div class="em-fg"><label>First Name *</label><input id="wza_fn_${idx}"></div>
      <div class="em-fg"><label>Last Name *</label><input id="wza_ln_${idx}"></div>
      <div class="em-fg"><label>Date of Birth</label><input type="date" id="wza_pdob_${idx}"></div>
      <div class="em-fg"><label>Nationality</label><input id="wza_pnat_${idx}"></div>
      <div class="em-fg"><label>Passport Number</label><input id="wza_pppnr_${idx}"></div>
      <div class="em-fg"><label>Passport Country</label><input id="wza_pppco_${idx}"></div>
      <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wza_pppex_${idx}"></div>
      <div class="em-fg"><label>Email</label><input id="wza_em_${idx}" type="email"></div>
      <div class="em-fg"><label>Phone</label><input id="wza_pph_${idx}"></div>
      <div class="em-fg full"><label>Address</label><input id="wza_paddr_${idx}"></div>
      <div class="em-fg"><label>Seat</label><input id="wza_seat_${idx}"></div>
      <div class="em-fg"><label>Checkin Status</label>
        <select id="wza_chk_${idx}" style="height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;background:var(--white)">
          <option value="">—</option><option value="checked_in">Checked In</option><option value="not_checked_in">Not Checked In</option>
        </select>
      </div>
    </div>`;
  list.appendChild(div);
  div.scrollIntoView({behavior:'smooth',block:'center'});
}

async function wzDoAddCustomer(){
  // Collect passengers
  const paxCards=document.querySelectorAll('#wzaPaxList .wza-pax');
  const passengers=[];
  paxCards.forEach(card=>{
    const idx=card.getAttribute('data-idx');
    const fn=(document.getElementById('wza_fn_'+idx)?.value||'').trim();
    const ln=(document.getElementById('wza_ln_'+idx)?.value||'').trim();
    if(!fn&&!ln)return;
    passengers.push({
      first_name:fn, last_name:ln,
      email:(document.getElementById('wza_em_'+idx)?.value||'').trim(),
      seat:(document.getElementById('wza_seat_'+idx)?.value||'').trim(),
      checkin_status:(document.getElementById('wza_chk_'+idx)?.value||'').trim()
    });
  });
  if(passengers.length===0||!passengers[0].first_name||!passengers[0].last_name){toast('First passenger name required');return}

  const data={
    account_number:document.getElementById('wza_accnr').value.trim(),
    holder_name:(document.getElementById('wza_hfn').value.trim()+' '+document.getElementById('wza_hln').value.trim()).trim(),
    holder_dob:document.getElementById('wza_dob').value||null,
    nationality:document.getElementById('wza_nat').value.trim(),
    phone:document.getElementById('wza_phone').value.trim(),
    account_email:document.getElementById('wza_accem').value.trim(),
    address:document.getElementById('wza_addr').value.trim(),
    passport_number:document.getElementById('wza_ppnr').value.trim(),
    passport_issued_country:document.getElementById('wza_ppco').value.trim(),
    passport_expiry:document.getElementById('wza_ppex').value||null,
    pnr:document.getElementById('wza_pnr').value.trim(),
    flight_number:document.getElementById('wza_fl').value.trim(),
    flight_date:document.getElementById('wza_dt').value,
    reason:document.getElementById('wza_rsn').value.trim(),
    origin:document.getElementById('wza_orig').value.trim(),
    destination:document.getElementById('wza_dest').value.trim(),
    distance_km:document.getElementById('wza_dist').value||null,
    passengers:passengers
  };
  const res=await fetch('?action=wz_add_customer',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
  const j=await res.json();
  if(j.ok){closeEdit();toast(passengers.length+' passenger(s) added — reloading...');setTimeout(()=>location.reload(),600)}
  else{toast(j.message||'Failed')}
}

// WZ Claim method selector (Beadva column)
function wzCmSel(id,cm){
  return `<select class="mail-sel" style="max-width:100px" onchange="wzUpdField(${id},'claim_method',this.value)">
    <option value="" ${!cm?'selected':''}>—</option>
    <option value="assignment" ${cm==='assignment'?'selected':''}>Assignment</option>
    <option value="sajat_fiok" ${cm==='sajat_fiok'?'selected':''}>Saját fiók</option>
    <option value="airhelp" ${cm==='airhelp'?'selected':''}>Airhelp</option>
  </select>`;
}
async function wzUpdField(id,field,val){
  await fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:field,value:val})});
  const r=WZ.find(x=>x.id==id);if(r)r[field==='claim_method'?'cm':field]=val;
}

// WZ Notes icon
function wzNotesC(id,notes){
  const has=notes&&notes.trim();
  const ico='<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>';
  if(!has) return`<span class="ni" onclick="wzEditNote(event,${id})">${ico}</span>`;
  return`<span class="ni has" onclick="wzEditNote(event,${id})" onmouseenter="wzShowNote(event,${id})" onmouseleave="wzHideNote()">${ico}</span>`;
}
let wzNoteTip=null;
function wzShowNote(ev,id){
  const r=WZ.find(x=>x.id==id);if(!r||!r.notes)return;
  let tip=document.getElementById('wzNoteTip');
  if(!tip){tip=document.createElement('div');tip.id='wzNoteTip';tip.className='ni-tip';document.body.appendChild(tip);}
  tip.textContent=r.notes;
  tip.style.display='block';
  const rect=ev.currentTarget.getBoundingClientRect();
  tip.style.left=rect.left+rect.width/2-tip.offsetWidth/2+'px';
  tip.style.top=rect.top-tip.offsetHeight-10+'px';
  const tr=tip.getBoundingClientRect();
  if(tr.left<8)tip.style.left='8px';
  if(tr.right>window.innerWidth-8)tip.style.left=window.innerWidth-8-tip.offsetWidth+'px';
  if(tr.top<8){tip.style.top=rect.bottom+10+'px';}
}
function wzHideNote(){const tip=document.getElementById('wzNoteTip');if(tip)tip.style.display='none';}
function wzEditNote(ev,id){
  ev.stopPropagation();wzHideNote();
  const r=WZ.find(x=>x.id==id);if(!r)return;
  const cur=r.notes||'';
  const old=document.getElementById('noteEditor');if(old)old.remove();
  const div=document.createElement('div');div.id='noteEditor';
  div.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(27,42,74,.35);z-index:99998;display:flex;align-items:center;justify-content:center';
  div.onclick=function(e){if(e.target===div)div.remove()};
  div.innerHTML=`<div style="background:var(--white);border-radius:18px;box-shadow:0 24px 64px rgba(27,42,74,.28);width:460px;overflow:hidden" onclick="event.stopPropagation()">
    <div style="padding:18px 24px;border-bottom:1px solid var(--g200);display:flex;align-items:center;justify-content:space-between">
      <span style="font-weight:800;font-size:15px;color:var(--navy)">Jegyzetek — ${esc(r.fn||r.paxName)} ${esc(r.ln||'')}</span>
      <button onclick="document.getElementById('noteEditor').remove()" style="width:28px;height:28px;border-radius:8px;border:none;background:var(--g100);color:var(--g500);cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center">✕</button>
    </div>
    <div style="padding:20px 24px">
      <textarea id="noteTA" style="width:100%;min-height:160px;border:1.5px solid var(--g200);border-radius:10px;padding:12px 14px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);resize:vertical;outline:none;line-height:1.6" placeholder="Jegyzet hozzáadása...">${esc(cur)}</textarea>
      <div style="display:flex;gap:8px;margin-top:14px;justify-content:flex-end">
        ${cur?`<button onclick="wzSaveNote(${id},'')" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:1px solid var(--red);background:var(--red-light);color:var(--red);cursor:pointer;font-family:'DM Sans',sans-serif">Törlés</button>`:''}
        <button onclick="document.getElementById('noteEditor').remove()" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:1px solid var(--g200);background:var(--white);color:var(--g500);cursor:pointer;font-family:'DM Sans',sans-serif">Mégse</button>
        <button onclick="wzSaveNote(${id},document.getElementById('noteTA').value)" style="padding:7px 16px;border-radius:8px;font-size:12px;font-weight:600;border:none;background:#E5007D;color:var(--white);cursor:pointer;font-family:'DM Sans',sans-serif">Mentés</button>
      </div>
    </div>
  </div>`;
  document.body.appendChild(div);
  const ta=document.getElementById('noteTA');ta.focus();ta.setSelectionRange(ta.value.length,ta.value.length);
}
async function wzSaveNote(id,val){
  document.getElementById('noteEditor').remove();
  const r=WZ.find(x=>x.id==id);if(r)r.notes=val;
  renderWz();toast(val?'Jegyzet mentve':'Jegyzet törölve');
  await fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,field:'notes',value:val})});
}

// WZ Remarketing badge (simplified)
function wzRmBdg(r){
  if(!r.rmSent)return'';
  const active=r.rmActive;
  return active?`<span style="font-size:10px;font-weight:700;color:#059669">Active</span>`:`<span style="font-size:10px;color:var(--g400)">Stopped</span>`;
}

// WZ Claim Mail button (preview only, same as main page)
function wzClaimMailBtn(id){
  return `<button class="prvw-btn" onclick="wzPreviewClaimMail(${id})" title="Preview claim notification email"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>`;
}
async function wzPreviewClaimMail(id){
  const r=WZ.find(x=>x.id==id);if(!r)return;
  const m=document.getElementById('editModal');
  m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:720px;max-height:90vh">
    <div class="em-head"><h3 style="color:#E5007D">Claim Preview — ${esc(r.fn||r.paxName)} ${esc(r.ln||'')}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body" style="padding:16px;text-align:center">
      <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--purple)" stroke-width="2" style="animation:spin 1s linear infinite"><path d="M21 12a9 9 0 11-6.219-8.56"/></svg>
      <p style="margin-top:8px;font-size:13px;color:var(--g500)">Loading email preview...</p>
    </div></div>`;
  m.classList.add('show');
  try{
    const res=await fetch('?action=wz_preview_template',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,template:'claim_submit'})});
    const j=await res.json();
    if(j.ok&&j.is_html){
      m.innerHTML=`<div class="em-box" onclick="event.stopPropagation()" style="max-width:720px;max-height:90vh;display:flex;flex-direction:column">
        <div class="em-head" style="flex-shrink:0"><h3 style="color:#E5007D">Claim Preview — ${esc(r.fn||r.paxName)} ${esc(r.ln||'')}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
        <div style="flex-shrink:0;padding:12px 20px;background:var(--g50);border-bottom:1px solid var(--g100);display:flex;align-items:center;gap:8px;flex-wrap:wrap">
          <span style="font-size:11px;color:var(--g400)">To:</span><span style="font-size:12px;font-weight:600;color:var(--navy)">${esc(j.email||'no email')}</span>
          <span style="font-size:11px;color:var(--g400);margin-left:12px">PNR:</span><span style="font-size:12px;font-weight:700;color:var(--purple)">${esc(r.pnr)}</span>
        </div>
        <div style="flex:1;overflow:auto;padding:0"><iframe id="wzClaimFrame" style="width:100%;height:600px;border:none" sandbox="allow-same-origin"></iframe></div>
        <div class="em-foot" style="flex-shrink:0"><button class="em-cancel" onclick="closeEdit()">Close</button></div>
      </div>`;
      setTimeout(()=>{const fr=document.getElementById('wzClaimFrame');if(fr&&fr.contentDocument){fr.contentDocument.open();fr.contentDocument.write(j.html);fr.contentDocument.close()}},50);
    }else{toast(j.message||'Preview failed');closeEdit()}
  }catch(e){toast('Preview failed');closeEdit()}
}

// ===== EDIT MODAL =====
function wzOpenEdit(bkId){
  const grp=WZ.filter(x=>x.bkId==bkId);
  if(!grp.length)return;
  const holder=grp.find(x=>x.isHolder)||grp[0];
  const pnr=holder.pnr;
  const m=document.getElementById('editModal');
  const selOpt=(id,val,opts)=>opts.map(o=>`<option value="${o[0]}" ${val===o[0]?'selected':''}>${o[1]}</option>`).join('');
  const chkOpts=[['','—'],['checked_in','Checked In'],['not_checked_in','Not Checked In']];
  const holderNameParts=(holder.holderName||'').split(' ');
  const holderFn=holderNameParts[0]||'';
  const holderLn=holderNameParts.slice(1).join(' ')||'';

  let paxHtml=grp.map((r,i)=>{
    const isH=r.isHolder;
    return `
      <div style="background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px">
        <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
          <span style="font-size:14px;font-weight:800;color:var(--navy)">${esc(r.fn||r.paxName)} ${esc(r.ln||'')}</span>
          ${isH?'<span style="font-size:9px;font-weight:700;text-transform:uppercase;color:#E5007D;background:#FDE8F3;padding:2px 6px;border-radius:4px">Main</span>':'<span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>'}
          <button onclick="wzDelPaxInEdit(${r.id})" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Delete</button>
        </div>
        <div class="em-grid">
          <div class="em-fg"><label>First Name</label><input id="wze_fn_${i}" value="${esc(r.fn)}"></div>
          <div class="em-fg"><label>Last Name</label><input id="wze_ln_${i}" value="${esc(r.ln)}"></div>
          <div class="em-fg"><label>Date of Birth</label><input type="date" id="wze_pdob_${i}" value="${r.paxDob||''}"></div>
          <div class="em-fg"><label>Nationality</label><input id="wze_pnat_${i}" value="${esc(r.paxNat)}"></div>
          <div class="em-fg"><label>Passport Number</label><input id="wze_pppnr_${i}" value="${esc(r.paxPpNr)}"></div>
          <div class="em-fg"><label>Passport Country</label><input id="wze_pppco_${i}" value="${esc(r.paxPpCo)}"></div>
          <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wze_pppex_${i}" value="${r.paxPpExp||''}"></div>
          <div class="em-fg"><label>Email</label><input id="wze_em_${i}" value="${esc(r.email)}" type="email"></div>
          <div class="em-fg"><label>Phone</label><input id="wze_pph_${i}" value="${esc(r.paxPhone)}"></div>
          <div class="em-fg full"><label>Address</label><input id="wze_paddr_${i}" value="${esc(r.paxAddr)}"></div>
          <div class="em-fg"><label>Seat</label><input id="wze_seat_${i}" value="${esc(r.seat)}"></div>
          <div class="em-fg"><label>Checkin Status</label>
            <select id="wze_chk_${i}" style="height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;background:var(--white)">
              ${selOpt('wze_chk_'+i,r.checkin||'',chkOpts)}
            </select>
          </div>
        </div>
      </div>`;
  }).join('');

  m.innerHTML=`
  <div class="em-box" onclick="event.stopPropagation()" style="max-width:750px">
    <div class="em-head"><h3 style="color:#E5007D">Edit Booking — ${esc(pnr)}</h3><button class="em-close" onclick="closeEdit()">✕</button></div>
    <div class="em-body">
      <div class="em-section">Flight Details</div>
      <div class="em-grid">
        <div class="em-fg"><label>PNR / Booking Ref</label><input id="wze_pnr" value="${esc(holder.pnr)}"></div>
        <div class="em-fg"><label>Flight Number</label><input id="wze_fl" value="${esc(holder.fl)}"></div>
        <div class="em-fg"><label>Date</label><input type="date" id="wze_dt" value="${holder.dt||''}"></div>
        <div class="em-fg"><label>Departure</label><input id="wze_orig" value="${esc(holder.origin)}"></div>
        <div class="em-fg"><label>Arrival</label><input id="wze_dest" value="${esc(holder.dest)}"></div>
        <div class="em-fg"><label>Reason</label><input id="wze_rsn" value="${esc(holder.reason)}"></div>
        <div class="em-fg"><label>Distance (km)</label><input type="number" id="wze_dist" value="${holder.dist||''}"></div>
      </div>
      <div class="em-section">Account Holder</div>
      <div class="em-grid">
        <div class="em-fg"><label>Account Number</label><input id="wze_accnr" value="${esc(holder.accNr)}"></div>
        <div class="em-fg"><label>First Name</label><input id="wze_hfn" value="${esc(holderFn)}"></div>
        <div class="em-fg"><label>Last Name</label><input id="wze_hln" value="${esc(holderLn)}"></div>
        <div class="em-fg"><label>Date of Birth</label><input type="date" id="wze_dob" value="${holder.holderDob||''}"></div>
        <div class="em-fg"><label>Nationality</label><input id="wze_nat" value="${esc(holder.accNat)}"></div>
        <div class="em-fg"><label>Passport Number</label><input id="wze_ppnr" value="${esc(holder.accPpNr)}"></div>
        <div class="em-fg"><label>Passport Country</label><input id="wze_ppco" value="${esc(holder.accPpCo)}"></div>
        <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wze_ppex" value="${holder.accPpExp||''}"></div>
        <div class="em-fg"><label>Email</label><input id="wze_accem" value="${esc(holder.accEmail)}" type="email"></div>
        <div class="em-fg"><label>Phone</label><input id="wze_phone" value="${esc(holder.accPhone)}"></div>
        <div class="em-fg full"><label>Address</label><input id="wze_addr" value="${esc(holder.accAddress)}"></div>
      </div>
      <div class="em-section">Passengers (${grp.length})</div>
      <div id="wzEditPaxList">${paxHtml}</div>
      <button onclick="wzAddPaxCardInEdit(${bkId})" style="margin-top:8px;width:100%;padding:10px;border-radius:8px;border:1.5px dashed var(--g300);background:var(--white);color:var(--g500);font-size:13px;font-weight:600;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;justify-content:center;gap:6px;transition:all .15s" onmouseover="this.style.borderColor='#E5007D';this.style.color='#E5007D';this.style.background='#FDE8F3'" onmouseout="this.style.borderColor='var(--g300)';this.style.color='var(--g500)';this.style.background='var(--white)'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Passenger</button>
    </div>
    <div class="em-foot">
      <button class="em-cancel" onclick="closeEdit()">Cancel</button>
      <button class="em-save" style="background:#E5007D" onclick="wzSaveEdit(${bkId})">Save Changes</button>
    </div>
  </div>`;
  m.classList.add('show');
}

async function wzSaveEdit(bkId){
  const grp=WZ.filter(x=>x.bkId==bkId);
  if(!grp.length)return;
  const holder=grp.find(x=>x.isHolder)||grp[0];
  const promises=[];

  // Account updates
  const accFields={
    holder_name:(document.getElementById('wze_hfn').value+' '+document.getElementById('wze_hln').value).trim(),
    holder_dob:document.getElementById('wze_dob').value,
    nationality:document.getElementById('wze_nat').value,
    phone:document.getElementById('wze_phone').value,
    email:document.getElementById('wze_accem').value,
    address:document.getElementById('wze_addr').value,
    passport_number:document.getElementById('wze_ppnr').value,
    passport_issued_country:document.getElementById('wze_ppco').value,
    passport_expiry:document.getElementById('wze_ppex').value
  };
  Object.entries(accFields).forEach(([field,value])=>{
    promises.push(fetch('?action=wz_update_account',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:holder.accId,field:field,value:value})}));
  });

  // Booking updates
  const bkFields={
    pnr:document.getElementById('wze_pnr').value,
    flight_number:document.getElementById('wze_fl').value,
    flight_date:document.getElementById('wze_dt').value,
    origin:document.getElementById('wze_orig').value,
    destination:document.getElementById('wze_dest').value,
    reason:document.getElementById('wze_rsn').value,
    distance_km:document.getElementById('wze_dist').value
  };
  Object.entries(bkFields).forEach(([field,value])=>{
    promises.push(fetch('?action=wz_update_booking',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:bkId,field:field,value:value})}));
  });

  // Passenger updates
  grp.forEach((r,i)=>{
    const fnEl=document.getElementById('wze_fn_'+i);
    if(!fnEl)return;
    const pFields={
      first_name:fnEl.value,
      last_name:document.getElementById('wze_ln_'+i).value,
      dob:document.getElementById('wze_pdob_'+i)?.value||'',
      nationality:document.getElementById('wze_pnat_'+i)?.value||'',
      passport_number:document.getElementById('wze_pppnr_'+i)?.value||'',
      passport_issued_country:document.getElementById('wze_pppco_'+i)?.value||'',
      passport_expiry:document.getElementById('wze_pppex_'+i)?.value||'',
      email:document.getElementById('wze_em_'+i).value,
      phone:document.getElementById('wze_pph_'+i)?.value||'',
      address:document.getElementById('wze_paddr_'+i)?.value||'',
      seat:document.getElementById('wze_seat_'+i).value,
      checkin_status:document.getElementById('wze_chk_'+i)?.value||''
    };
    Object.entries(pFields).forEach(([field,value])=>{
      promises.push(fetch('?action=wz_update_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:r.id,field:field,value:value})}));
    });
    r.fn=pFields.first_name;r.ln=pFields.last_name;r.email=pFields.email;r.seat=pFields.seat;r.checkin=pFields.checkin_status;
    r.paxDob=pFields.dob;r.paxNat=pFields.nationality;r.paxPpNr=pFields.passport_number;r.paxPpCo=pFields.passport_issued_country;r.paxPpExp=pFields.passport_expiry;r.paxPhone=pFields.phone;r.paxAddr=pFields.address;
  });

  // Update local data for account/booking
  grp.forEach(r=>{
    r.holderName=accFields.holder_name;r.holderDob=accFields.holder_dob;r.accNat=accFields.nationality;
    r.accPhone=accFields.phone;r.accEmail=accFields.email;r.accAddress=accFields.address;
    r.accPpNr=accFields.passport_number;r.accPpCo=accFields.passport_issued_country;r.accPpExp=accFields.passport_expiry;
    r.pnr=bkFields.pnr;r.fl=bkFields.flight_number;r.dt=bkFields.flight_date;
    r.origin=bkFields.origin;r.dest=bkFields.destination;r.reason=bkFields.reason;
    r.dist=parseInt(bkFields.distance_km)||0;r.compKm=r.dist||calcDist(r.origin,r.dest)||0;
  });

  // Save new passengers added inline
  const wzNewCards=document.querySelectorAll('.wzNewPaxCard');
  let wzNewPaxCount=0;
  for(const card of wzNewCards){
    const idx=card.getAttribute('data-idx');
    const fn=(document.getElementById('wze_newf_'+idx)?.value||'').trim();
    const ln=(document.getElementById('wze_newl_'+idx)?.value||'').trim();
    const em=(document.getElementById('wze_newem_'+idx)?.value||'').trim();
    const seat=(document.getElementById('wze_newseat_'+idx)?.value||'').trim();
    if(!fn||!ln)continue;
    const holder=grp.find(x=>x.isHolder)||grp[0];
    await fetch('?action=wz_add_customer',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({
      account_number:holder.accNr,
      pnr:bkFields.pnr||holder.pnr,
      flight_number:bkFields.flight_number||holder.fl,
      flight_date:bkFields.flight_date||holder.dt,
      origin:bkFields.origin||holder.origin,
      destination:bkFields.destination||holder.dest,
      passengers:[{first_name:fn,last_name:ln,email:em,seat:seat}]
    })});
    wzNewPaxCount++;
  }

  await Promise.all(promises);
  closeEdit();renderWz();
  if(wzNewPaxCount>0){toast('Saved + '+wzNewPaxCount+' new passenger(s)!');setTimeout(()=>location.reload(),500)}
  else{toast('Booking updated!')}
}

// WZ History tooltip — shows mail + status history for all passengers in booking
let wzFloatTip=null;let wzFloatTimeout=null;
const wzHistCache={};
function wzHideHist(){wzFloatTimeout=setTimeout(()=>{if(wzFloatTip){wzFloatTip.remove();wzFloatTip=null}},200)}
async function wzShowHist(ev,bkId){
  clearTimeout(wzFloatTimeout);
  if(wzFloatTip){wzFloatTip.remove();wzFloatTip=null}
  const rect=ev.currentTarget.getBoundingClientRect();
  const tip=document.createElement('div');tip.className='float-tip';
  let top=rect.bottom+8;let left=rect.left+rect.width/2-220;
  if(left<8)left=8;if(left+460>window.innerWidth)left=window.innerWidth-468;
  if(top+300>window.innerHeight)top=rect.top-310;
  tip.style.top=top+'px';tip.style.left=left+'px';
  tip.innerHTML='<div style="color:var(--g400);font-size:10px;text-align:center">Loading history...</div>';
  tip.onmouseenter=()=>clearTimeout(wzFloatTimeout);
  tip.onmouseleave=()=>wzHideHist();
  document.body.appendChild(tip);wzFloatTip=tip;

  const ck='wzhist_'+bkId;
  if(wzHistCache[ck]){tip.innerHTML=wzHistCache[ck];return}
  try{
    // Get all passenger IDs in this booking
    const paxIds=WZ.filter(x=>x.bkId==bkId).map(x=>x.id);
    // Fetch history for all passengers
    let allMails=[];let allStatuses=[];
    for(const pid of paxIds){
      const res=await fetch('?action=get_history',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:pid})});
      const j=await res.json();if(!j.ok)continue;
      const paxR=WZ.find(x=>x.id==pid);
      const pName=paxR?(paxR.fn+' '+paxR.ln).trim():'Passenger #'+pid;
      j.mails.forEach(m=>{m._pax=pName;allMails.push(m)});
      j.statuses.forEach(s=>{s._pax=pName;allStatuses.push(s)});
    }
    allMails.sort((a,b)=>new Date(b.sent_at)-new Date(a.sent_at));
    allStatuses.sort((a,b)=>new Date(b.changed_at)-new Date(a.changed_at));

    let mailHtml='<div class="ht-title"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>Mail History</div>';
    if(allMails.length===0)mailHtml+='<div class="ht-empty">No mails sent</div>';
    else allMails.forEach(m=>{mailHtml+=`<div class="ht-row"><span class="ht-dot mail"></span><div class="ht-info"><span class="ht-val">${m.template_label} <span style="font-size:9px;color:var(--g400)">(${m._pax})</span></span><span class="ht-date">${fDT(m.sent_at)}</span></div></div>`});

    let stHtml='<div class="ht-title"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>Status History</div>';
    if(allStatuses.length===0)stHtml+='<div class="ht-empty">No changes</div>';
    else allStatuses.forEach(s=>{stHtml+=`<div class="ht-row"><span class="ht-dot status"></span><div class="ht-info"><span class="ht-val">${SLB[s.status]||s.status} <span style="font-size:9px;color:var(--g400)">(${s._pax})</span></span><span class="ht-date">${fDT(s.changed_at)}</span></div></div>`});

    const html=`<div class="ft-cols"><div class="ft-col">${mailHtml}</div><div class="ft-col" style="border-left:1px solid var(--g100);padding-left:16px">${stHtml}</div></div>`;
    wzHistCache[ck]=html;
    if(wzFloatTip===tip)tip.innerHTML=html;
  }catch(e){if(wzFloatTip===tip)tip.innerHTML='<div class="ht-empty">Failed to load</div>'}
}

async function wzDelPaxInEdit(id){
  if(!confirm('Delete this passenger?'))return;
  await fetch('?action=wz_delete_passenger',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id})});
  const idx=WZ.findIndex(x=>x.id==id);if(idx>-1)WZ.splice(idx,1);
  const idx2=wzFlat.findIndex(x=>x.id==id);if(idx2>-1)wzFlat.splice(idx2,1);
  closeEdit();renderWz();toast('Passenger deleted');
}

let wzEditNewIdx=100;
function wzAddPaxCardInEdit(bkId){
  const idx=wzEditNewIdx++;
  const list=document.getElementById('wzEditPaxList');
  const div=document.createElement('div');
  div.className='wzNewPaxCard';
  div.setAttribute('data-idx',idx);
  div.style.cssText='background:var(--g50);border:1px solid var(--g200);border-radius:10px;padding:16px;margin-bottom:12px';
  div.innerHTML=`
    <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
      <span style="font-size:14px;font-weight:800;color:var(--g500)">New Passenger</span>
      <span style="font-size:9px;font-weight:700;text-transform:uppercase;color:var(--g400);background:var(--g100);padding:2px 6px;border-radius:4px">Sub</span>
      <button onclick="this.closest('.wzNewPaxCard').remove()" style="margin-left:auto;padding:4px 10px;border-radius:6px;border:1.5px solid rgba(220,38,38,.3);background:#FEF2F2;color:#DC2626;font-size:10px;font-weight:700;cursor:pointer;font-family:'DM Sans',sans-serif;display:flex;align-items:center;gap:4px"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>Remove</button>
    </div>
    <div class="em-grid">
      <div class="em-fg"><label>First Name *</label><input id="wze_newf_${idx}"></div>
      <div class="em-fg"><label>Last Name *</label><input id="wze_newl_${idx}"></div>
      <div class="em-fg"><label>Date of Birth</label><input type="date" id="wze_newdob_${idx}"></div>
      <div class="em-fg"><label>Nationality</label><input id="wze_newnat_${idx}"></div>
      <div class="em-fg"><label>Passport Number</label><input id="wze_newppnr_${idx}"></div>
      <div class="em-fg"><label>Passport Country</label><input id="wze_newppco_${idx}"></div>
      <div class="em-fg"><label>Passport Expiry</label><input type="date" id="wze_newppex_${idx}"></div>
      <div class="em-fg"><label>Email</label><input id="wze_newem_${idx}" type="email"></div>
      <div class="em-fg"><label>Phone</label><input id="wze_newph_${idx}"></div>
      <div class="em-fg full"><label>Address</label><input id="wze_newaddr_${idx}"></div>
      <div class="em-fg"><label>Seat</label><input id="wze_newseat_${idx}"></div>
      <div class="em-fg"><label>Checkin Status</label>
        <select id="wze_newchk_${idx}" style="height:38px;border:1.5px solid var(--g200);border-radius:8px;padding:0 12px;font-size:13px;font-family:'DM Sans',sans-serif;color:var(--navy);outline:none;background:var(--white)">
          <option value="">—</option><option value="checked_in">Checked In</option><option value="not_checked_in">Not Checked In</option>
        </select>
      </div>
    </div>`;
  list.appendChild(div);
  div.scrollIntoView({behavior:'smooth',block:'center'});
}

// ===== RENDER TABLE =====
function wzRenderTable(data){
  const tb=document.getElementById('wzTB');
  let h='';
  // Group by booking (pnr+fl+dt)
  const groups={};const groupOrder=[];
  data.forEach(r=>{
    const gk=r.pnr+'|'+r.fl+'|'+r.dt+'|'+r.accId;
    if(!groups[gk]){groups[gk]=[];groupOrder.push(gk)}
    groups[gk].push(r);
  });
  groupOrder.forEach((gk,gi)=>{
    const grp=groups[gk];
    const holder=grp.find(x=>x.isHolder)||grp[0];
    const mainPax=grp.find(x=>x.isHolder)||grp[0];
    const subs=grp.filter(x=>!x.isHolder);
    const wzGrp=grp;
    const wzUrl=wzGenUrl(holder,wzGrp);

    // === ROW 1: HOLDER (account-level) ===
    const wzHasSubs=subs.length>0;
    h+=`<tr style="border-top:6px solid rgba(229,0,125,0.28);background:var(--white)">`;
    // Checkbox — only on holder
    h+=`<td><input type="checkbox" class="row-cb" ${wzSelected.has(holder.id)?'checked':''} onchange="wzToggleSel(${holder.id},this.checked)"></td>`;
    // ID
    h+=`<td style="font-size:10px;color:var(--g500)">${k(holder.id)}</td>`;
    // Link
    h+=`<td><span style="display:flex;align-items:center;gap:3px;white-space:nowrap"><a href="${wzUrl}" target="_blank" class="lnk-b" style="background:#FDE8F3;color:#E5007D">Open</a><button class="lnk-c" onclick="event.preventDefault();cp('${wzUrl.replace(/'/g,"\\'")}')" title="Copy link">📋</button></span></td>`;
    // Acc Nr
    h+=`<td style="font-size:10px;color:var(--g500)">${k(holder.accNr)}</td>`;
    // First/Last Name — holder name with badge
    h+=`<td class="nm">${k(holder.holderName||holder.fn)}<span class="mbdg" style="background:#FDE8F3;color:#E5007D;margin-left:4px">Holder</span></td>`;
    h+=`<td class="nm"></td>`;
    // Birth, Nationality
    h+=`<td style="font-size:10px;color:var(--g500)">${k([fD(holder.holderDob),holder.accNat].filter(Boolean).join(', '))}</td>`;
    // Passport
    h+=`<td style="font-size:10px;color:var(--g500)">${k([holder.accPpNr,holder.accPpCo,fD(holder.accPpExp)].filter(Boolean).join(', '))}</td>`;
    // Email (account)
    h+=`<td style="font-size:11px;color:var(--g500)">${k(holder.accEmail)}</td>`;
    // Phone
    h+=`<td style="font-size:11px;color:var(--g500)">${holder.accPhone?`<span class="cp" title="${esc(holder.accPhone)}" onclick="cp('${esc(holder.accPhone)}')">${(holder.accPhone.match(/^\+?\d{1,3}/)||[''])[0]}</span>`:''}</td>`;
    // Address
    h+=`<td class="addr">${holder.accAddress?`<span class="cp" title="${esc(holder.accAddress)}" onclick="cp('${esc(holder.accAddress)}')">${holder.accAddress.split(',').pop().trim()}</span>`:''}</td>`;
    // Booking Ref
    h+=`<td class="bk" style="color:#E5007D">${k(holder.pnr)}</td>`;
    // Flight Number
    h+=`<td class="fl">${k(holder.fl)}</td>`;
    // Seat — empty on holder
    h+=`<td></td>`;
    // Checkin — empty on holder
    h+=`<td></td>`;
    // Date
    h+=`<td class="dt">${k(fD(holder.dt))}</td>`;
    // Departure
    h+=`<td>${k(holder.origin)}</td>`;
    // Arrival
    h+=`<td>${k(holder.dest)}</td>`;
    // Reason
    h+=`<td>${holder.reason?`<span class="rtag ${rC(holder.reason)}">${fmtReason(holder.reason)}</span>`:''}</td>`;
    // Distance
    h+=`<td class="dst">${holder.dist?k(holder.dist.toLocaleString()+' km'):''}</td>`;
    // Compensation — empty on holder
    h+=`<td></td>`;
    // AirHelp
    const hAh=holder.ah;const hAhTip=(holder.ahNote||'').replace(/"/g,'&quot;');
    h+=`<td>${hAh==='ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#ECFDF5;color:#059669" title="${hAhTip}">ELIGIBLE</span>`:hAh==='NOT ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#FEF2F2;color:#DC2626" title="${hAhTip}">NOT ELIGIBLE</span>`:''}</td>`;
    // Source
    h+=`<td>${holder.ahSrc?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:600;background:${holder.ahSrc==='SELECTED'?'#EFF6FF':'#FDF4FF'};color:${holder.ahSrc==='SELECTED'?'#2563EB':'#9333EA'}">${holder.ahSrc}</span>`:''}</td>`;
    // ID Doc, Travel Doc, Assignment — empty on holder
    h+=`<td></td><td></td><td></td>`;
    // Mail Sablon, Mail, Claim Mail — empty on holder
    h+=`<td></td><td></td><td></td>`;
    // Remarketing, Status, Beadva, Jegyzetek — empty on holder
    h+=`<td></td><td></td><td></td><td></td>`;
    // Updated — empty on holder row
    h+=`<td></td>`;
    // Edit button — only on holder
    h+=`<td><button class="edit-btn" onclick="wzOpenEdit(${holder.bkId})"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg></button></td>`;
    h+=`</tr>`;

    // === ROW 2: MAIN PASSENGER ===
    const mainPaxStyle=wzHasSubs?'background:#FAFBFC':'border-bottom:6px solid rgba(229,0,125,0.28);background:#FAFBFC';
    h+=`<tr style="${mainPaxStyle}">`;
    h+=`<td></td>`; // no checkbox
    h+=`<td style="font-size:10px;color:var(--g500)">${k(mainPax.id)}</td>`;
    h+=`<td></td>`; // no link
    h+=`<td></td>`; // no acc nr
    // First Name with indent + Main badge
    h+=`<td class="nm"><span class="sc-c" style="margin-right:2px">└</span>${k(mainPax.fn||mainPax.paxName.split(' ')[0]||'')}<span class="mbdg" style="background:#FDE8F3;color:#E5007D;margin-left:4px">Main</span></td>`;
    h+=`<td class="nm">${k(mainPax.ln||mainPax.paxName.split(' ').slice(1).join(' ')||'')}</td>`;
    // Birth/Nationality (passenger-level)
    h+=`<td style="font-size:10px;color:var(--g500)">${k([fD(mainPax.paxDob),mainPax.paxNat].filter(Boolean).join(', '))}</td>`;
    // Passport (passenger-level)
    h+=`<td style="font-size:10px;color:var(--g500)">${k([mainPax.paxPpNr,mainPax.paxPpCo,fD(mainPax.paxPpExp)].filter(Boolean).join(', '))}</td>`;
    // Email (passenger)
    h+=`<td style="font-size:11px;color:var(--g500)">${k(mainPax.email)}</td>`;
    // Phone (passenger-level)
    h+=`<td style="font-size:11px;color:var(--g500)">${mainPax.paxPhone?`<span class="cp" title="${esc(mainPax.paxPhone)}" onclick="cp('${esc(mainPax.paxPhone)}')">${(mainPax.paxPhone.match(/^\+?\d{1,3}/)||[''])[0]}</span>`:''}</td>`;
    // Address (passenger-level)
    h+=`<td class="addr">${mainPax.paxAddr?`<span class="cp" title="${esc(mainPax.paxAddr)}" onclick="cp('${esc(mainPax.paxAddr)}')">${mainPax.paxAddr.split(',').pop().trim()}</span>`:''}</td>`;
    // Booking Ref
    h+=`<td class="bk" style="color:#E5007D">${k(mainPax.pnr)}</td>`;
    // Flight Number
    h+=`<td class="fl">${k(mainPax.fl)}</td>`;
    // Seat
    h+=`<td>${k(mainPax.seat)}</td>`;
    // Checkin Status
    h+=`<td style="font-size:10px">${mainPax.checkin?`<span style="display:inline-block;padding:2px 6px;border-radius:5px;font-size:9px;font-weight:700;background:${mainPax.checkin==='checked_in'?'var(--green-light)':'var(--g100)'};color:${mainPax.checkin==='checked_in'?'var(--green)':'var(--g500)'}">${mainPax.checkin.replace('_',' ')}</span>`:''}</td>`;
    // Date
    h+=`<td class="dt">${k(fD(mainPax.dt))}</td>`;
    // Departure
    h+=`<td>${k(mainPax.origin)}</td>`;
    // Arrival
    h+=`<td>${k(mainPax.dest)}</td>`;
    // Reason
    h+=`<td>${mainPax.reason?`<span class="rtag ${rC(mainPax.reason)}">${fmtReason(mainPax.reason)}</span>`:''}</td>`;
    // Distance
    h+=`<td class="dst">${mainPax.dist?k(mainPax.dist.toLocaleString()+' km'):''}</td>`;
    // Compensation
    h+=`<td>${mainPax.compKm?`<span class="comp">${calcComp(mainPax.compKm)}</span>`:''}</td>`;
    // AirHelp
    const ahVal=mainPax.ah;const ahTip=(mainPax.ahNote||'').replace(/"/g,'&quot;');
    h+=`<td>${ahVal==='ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#ECFDF5;color:#059669" title="${ahTip}">ELIGIBLE</span>`:ahVal==='NOT ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#FEF2F2;color:#DC2626" title="${ahTip}">NOT ELIGIBLE</span>`:''}</td>`;
    // Source
    h+=`<td>${mainPax.ahSrc?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:600;background:${mainPax.ahSrc==='SELECTED'?'#EFF6FF':'#FDF4FF'};color:${mainPax.ahSrc==='SELECTED'?'#2563EB':'#9333EA'}">${mainPax.ahSrc}</span>`:''}</td>`;
    // ID Doc, Travel Doc, Assignment
    h+=`<td>${wzDocC(mainPax.id,'id',mainPax.idF,mainPax.idP,mainPax.idV)}</td>`;
    h+=`<td>${wzDocC(mainPax.id,'travel',mainPax.trF,mainPax.trP,mainPax.trV)}</td>`;
    h+=`<td>${wzAsC(mainPax.id,mainPax.asF,mainPax.asP,!!mainPax.accAddress)}</td>`;
    // Mail Sablon
    h+=`<td>${wzMailTplSel(mainPax.id,mainPax.mt)}</td>`;
    // Mail (Send)
    h+=`<td>${wzMailC(mainPax.id,mainPax.ms,mainPax.mt,mainPax.mts)}</td>`;
    // Claim Mail
    h+=`<td>${wzClaimMailBtn(mainPax.id)}</td>`;
    // Status
    h+=`<td>${wzStBdg(mainPax.id,mainPax.st)}</td>`;
    // Jegyzetek
    h+=`<td>${wzNotesC(mainPax.id,mainPax.notes)}</td>`;
    // Updated
    h+=`<td class="dt" onmouseenter="wzShowHist(event,${mainPax.bkId})" onmouseleave="wzHideHist()" style="cursor:pointer">${k(fDT(mainPax.upd))}</td>`;
    // Edit — empty on main
    h+=`<td></td>`;
    h+=`</tr>`;

    // === ROW 3+: SUB PASSENGERS ===
    subs.forEach((r,si)=>{
      const isLastSub=si===subs.length-1;
      const subStyle=isLastSub?'background:#FAFBFC;border-bottom:6px solid rgba(229,0,125,0.28)':'background:#FAFBFC';
      h+=`<tr style="${subStyle}">`;
      h+=`<td></td>`; // no checkbox
      h+=`<td style="font-size:10px;color:var(--g500)">${k(r.id)}</td>`;
      h+=`<td></td>`; // no link
      h+=`<td></td>`; // no acc nr
      // First Name with double indent + Sub badge
      h+=`<td class="nm"><span class="sc-c" style="margin-right:2px">└└</span>${k(r.fn||r.paxName.split(' ')[0]||'')}<span class="mbdg" style="background:var(--g100);color:var(--g500);margin-left:4px">Sub</span></td>`;
      h+=`<td class="nm">${k(r.ln||r.paxName.split(' ').slice(1).join(' ')||'')}</td>`;
      // Birth/Nationality (passenger-level)
      h+=`<td style="font-size:10px;color:var(--g500)">${k([fD(r.paxDob),r.paxNat].filter(Boolean).join(', '))}</td>`;
      // Passport (passenger-level)
      h+=`<td style="font-size:10px;color:var(--g500)">${k([r.paxPpNr,r.paxPpCo,fD(r.paxPpExp)].filter(Boolean).join(', '))}</td>`;
      // Email
      h+=`<td style="font-size:11px;color:var(--g500)">${k(r.email)}</td>`;
      // Phone (passenger-level)
      h+=`<td style="font-size:11px;color:var(--g500)">${r.paxPhone?`<span class="cp" title="${esc(r.paxPhone)}" onclick="cp('${esc(r.paxPhone)}')">${(r.paxPhone.match(/^\+?\d{1,3}/)||[''])[0]}</span>`:''}</td>`;
      // Address (passenger-level)
      h+=`<td class="addr">${r.paxAddr?`<span class="cp" title="${esc(r.paxAddr)}" onclick="cp('${esc(r.paxAddr)}')">${r.paxAddr.split(',').pop().trim()}</span>`:''}</td>`;
      // Booking Ref
      h+=`<td class="bk" style="color:#E5007D">${k(r.pnr)}</td>`;
      // Flight Number
      h+=`<td class="fl">${k(r.fl)}</td>`;
      // Seat
      h+=`<td>${k(r.seat)}</td>`;
      // Checkin
      h+=`<td style="font-size:10px">${r.checkin?`<span style="display:inline-block;padding:2px 6px;border-radius:5px;font-size:9px;font-weight:700;background:${r.checkin==='checked_in'?'var(--green-light)':'var(--g100)'};color:${r.checkin==='checked_in'?'var(--green)':'var(--g500)'}">${r.checkin.replace('_',' ')}</span>`:''}</td>`;
      // Date
      h+=`<td class="dt">${k(fD(r.dt))}</td>`;
      // Departure
      h+=`<td>${k(r.origin)}</td>`;
      // Arrival
      h+=`<td>${k(r.dest)}</td>`;
      // Reason
      h+=`<td>${r.reason?`<span class="rtag ${rC(r.reason)}">${fmtReason(r.reason)}</span>`:''}</td>`;
      // Distance
      h+=`<td class="dst">${r.dist?k(r.dist.toLocaleString()+' km'):''}</td>`;
      // Compensation
      h+=`<td>${r.compKm?`<span class="comp">${calcComp(r.compKm)}</span>`:''}</td>`;
      // AirHelp
      const sAh=r.ah;const sAhTip=(r.ahNote||'').replace(/"/g,'&quot;');
      h+=`<td>${sAh==='ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#ECFDF5;color:#059669" title="${sAhTip}">ELIGIBLE</span>`:sAh==='NOT ELIGIBLE'?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#FEF2F2;color:#DC2626" title="${sAhTip}">NOT ELIGIBLE</span>`:''}</td>`;
      // Source
      h+=`<td>${r.ahSrc?`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:600;background:${r.ahSrc==='SELECTED'?'#EFF6FF':'#FDF4FF'};color:${r.ahSrc==='SELECTED'?'#2563EB':'#9333EA'}">${r.ahSrc}</span>`:''}</td>`;
      // ID Doc, Travel Doc, Assignment
      h+=`<td>${wzDocC(r.id,'id',r.idF,r.idP,r.idV)}</td>`;
      h+=`<td>${wzDocC(r.id,'travel',r.trF,r.trP,r.trV)}</td>`;
      h+=`<td>${wzAsC(r.id,r.asF,r.asP,!!r.accAddress)}</td>`;
      // Mail Sablon, Mail, Claim Mail — empty for sub
      h+=`<td></td><td></td><td></td>`;
      // Status — only on main
      h+=`<td></td>`;
      // Jegyzetek — empty on sub
      h+=`<td></td>`;
      // Updated — empty on sub
      h+=`<td></td>`;
      // Edit — empty
      h+=`<td></td>`;
      h+=`</tr>`;
    });
  });
  tb.innerHTML=h;
}

// Pagination for WZ
function wzRenderPag(total){
  const pages=Math.ceil(total/WZ_PER_PAGE);
  const area=document.getElementById('wzPagArea');
  if(pages<=1){area.innerHTML=`<span class="pag-info">${total} passengers</span>`;return}
  let ph=`<button class="pag-btn" onclick="wzGoPage(${wzCurPage-1})" ${wzCurPage<=1?'disabled':''}>&lt;</button>`;
  const start=Math.max(1,wzCurPage-3);const end=Math.min(pages,wzCurPage+3);
  if(start>1)ph+=`<button class="pag-btn" onclick="wzGoPage(1)">1</button>`;
  if(start>2)ph+=`<span class="pag-info">...</span>`;
  for(let i=start;i<=end;i++)ph+=`<button class="pag-btn ${i===wzCurPage?'act':''}" onclick="wzGoPage(${i})">${i}</button>`;
  if(end<pages-1)ph+=`<span class="pag-info">...</span>`;
  if(end<pages)ph+=`<button class="pag-btn" onclick="wzGoPage(${pages})">${pages}</button>`;
  ph+=`<button class="pag-btn" onclick="wzGoPage(${wzCurPage+1})" ${wzCurPage>=pages?'disabled':''}>&gt;</button>`;
  ph+=`<span class="pag-info">${(wzCurPage-1)*WZ_PER_PAGE+1}–${Math.min(wzCurPage*WZ_PER_PAGE,total)} of ${total}</span>`;
  area.innerHTML=ph;
}
function wzGoPage(p){const pages=Math.ceil(wzFilteredData.length/WZ_PER_PAGE);if(p<1||p>pages)return;wzCurPage=p;wzRenderTable(wzGetPageData());wzRenderPag(wzFilteredData.length)}

// Main render function
function wzUpdateStats(){
  const d=WZ;
  document.getElementById('wzST').textContent=d.length;
  let total=0;d.forEach(r=>{if(r.compKm)total+=cc2(r.compKm)});
  document.getElementById('wzSA').textContent='€'+total.toLocaleString();
  document.getElementById('wzSI').textContent=d.filter(r=>r.idF).length;
  document.getElementById('wzSB').textContent=d.filter(r=>r.st.startsWith('beadva')).length;
}

function renderWz(){
  const q=(document.getElementById('wzSearch')?.value||'').toLowerCase();
  const stF=document.getElementById('wzStatusFilter')?.value||'';
  const rsnF=document.getElementById('wzReasonFilter')?.value||'';
  const idF=document.getElementById('wzIdFilter')?.value||'';
  const ckF=document.getElementById('wzCheckinFilter')?.value||'';
  let data=[...WZ];
  if(stF){data=data.filter(r=>r.st===stF)}
  if(rsnF==='delay'){data=data.filter(r=>r.reason&&/^\d+/.test(r.reason.trim()))}
  if(rsnF==='cancel'){data=data.filter(r=>r.reason&&r.reason.toLowerCase().includes('cancel'))}
  if(rsnF==='none'){data=data.filter(r=>!r.reason)}
  if(idF==='yes'){data=data.filter(r=>r.idF)}
  if(idF==='no'){data=data.filter(r=>!r.idF)}
  if(ckF){data=data.filter(r=>r.checkin===ckF)}
  if(q){data=data.filter(r=>(r.fn+' '+r.ln+' '+r.paxName).toLowerCase().includes(q)||r.pnr.toLowerCase().includes(q)||r.fl.toLowerCase().includes(q)||r.origin.toLowerCase().includes(q)||r.dest.toLowerCase().includes(q)||r.accNr.toLowerCase().includes(q)||r.email.toLowerCase().includes(q))}
  wzFilteredData=data;
  document.getElementById('wzCnt').textContent=data.length;
  wzCurPage=1;
  wzRenderTable(wzGetPageData());
  wzRenderPag(data.length);
  wzUpdateStats();
}

// Init — empty state, waiting for airline selection

// ===== REMARKETING PAGE =====
let rmData={logs:[],active:[],tracking:[],subPax:[]};
let rmLoaded=false;
const RM_PER_PAGE=50;
let rmCurPage=1;
let rmFilteredData=[];

async function renderRmPage(forceReload){
  if(!rmLoaded||forceReload){
    try{
      const res=await fetch('?action=get_all_remarketing');
      const j=await res.json();
      if(j.ok){rmData=j;rmLoaded=true}
    }catch(e){console.error('Failed to load remarketing data',e)}
  }
  // Build tracking lookup: {source_customerid: {open:{first_at,last_at,cnt}, click:{...}}}
  const trkMap={};
  (rmData.tracking||[]).forEach(t=>{
    const key=t.source==='wz_passengers'?'wz_'+t.customer_id:String(t.customer_id);
    if(!trkMap[key])trkMap[key]={};
    trkMap[key][t.event_type]={first:t.first_at,last:t.last_at,cnt:parseInt(t.cnt)};
  });
  // Build logs lookup: {source_customerid: {1:log, 2:log, ...}}
  const logMap={};
  (rmData.logs||[]).forEach(l=>{
    const key=l.source==='wz_passengers'?'wz_'+l.customer_id:String(l.customer_id);
    if(!logMap[key])logMap[key]={};
    logMap[key][l.step]=l;
  });
  // Build subPax lookup: {booking_ref: [{...}]}
  const spMap={};
  (rmData.subPax||[]).forEach(p=>{
    if(!spMap[p.booking_ref])spMap[p.booking_ref]=[];
    spMap[p.booking_ref].push(p);
  });
  // Build combined list from active
  let list=(rmData.active||[]).map(a=>{
    const src=a.source||'customers';
    const key=src==='wz_passengers'?'wz_'+a.id:String(a.id);
    const trk=trkMap[key]||{};
    const logs=logMap[key]||{};
    const subs=spMap[a.booking_ref]||[];
    const allHaveId=subs.length>0&&subs.every(s=>s.id_doc_path);
    return{
      id:a.id,source:src,
      name:(a.first_name||'')+' '+(a.last_name||''),
      email:a.email||'',
      booking:a.booking_ref||'',
      flight:a.flight_number||'',
      route:(a.departure||'')+' → '+(a.arrival||''),
      airline:a.airline||'easyJet',
      claimSent:a.claim_mail_sent_at||'',
      active:parseInt(a.remarketing_active)||0,
      stoppedAt:a.remarketing_stopped_at||'',
      stoppedReason:a.remarketing_stopped_reason||'',
      idDoc:!!a.id_doc_path,
      allIdDone:allHaveId,
      status:a.status||'',
      sentCount:parseInt(a.sent_count)||0,
      open:trk.open||null,
      click:trk.click||null,
      steps:logs,
      subs:subs
    };
  });
  // Filter
  const q=(document.getElementById('rmSearch')?.value||'').toLowerCase();
  const airF=document.getElementById('rmAirlineFilter')?.value||'';
  const idF=document.getElementById('rmIdFilter')?.value||'';
  const statusF=document.getElementById('rmStatusFilter')?.value||'';
  const stepF=document.getElementById('rmStepFilter')?.value||'';
  if(q){list=list.filter(r=>(r.name+r.email+r.booking+r.flight+r.route+r.airline).toLowerCase().includes(q))}
  if(airF){list=list.filter(r=>r.airline===airF)}
  if(idF==='yes'){list=list.filter(r=>r.idDoc)}
  if(idF==='no'){list=list.filter(r=>!r.idDoc)}
  if(statusF==='active'){list=list.filter(r=>r.active)}
  if(statusF==='stopped'){list=list.filter(r=>!r.active)}
  if(stepF){list=list.filter(r=>r.steps[stepF])}
  // Sort by claim sent date descending (newest first)
  list.sort((a,b)=>(b.claimSent||'').localeCompare(a.claimSent||''));
  rmFilteredData=list;
  // Stats
  const allList=(rmData.active||[]);
  document.getElementById('rmActCnt').textContent=allList.filter(a=>parseInt(a.remarketing_active)).length;
  document.getElementById('rmSentCnt').textContent=(rmData.logs||[]).filter(l=>l.send_ok==='1'||l.send_ok===1).length;
  document.getElementById('rmConvCnt').textContent=allList.filter(a=>a.id_doc_path).length;
  document.getElementById('rmPendCnt').textContent=allList.filter(a=>!parseInt(a.remarketing_active)&&a.claim_mail_sent_at).length;
  // Paginate
  const pages=Math.ceil(list.length/RM_PER_PAGE);
  if(rmCurPage>pages)rmCurPage=1;
  const start=(rmCurPage-1)*RM_PER_PAGE;
  const pageData=list.slice(start,start+RM_PER_PAGE);
  // Render table
  const tb=document.getElementById('rmTB');
  if(!tb)return;
  if(pageData.length===0){tb.innerHTML='<tr><td colspan="16" style="text-align:center;padding:40px;color:var(--g400)">No remarketing data found. Send claim emails first.</td></tr>';renderRmPag(list.length);return;}
  let html='';
  pageData.forEach(r=>{
    const airColor=r.airline==='Wizz Air'?'#E5007D':'#FF6B35';
    const airBg=r.airline==='Wizz Air'?'#FDE8F3':'#FFF0EB';
    const openBdg=r.open?`<span style="color:#22C55E;font-weight:700" title="First: ${r.open.first}\nLast: ${r.open.last}">✓ ${r.open.cnt}x</span>`:'<span style="color:var(--g300)">—</span>';
    const clickBdg=r.click?`<span style="color:#3B82F6;font-weight:700" title="First: ${r.click.first}\nLast: ${r.click.last}">✓ ${r.click.cnt}x</span>`:'<span style="color:var(--g300)">—</span>';
    function stepBdg(n){
      const s=r.steps[n];
      if(!s)return'<span style="color:var(--g300);font-size:10px">—</span>';
      if(s.send_ok==='1'||s.send_ok===1)return`<span style="color:#22C55E;font-weight:700;font-size:10px" title="${s.sent_at}">✓</span>`;
      return`<span style="color:#EF4444;font-weight:700;font-size:10px" title="${s.error_message||'Failed'}">✗</span>`;
    }
    const idBdg=r.idDoc?'<span style="color:#22C55E;font-weight:700">✓ Yes</span>':'<span style="color:var(--g400)">✗ No</span>';
    // Format claim sent as concrete date + relative days
    let claimSentDisplay='—';
    if(r.claimSent){
      const d=new Date(r.claimSent+'Z');
      const date=d.toLocaleDateString('en-GB',{day:'2-digit',month:'short',year:'numeric'});
      const time=d.toLocaleTimeString('en-GB',{hour:'2-digit',minute:'2-digit'});
      const daysAgo=Math.floor((Date.now()-d.getTime())/86400000);
      claimSentDisplay=`${date}<br><span style="color:var(--g400);font-size:10px">${time} (${daysAgo}d ago)</span>`;
    }
    // Status badge: Active / Stopped (with reason)
    let statusBdg;
    if(r.active){
      statusBdg=`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#ECFDF5;color:#22C55E">Active</span>`;
    }else if(r.stoppedAt){
      const stopDate=r.stoppedAt.substring(0,10);
      statusBdg=`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:#FEF2F2;color:#EF4444" title="Stopped: ${stopDate}\nReason: ${esc(r.stoppedReason)}">${esc(r.stoppedReason||'Stopped')}</span>`;
    }else{
      statusBdg=`<span style="display:inline-block;padding:2px 8px;border-radius:5px;font-size:10px;font-weight:700;background:var(--g100);color:var(--g500)">Stopped</span>`;
    }
    const actBtn=r.active
      ?`<button onclick="rmStop(${r.id},'${r.source}')" style="padding:3px 8px;border-radius:5px;border:1px solid var(--g200);background:var(--white);font-size:10px;font-weight:600;color:var(--red);cursor:pointer">Stop</button>`
      :`<button onclick="rmRestart(${r.id},'${r.source}')" style="padding:3px 8px;border-radius:5px;border:1px solid var(--g200);background:var(--white);font-size:10px;font-weight:600;color:var(--green);cursor:pointer">Restart</button>`;
    html+=`<tr style="${!r.active?'opacity:0.7':''}">
      <td class="nm">${esc(r.name)}<br><span style="display:inline-block;padding:1px 6px;border-radius:4px;font-size:9px;font-weight:700;background:${airBg};color:${airColor}">${r.airline}</span></td>
      <td style="font-size:11px">${esc(r.email)}</td>
      <td class="bk">${esc(r.booking)}</td>
      <td class="fl">${esc(r.flight)}</td>
      <td style="font-size:11px">${esc(r.route)}</td>
      <td style="font-size:11px">${claimSentDisplay}</td>
      <td>${openBdg}</td>
      <td>${clickBdg}</td>
      <td>${stepBdg(1)}</td><td>${stepBdg(2)}</td><td>${stepBdg(3)}</td><td>${stepBdg(4)}</td><td>${stepBdg(5)}</td>
      <td>${idBdg}</td>
      <td>${statusBdg}</td>
      <td>${actBtn}</td>
    </tr>`;
  });
  tb.innerHTML=html;
  renderRmPag(list.length);
}

function renderRmPag(total){
  const area=document.getElementById('rmPagArea');
  if(!area)return;
  const pages=Math.ceil(total/RM_PER_PAGE);
  if(pages<=1){area.innerHTML='';return}
  let h=`<button onclick="rmGoPage(${rmCurPage-1})" ${rmCurPage<=1?'disabled':''} class="pg-btn">‹</button>`;
  for(let i=1;i<=pages;i++){h+=`<button onclick="rmGoPage(${i})" class="pg-btn${i===rmCurPage?' act':''}">${i}</button>`}
  h+=`<button onclick="rmGoPage(${rmCurPage+1})" ${rmCurPage>=pages?'disabled':''} class="pg-btn">›</button>`;
  area.innerHTML=h;
}

function rmGoPage(p){const pages=Math.ceil(rmFilteredData.length/RM_PER_PAGE);if(p<1||p>pages)return;rmCurPage=p;renderRmPage()}

async function rmStop(id,source){
  await fetch('?action=stop_remarketing',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,source:source,reason:'Manual stop'})});
  rmLoaded=false;renderRmPage(true);
}

async function rmRestart(id,source){
  await fetch('?action=restart_remarketing',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:id,source:source})});
  rmLoaded=false;renderRmPage(true);
}

</script>
</body>
</html>