<?php
declare(strict_types=1);

require_once __DIR__ . '/lib/tenant.php';
require_once __DIR__ . '/lib/media.php';

$tenant = resolve_tenant_from_host();
if (!$tenant) {
    http_response_code(404);
    echo 'Shop not found. Run setup.php first.';
    exit;
}

$tenantId = (int) $tenant['id'];
$fonts = font_pairing_css((string) $tenant['font_pairing']);

$ps = db()->prepare('SELECT * FROM page_settings WHERE tenant_id = ?');
$ps->execute([$tenantId]);
$page = $ps->fetch() ?: [];

$services = db()->prepare('SELECT * FROM services WHERE tenant_id = ? ORDER BY display_order, id');
$services->execute([$tenantId]);
$serviceRows = $services->fetchAll();

$staff = db()->prepare('SELECT * FROM staff_barbers WHERE tenant_id = ? ORDER BY name');
$staff->execute([$tenantId]);
$staffRows = $staff->fetchAll();

$styles = db()->prepare('SELECT * FROM style_gallery WHERE tenant_id = ? ORDER BY display_order, id');
$styles->execute([$tenantId]);
$styleRows = $styles->fetchAll();

$social = json_decode((string) ($page['social_links'] ?? '{}'), true) ?: [];
$preselect = (int) ($_GET['service'] ?? 0);

$heroMedia = media_public_url((string) ($page['hero_media_path'] ?? ''));
$business = shop_company_name($page, $tenant);
$seoTitle = shop_placeholder_name((string) ($page['seo_title'] ?? ''), $business);
$seoDesc = (string) ($page['seo_description'] ?? '');
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title><?= htmlspecialchars($seoTitle) ?></title>
  <meta name="description" content="<?= htmlspecialchars($seoDesc) ?>">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="<?= htmlspecialchars($fonts['import']) ?>" rel="stylesheet">
  <link rel="stylesheet" href="<?= APP_BASE ?>/assets/public.css?v=20260727c">
  <style>
    :root {
      --primary: <?= htmlspecialchars((string) $tenant['primary_color']) ?>;
      --secondary: <?= htmlspecialchars((string) $tenant['secondary_color']) ?>;
      --font-heading: <?= $fonts['heading'] ?>;
      --font-body: <?= $fonts['body'] ?>;
    }
    /* Booking modals — inline so live works even if public.css is stale/cached */
    .demo-modal {
      display: none !important;
      position: fixed !important;
      inset: 0 !important;
      z-index: 100000 !important;
      place-items: center;
      padding: 1.25rem;
      box-sizing: border-box;
    }
    .demo-modal.is-open {
      display: grid !important;
    }
    .demo-modal-backdrop {
      position: absolute;
      inset: 0;
      background: rgba(10, 12, 18, .66);
    }
    .demo-modal-card {
      position: relative;
      width: min(440px, 100%);
      background: #fff;
      color: #111;
      border-radius: 14px;
      padding: 1.4rem 1.35rem 1.25rem;
      box-shadow: 0 24px 60px rgba(0,0,0,.35);
      z-index: 1;
    }
    .demo-modal-card h3 { margin: 0 0 .65rem; }
    .demo-modal-card .btn { width: 100%; margin-top: .25rem; }
    .book-confirm-kicker {
      margin: 0 0 .35rem;
      font-size: .78rem;
      letter-spacing: .08em;
      text-transform: uppercase;
      color: #1a6b3c;
      font-weight: 700;
    }
    .book-confirm-details {
      margin: 1rem 0 1.1rem;
      display: grid;
      gap: .7rem;
    }
    .book-confirm-details > div {
      display: grid;
      grid-template-columns: 5.5rem 1fr;
      gap: .5rem;
      align-items: baseline;
      padding-bottom: .55rem;
      border-bottom: 1px solid rgba(0,0,0,.08);
    }
    .book-confirm-details dt {
      margin: 0;
      font-size: .78rem;
      color: #666;
      text-transform: uppercase;
      letter-spacing: .04em;
    }
    .book-confirm-details dd {
      margin: 0;
      font-size: 1.05rem;
      font-weight: 700;
      color: #111;
    }
    .book-confirm-note {
      margin: 0 0 1.1rem;
      color: #555;
      font-size: .92rem;
      line-height: 1.4;
    }
    .book-confirm-upsell {
      margin: 0 0 1rem;
      padding: .85rem .9rem;
      border-radius: 10px;
      background: color-mix(in srgb, var(--secondary) 16%, #fff);
      border: 1px solid rgba(0,0,0,.08);
    }
    .book-confirm-upsell p {
      margin: 0 0 .65rem;
      color: #333;
      font-size: .92rem;
      line-height: 1.4;
    }
    .book-confirm-upsell .btn {
      width: 100%;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      box-sizing: border-box;
    }
  </style>
</head>
<body>
<?php if (!empty($page['announcement_enabled']) && !empty($page['announcement_text'])): ?>
  <div class="announce" style="background:<?= htmlspecialchars((string) $page['announcement_bg_color']) ?>">
    <?= htmlspecialchars((string) $page['announcement_text']) ?>
  </div>
<?php endif; ?>

<header class="site-header">
  <a class="logo" href="#top"><?= htmlspecialchars($business) ?></a>
  <nav>
    <a href="#styles">Styles</a>
    <a href="#services">Services</a>
    <a href="#team">Team</a>
    <a href="<?= APP_BASE ?>/shop.php<?= htmlspecialchars(tenant_qs($tenant)) ?>">Shop</a>
    <a href="<?= APP_BASE ?>/client/login.php<?= htmlspecialchars(tenant_qs($tenant)) ?>">My account</a>
    <a href="#book" class="nav-cta">Book</a>
  </nav>
</header>

<section class="hero" id="top" <?= $heroMedia ? 'style="--hero-image:url(' . htmlspecialchars($heroMedia) . ')"' : '' ?>>
  <div class="hero-veil"></div>
  <div class="hero-copy">
    <p class="eyebrow"><?= htmlspecialchars($business) ?></p>
    <h1><?= htmlspecialchars(shop_title_here($page)) ?></h1>
    <p class="lede"><?= htmlspecialchars((string) ($page['hero_subheadline'] ?? '')) ?></p>
    <div class="cta-row">
      <a class="btn" href="<?= htmlspecialchars((string) ($page['cta_link'] ?? '#book')) ?>">
        <?= htmlspecialchars((string) ($page['cta_text'] ?? 'Book Now')) ?>
      </a>
      <a class="btn ghost" href="#styles">Browse looks</a>
    </div>
  </div>
</section>

<section class="section" id="styles">
  <div class="section-head">
    <h2>Styles showcase</h2>
    <p>Pick a look. Book This Look pre-selects the mapped service.</p>
  </div>
  <div class="style-grid">
    <?php foreach ($styleRows as $g):
      $img = media_public_url($g['image_url']);
      $svc = (int) ($g['linked_service_id'] ?? 0);
      ?>
      <article class="style-card">
        <img src="<?= htmlspecialchars($img) ?>" alt="<?= htmlspecialchars($g['style_name']) ?>" loading="lazy">
        <div class="style-meta">
          <span class="pill"><?= htmlspecialchars((string) $g['category_tag']) ?></span>
          <h3><?= htmlspecialchars($g['style_name']) ?></h3>
          <?php if ($svc): ?>
            <a class="btn small" href="#book" data-book-service="<?= $svc ?>">Book This Look</a>
          <?php endif; ?>
        </div>
      </article>
    <?php endforeach; ?>
  </div>
</section>

<section class="section alt" id="services">
  <div class="section-head">
    <h2>Service menu</h2>
    <p>Transparent pricing. Duration included.</p>
  </div>
  <div class="service-list">
    <?php foreach ($serviceRows as $sv): ?>
      <div class="service-item">
        <div>
          <h3><?= htmlspecialchars($sv['name']) ?></h3>
          <p><?= htmlspecialchars((string) $sv['description']) ?></p>
        </div>
        <div class="service-price">
          <strong>$<?= number_format((float) $sv['price'], 2) ?></strong>
          <span><?= (int) $sv['duration_minutes'] ?> min</span>
          <a class="btn small" href="#book" data-book-service="<?= (int) $sv['id'] ?>">Book</a>
        </div>
      </div>
    <?php endforeach; ?>
  </div>
</section>

<section class="section" id="team">
  <div class="section-head">
    <h2>Barbers</h2>
    <p>Specialists behind the chair.</p>
  </div>
  <div class="team-grid">
    <?php foreach ($staffRows as $b): ?>
      <article class="team-card">
        <?php if (!empty($b['profile_image_url'])): ?>
          <img src="<?= htmlspecialchars(media_public_url($b['profile_image_url'])) ?>" alt="">
        <?php else: ?>
          <div class="avatar-fallback"><?= strtoupper(substr($b['name'], 0, 1)) ?></div>
        <?php endif; ?>
        <h3><?= htmlspecialchars($b['name']) ?></h3>
        <p class="role"><?= htmlspecialchars((string) $b['title']) ?></p>
        <p><?= htmlspecialchars((string) ($b['specialties'] ?? '')) ?></p>
      </article>
    <?php endforeach; ?>
  </div>
</section>

<section class="section alt" id="book">
  <div class="section-head">
    <h2>Book an appointment</h2>
    <p>Choose a service and date — pick the first open chair or a specific barber’s time.</p>
  </div>
  <form class="book-form" id="public-book-form">
    <div id="book-flash" class="book-flash" hidden></div>
    <label>Service</label>
    <select name="service_id" id="serviceSelect" required>
      <option value="">Select a service</option>
      <?php foreach ($serviceRows as $sv): ?>
        <option value="<?= (int) $sv['id'] ?>"
                data-duration="<?= (int) $sv['duration_minutes'] ?>"
                data-price="<?= number_format((float) $sv['price'], 2, '.', '') ?>"
                data-name="<?= htmlspecialchars($sv['name'], ENT_QUOTES) ?>"
                <?= $preselect === (int) $sv['id'] ? 'selected' : '' ?>>
          <?= htmlspecialchars($sv['name']) ?> — $<?= number_format((float) $sv['price'], 2) ?> (<?= (int) $sv['duration_minutes'] ?> min)
        </option>
      <?php endforeach; ?>
    </select>
    <label>Date</label>
    <input type="date" name="date" id="bookDate" required min="<?= date('Y-m-d') ?>" value="<?= date('Y-m-d') ?>">
    <label>Available times</label>
    <div id="slotStatus" class="muted" style="margin-bottom:.5rem">Select a service to load times.</div>
    <div class="book-slot-picker" id="slotPicker" hidden>
      <label class="slot-choice first-avail">
        <input type="radio" name="slot_choice" id="firstAvailRadio" value="first" disabled>
        <span>
          <strong>First available</strong>
          <small id="firstAvailHint">Earliest open chair that day</small>
        </span>
      </label>
      <div id="barberSlotLists" class="barber-slot-lists"></div>
    </div>
    <input type="hidden" name="time" id="bookTime" required>
    <input type="hidden" name="staff_id" id="resolvedStaffId" value="">
    <label>Your name</label>
    <input type="text" name="customer_name" required>
    <label>Phone</label>
    <input type="text" name="customer_phone" required>
    <label>Email <span class="muted">(required for reminders)</span></label>
    <input type="email" name="customer_email" required placeholder="you@email.com">
    <p class="muted" style="margin:-.35rem 0 .75rem;font-size:.85rem">
      We’ll email your appointment reminder. Text-via-carrier is optional and only works if your provider still accepts email-to-SMS — otherwise email is used.
    </p>
    <label>Mobile carrier <span class="muted">(optional text attempt)</span></label>
    <select name="carrier_id" id="carrierSelect">
      <option value="">— Email only (recommended) —</option>
      <?php
      try {
          require_once __DIR__ . '/lib/mailer.php';
          foreach (sms_carriers_list(true) as $c):
              if (($c['status'] ?? '') === 'retired') continue;
              ?>
        <option value="<?= (int) $c['id'] ?>">
          <?= htmlspecialchars($c['name']) ?> (@<?= htmlspecialchars($c['sms_domain']) ?>)
        </option>
      <?php endforeach;
      } catch (Throwable $e) { /* carriers table may not exist yet */ }
      ?>
    </select>
    <fieldset class="pay-methods" id="bookPayMethods">
      <legend>Payment</legend>
      <div id="bookPayHint" class="muted" style="margin-bottom:.5rem">Select a service to see payment options.</div>
      <div id="bookPayOptions"></div>
    </fieldset>
    <button class="btn" type="submit" id="bookSubmit" disabled>Request appointment</button>
  </form>
</section>

<div class="demo-modal" id="demoPayModal" hidden aria-hidden="true">
  <div class="demo-modal-backdrop" data-close-demo></div>
  <div class="demo-modal-card" role="dialog" aria-modal="true" aria-labelledby="demoPayTitle">
    <h3 id="demoPayTitle">Demo checkout</h3>
    <p id="demoPayBody">This is disabled in the demo — you would see the bank processing page on this page if this were the live version.</p>
    <button type="button" class="btn" id="demoPayContinue">Got it — continue</button>
  </div>
</div>

<div class="demo-modal book-confirm-modal" id="bookConfirmModal" hidden aria-hidden="true">
  <div class="demo-modal-backdrop" data-close-confirm></div>
  <div class="demo-modal-card" role="dialog" aria-modal="true" aria-labelledby="bookConfirmTitle">
    <p class="book-confirm-kicker">Booking confirmed</p>
    <h3 id="bookConfirmTitle">You’re on the books</h3>
    <dl class="book-confirm-details">
      <div>
        <dt>Barber</dt>
        <dd id="bookConfirmBarber">—</dd>
      </div>
      <div>
        <dt>Date</dt>
        <dd id="bookConfirmDate">—</dd>
      </div>
      <div>
        <dt>Time</dt>
        <dd id="bookConfirmTime">—</dd>
      </div>
      <div>
        <dt>Service</dt>
        <dd id="bookConfirmService">—</dd>
      </div>
    </dl>
    <p class="book-confirm-note" id="bookConfirmNote"></p>
    <div class="book-confirm-upsell" id="bookConfirmUpsell">
      <p><strong>While you’re here</strong> — grab pomade, oil, or tools for pickup at your appointment.</p>
      <a class="btn secondary" id="bookConfirmShop" href="#">Browse products</a>
    </div>
    <button type="button" class="btn" id="bookConfirmClose">Done</button>
  </div>
</div>

<footer class="site-footer">
  <div>
    <strong><?= htmlspecialchars($business) ?></strong>
    <p><?= nl2br(htmlspecialchars((string) ($page['address'] ?? ''))) ?></p>
    <p><a href="tel:<?= htmlspecialchars(preg_replace('/\D+/', '', (string) ($page['phone'] ?? '')) ?? '') ?>"><?= htmlspecialchars((string) ($page['phone'] ?? '')) ?></a></p>
    <p><a href="<?= APP_BASE ?>/download-app.php">Get the Android app</a></p>
  </div>
  <div class="socials">
    <?php foreach (['instagram', 'facebook', 'tiktok'] as $net):
      if (empty($social[$net])) continue; ?>
      <a href="<?= htmlspecialchars($social[$net]) ?>" target="_blank" rel="noopener"><?= ucfirst($net) ?></a>
    <?php endforeach; ?>
  </div>
  <?php if (!empty($page['maps_embed'])): ?>
    <iframe class="map" src="<?= htmlspecialchars((string) $page['maps_embed']) ?>" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
  <?php endif; ?>
  <?php
    require_once __DIR__ . '/lib/sn_credit.php';
    sn_credit_render();
  ?>
</footer>

<script>
(function(){
  const APP_BASE = <?= json_encode(APP_BASE) ?>;
  const IS_DEMO = <?= json_encode(defined('DEMO_MODE') ? (bool) DEMO_MODE : false) ?>;
  const tenantQ = <?= json_encode(tenant_param($tenant)) ?>;
  const select = document.getElementById('serviceSelect');
  const dateInput = document.getElementById('bookDate');
  const timeInput = document.getElementById('bookTime');
  const resolvedStaff = document.getElementById('resolvedStaffId');
  const slotPicker = document.getElementById('slotPicker');
  const barberSlotLists = document.getElementById('barberSlotLists');
  const firstAvailRadio = document.getElementById('firstAvailRadio');
  const firstAvailHint = document.getElementById('firstAvailHint');
  const slotStatus = document.getElementById('slotStatus');
  const bookSubmit = document.getElementById('bookSubmit');
  const form = document.getElementById('public-book-form');
  const flash = document.getElementById('book-flash');
  const payOptions = document.getElementById('bookPayOptions');
  const payHint = document.getElementById('bookPayHint');
  const demoModal = document.getElementById('demoPayModal');
  const confirmModal = document.getElementById('bookConfirmModal');
  let quoteDue = { amount: 0, required: false, optional: false };
  let latestSlots = [];
  let pendingSuccess = null;

  const urlParams = new URLSearchParams(window.location.search);
  if (urlParams.get('booked') === '1') {
    showFlash('Payment received — your appointment is confirmed.', true);
  } else if (urlParams.get('book_pay_cancel') === '1') {
    showFlash('Payment cancelled. An unpaid hold expires in about 45 minutes.', false);
  } else if (urlParams.get('book_pay_pending') === '1') {
    showFlash('Payment is still processing. You’ll get confirmation when it clears.', true);
  }

  function showFlash(msg, ok) {
    flash.textContent = msg;
    flash.className = 'book-flash ' + (ok ? 'ok' : 'err');
    flash.hidden = false;
  }

  function parseStarts(data) {
    const starts = data.starts_at || (dateInput.value + ' ' + (timeInput.value || '00:00') + ':00');
    return {
      ymd: String(starts).slice(0, 10),
      hhmm: String(starts).slice(11, 16),
    };
  }

  function openConfirmModal(data) {
    const { ymd, hhmm } = parseStarts(data);
    const svc = data.service_name || (select.selectedOptions[0] && select.selectedOptions[0].dataset.name) || 'Appointment';
    const barber = data.staff_name || 'Your barber';
    const email = data.customer_email || (form.customer_email && form.customer_email.value) || '';
    document.getElementById('bookConfirmBarber').textContent = barber;
    document.getElementById('bookConfirmDate').textContent = formatDateLabel(ymd);
    document.getElementById('bookConfirmTime').textContent = formatTime(hhmm);
    document.getElementById('bookConfirmService').textContent = svc;
    document.getElementById('bookConfirmNote').textContent = email
      ? 'A reminder will be sent to ' + email + '.'
      : 'You’re all set — see you at the shop.';
    const shopLink = document.getElementById('bookConfirmShop');
    if (shopLink) {
      shopLink.href = APP_BASE + '/shop.php?tenant=' + encodeURIComponent(tenantQ || '');
    }
    confirmModal.classList.add('is-open');
    confirmModal.hidden = false;
    confirmModal.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
    showFlash('Booking confirmed with ' + barber + ' · ' + formatDateLabel(ymd) + ' at ' + formatTime(hhmm) + '.', true);
  }

  function closeConfirmModal() {
    confirmModal.classList.remove('is-open');
    confirmModal.hidden = true;
    confirmModal.setAttribute('aria-hidden', 'true');
    if (!demoModal.classList.contains('is-open')) {
      document.body.style.overflow = '';
    }
  }

  function qsTenant(url) {
    const u = new URL(url, window.location.origin);
    if (tenantQ) u.searchParams.set('tenant', tenantQ);
    return u.pathname + u.search;
  }

  function formatTime(hhmm) {
    const [h, m] = String(hhmm).split(':').map(Number);
    const ampm = h >= 12 ? 'PM' : 'AM';
    const hr = ((h + 11) % 12) + 1;
    return hr + ':' + String(m).padStart(2, '0') + ' ' + ampm;
  }

  function formatDateLabel(ymd) {
    const d = new Date(ymd + 'T12:00:00');
    return d.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' });
  }

  function clearSlotSelection() {
    timeInput.value = '';
    resolvedStaff.value = '';
    bookSubmit.disabled = true;
    firstAvailRadio.checked = false;
    barberSlotLists.querySelectorAll('select').forEach(s => { s.value = ''; });
    syncSubmitLabel();
  }

  function applySlot(time, staffId) {
    timeInput.value = time || '';
    resolvedStaff.value = staffId ? String(staffId) : '';
    bookSubmit.disabled = !time;
    syncSubmitLabel();
  }

  function syncSubmitLabel() {
    const method = form.querySelector('input[name="payment_method"]:checked');
    const id = method ? method.value : 'manual';
    const amt = Number(quoteDue.amount || 0);
    if ((id === 'demo' || id === 'stripe' || id === 'paypal') && amt > 0) {
      bookSubmit.textContent = 'Pay now · $' + amt.toFixed(2);
    } else {
      bookSubmit.textContent = 'Request appointment';
    }
  }

  function groupSlotsByBarber(slots) {
    const map = new Map();
    (slots || []).forEach(slot => {
      const id = String(slot.staff_id);
      if (!map.has(id)) {
        map.set(id, { staff_id: slot.staff_id, staff_name: slot.staff_name, slots: [] });
      }
      map.get(id).slots.push(slot);
    });
    return [...map.values()].sort((a, b) => a.staff_name.localeCompare(b.staff_name));
  }

  function earliestSlot(slots) {
    if (!slots || !slots.length) return null;
    return slots.slice().sort((a, b) => a.starts_at.localeCompare(b.starts_at))[0];
  }

  function renderSlotPicker(slots) {
    latestSlots = slots || [];
    barberSlotLists.innerHTML = '';
    const groups = groupSlotsByBarber(latestSlots);
    const first = earliestSlot(latestSlots);
    if (!groups.length || !first) {
      slotPicker.hidden = true;
      firstAvailRadio.disabled = true;
      return;
    }
    firstAvailRadio.disabled = false;
    firstAvailHint.textContent = formatTime(first.time) + ' with ' + first.staff_name;
    firstAvailRadio.dataset.time = first.time;
    firstAvailRadio.dataset.staffId = String(first.staff_id);

    groups.forEach(g => {
      const wrap = document.createElement('div');
      wrap.className = 'barber-slot-row';
      const label = document.createElement('label');
      label.textContent = g.staff_name;
      const sel = document.createElement('select');
      sel.className = 'barber-time-select';
      sel.dataset.staffId = String(g.staff_id);
      sel.innerHTML = '<option value="">Choose a time…</option>';
      g.slots.forEach(slot => {
        const opt = document.createElement('option');
        opt.value = slot.time;
        opt.textContent = formatTime(slot.time);
        sel.appendChild(opt);
      });
      sel.addEventListener('change', () => {
        if (!sel.value) {
          clearSlotSelection();
          return;
        }
        firstAvailRadio.checked = false;
        barberSlotLists.querySelectorAll('select').forEach(other => {
          if (other !== sel) other.value = '';
        });
        applySlot(sel.value, g.staff_id);
      });
      wrap.appendChild(label);
      wrap.appendChild(sel);
      barberSlotLists.appendChild(wrap);
    });
    slotPicker.hidden = false;
  }

  firstAvailRadio.addEventListener('change', () => {
    if (!firstAvailRadio.checked) return;
    barberSlotLists.querySelectorAll('select').forEach(s => { s.value = ''; });
    applySlot(firstAvailRadio.dataset.time, firstAvailRadio.dataset.staffId);
  });

  async function loadPayQuote() {
    if (!payOptions || !payHint) return;
    payOptions.innerHTML = '';
    quoteDue = { amount: 0, required: false, optional: false };
    if (!select.value) {
      payHint.textContent = 'Select a service to see payment options.';
      syncSubmitLabel();
      return;
    }
    try {
      const u = new URL(qsTenant(APP_BASE + '/api/bookings.php'), window.location.origin);
      u.searchParams.set('action', 'quote_public');
      u.searchParams.set('service_id', select.value);
      const res = await fetch(u.pathname + u.search);
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || 'Quote failed');
      quoteDue = data.due || quoteDue;
      payHint.textContent = (quoteDue.label || 'Payment')
        + (quoteDue.amount > 0 ? ' · up to $' + Number(quoteDue.amount).toFixed(2) : '');
      let methods = Array.isArray(data.methods) ? data.methods.slice() : [];
      if (!methods.length) {
        methods = [{ id: 'manual', label: 'Pay at the chair', hint: 'Pay when you arrive — no card needed online' }];
      }
      if (IS_DEMO && !methods.some(m => m.id === 'demo')) {
        methods.push({
          id: 'demo',
          label: 'Pay in advance',
          hint: 'Card / bank · demo checkout (no real charge)'
        });
      }
      methods.forEach((m, i) => {
        const label = document.createElement('label');
        label.className = 'pay-option';
        label.innerHTML = '<input type="radio" name="payment_method" value="' + m.id + '"' + (i === 0 ? ' checked' : '') + '>'
          + '<span><strong>' + m.label + '</strong><small>' + (m.hint || '') + '</small></span>';
        payOptions.appendChild(label);
      });
      payOptions.querySelectorAll('input[name="payment_method"]').forEach(r => {
        r.addEventListener('change', syncSubmitLabel);
      });
      syncSubmitLabel();
    } catch (e) {
      payHint.textContent = 'Pay at the chair';
      payOptions.innerHTML = '<label class="pay-option"><input type="radio" name="payment_method" value="manual" checked><span><strong>Pay at the chair</strong><small>Pay when you arrive</small></span></label>'
        + (IS_DEMO
          ? '<label class="pay-option"><input type="radio" name="payment_method" value="demo"><span><strong>Pay in advance</strong><small>Demo checkout</small></span></label>'
          : '');
      payOptions.querySelectorAll('input[name="payment_method"]').forEach(r => {
        r.addEventListener('change', syncSubmitLabel);
      });
      syncSubmitLabel();
    }
  }

  async function loadSlots(opts) {
    const autoAdvance = !opts || opts.autoAdvance !== false;
    clearSlotSelection();
    const serviceId = select.value;
    if (!serviceId) {
      slotPicker.hidden = true;
      slotStatus.textContent = 'Select a service to load times.';
      return;
    }
    const date = dateInput.value;
    if (!date) {
      slotStatus.textContent = 'Pick a date.';
      return;
    }
    slotStatus.textContent = 'Loading open chairs…';
    slotPicker.hidden = true;
    barberSlotLists.innerHTML = '';

    const params = new URLSearchParams({
      action: 'slots',
      service_id: serviceId,
      date: date,
      tenant: tenantQ,
      collapse: '0'
    });

    try {
      const res = await fetch(APP_BASE + '/api/availability.php?' + params.toString());
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || 'Could not load slots');
      if (!data.slots || !data.slots.length) {
        if (autoAdvance) {
          const start = new Date(date + 'T12:00:00');
          for (let i = 1; i <= 14; i++) {
            const d = new Date(start);
            d.setDate(d.getDate() + i);
            const ymd = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
            const p2 = new URLSearchParams({
              action: 'slots',
              service_id: serviceId,
              date: ymd,
              tenant: tenantQ,
              collapse: '0'
            });
            const res2 = await fetch(APP_BASE + '/api/availability.php?' + p2.toString());
            const data2 = await res2.json();
            if (data2.ok && data2.slots && data2.slots.length) {
              dateInput.value = ymd;
              slotStatus.textContent = 'Closed on ' + date + ' — showing next open day (' + ymd + ').';
              return loadSlots({ autoAdvance: false });
            }
          }
        }
        slotStatus.textContent = data.message || 'No open times this day — try another date.';
        bookSubmit.disabled = true;
        return;
      }
      const groups = groupSlotsByBarber(data.slots);
      slotStatus.textContent = data.slots.length + ' open time' + (data.slots.length === 1 ? '' : 's')
        + ' across ' + groups.length + ' barber' + (groups.length === 1 ? '' : 's')
        + ' · ' + data.duration_minutes + ' min';
      renderSlotPicker(data.slots);
    } catch (err) {
      slotStatus.textContent = err.message;
      bookSubmit.disabled = true;
    }
  }

  function openDemoModal(data) {
    pendingSuccess = data;
    demoModal.classList.add('is-open');
    demoModal.hidden = false;
    demoModal.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
  }

  function closeDemoModal() {
    demoModal.classList.remove('is-open');
    demoModal.hidden = true;
    demoModal.setAttribute('aria-hidden', 'true');
    if (pendingSuccess) {
      const data = pendingSuccess;
      pendingSuccess = null;
      finishSuccess(data);
      return;
    }
    if (!confirmModal.classList.contains('is-open')) {
      document.body.style.overflow = '';
    }
  }

  function finishSuccess(data) {
    openConfirmModal(data);
    const keepService = select.value;
    form.reset();
    select.value = keepService || (<?= (int) $preselect ?> ? '<?= (int) $preselect ?>' : '');
    dateInput.value = new Date().toISOString().slice(0, 10);
    clearSlotSelection();
    slotPicker.hidden = true;
    loadSlots();
    loadPayQuote();
  }

  document.querySelectorAll('[data-close-demo]').forEach(el => {
    el.addEventListener('click', closeDemoModal);
  });
  document.getElementById('demoPayContinue').addEventListener('click', closeDemoModal);
  document.querySelectorAll('[data-close-confirm]').forEach(el => {
    el.addEventListener('click', closeConfirmModal);
  });
  document.getElementById('bookConfirmClose').addEventListener('click', closeConfirmModal);

  document.querySelectorAll('[data-book-service]').forEach(el => {
    el.addEventListener('click', () => {
      const id = el.getAttribute('data-book-service');
      if (select) select.value = id;
      loadSlots();
      loadPayQuote();
      document.getElementById('book').scrollIntoView({ behavior: 'smooth' });
    });
  });

  select.addEventListener('change', () => { loadSlots(); loadPayQuote(); });
  dateInput.addEventListener('change', () => loadSlots({ autoAdvance: false }));

  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    if (!timeInput.value || !resolvedStaff.value) {
      showFlash('Pick first available or a barber time slot.', false);
      return;
    }
    const fd = new FormData(form);
    fd.append('action', 'create_public');
    fd.append('tenant', tenantQ || '');
    fd.set('staff_id', resolvedStaff.value);
    flash.hidden = true;
    bookSubmit.disabled = true;
    try {
      const res = await fetch(qsTenant(APP_BASE + '/api/bookings.php'), { method: 'POST', body: fd });
      const data = await res.json();
      if (!res.ok || !data.ok) throw new Error(data.error || 'Could not book');
      if (data.demo_checkout) {
        openDemoModal(data);
        return;
      }
      if (data.checkout_url) {
        window.location.href = data.checkout_url;
        return;
      }
      finishSuccess(data);
    } catch (err) {
      showFlash(err.message, false);
      bookSubmit.disabled = !timeInput.value;
    }
  });

  if (select.value) { loadSlots(); loadPayQuote(); }
})();
</script>
</body>
</html>
