<?php
declare(strict_types=1);

require_once dirname(__DIR__) . '/lib/client.php';
require_once dirname(__DIR__) . '/lib/reminders.php';
require_once dirname(__DIR__) . '/lib/availability.php';

$tenantParam = tenant_param();
$_GET['tenant'] = $tenantParam;
$tenant = resolve_tenant_from_host();
if (!$tenant) {
    http_response_code(404);
    echo 'Shop not found.';
    exit;
}
$tenantId = (int) $tenant['id'];
$user = client_require_login($tenantParam);
$policy = client_policy($tenantId);
$flash = '';
$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    $bookingId = (int) ($_POST['booking_id'] ?? 0);
    try {
        $stmt = db()->prepare(
            'SELECT * FROM bookings WHERE id = ? AND tenant_id = ? AND user_id = ? LIMIT 1'
        );
        $stmt->execute([$bookingId, $tenantId, (int) $user['id']]);
        $booking = $stmt->fetch();
        if (!$booking) {
            throw new RuntimeException('Appointment not found.');
        }
        if (in_array((string) $booking['status'], ['cancelled', 'completed'], true)) {
            throw new RuntimeException('This appointment can no longer be changed.');
        }

        $check = client_policy_check($tenantId, (string) $booking['starts_at']);
        if (!$check['allowed']) {
            throw new RuntimeException($check['message']);
        }

        if ($action === 'cancel') {
            if (empty($policy['allow_cancel'])) {
                throw new RuntimeException('Online cancel is disabled. Please call the shop.');
            }
            $note = $check['fee_applies']
                ? trim((string) ($booking['notes'] ?? '') . "\n[Client cancel] Fee may apply: $" . number_format($check['cancel_fee'], 2))
                : trim((string) ($booking['notes'] ?? '') . "\n[Client cancel] Free (outside notice window)");
            db()->prepare('UPDATE bookings SET status = ?, notes = ? WHERE id = ? AND tenant_id = ?')
                ->execute(['cancelled', $note, $bookingId, $tenantId]);
            reminder_cancel_pending($bookingId);
            $flash = $check['fee_applies']
                ? 'Appointment cancelled. ' . $check['message']
                : 'Appointment cancelled at no fee.';
        } elseif ($action === 'reschedule') {
            if (empty($policy['allow_reschedule'])) {
                throw new RuntimeException('Online reschedule is disabled. Please call the shop.');
            }
            $date = trim((string) ($_POST['date'] ?? ''));
            $time = trim((string) ($_POST['time'] ?? ''));
            $staffId = ($_POST['staff_id'] ?? '') !== '' ? (int) $_POST['staff_id'] : ((int) $booking['staff_id'] ?: null);
            if ($date === '' || $time === '') {
                throw new RuntimeException('Pick a new date and time slot.');
            }
            if (strlen($time) === 4) {
                $time = '0' . $time;
            }
            $serviceId = (int) $booking['service_id'];
            $starts = DateTime::createFromFormat('Y-m-d H:i', $date . ' ' . $time);
            if (!$starts) {
                throw new RuntimeException('Invalid date/time.');
            }
            $resolvedStaff = availability_resolve_staff_for_slot($tenantId, $serviceId, $date, $time, $staffId, $bookingId);
            if (!$resolvedStaff) {
                throw new RuntimeException('That slot is not available. Pick another time.');
            }
            if (!availability_is_bookable($tenantId, $serviceId, $starts->format('Y-m-d H:i:s'), $resolvedStaff, $bookingId)) {
                throw new RuntimeException('That slot is not available. Pick another time.');
            }
            $svc = db()->prepare('SELECT duration_minutes FROM services WHERE id = ? AND tenant_id = ?');
            $svc->execute([$serviceId, $tenantId]);
            $service = $svc->fetch();
            if (!$service) {
                throw new RuntimeException('Service missing.');
            }
            $ends = clone $starts;
            $ends->modify('+' . (int) $service['duration_minutes'] . ' minutes');
            $note = $check['fee_applies']
                ? trim((string) ($booking['notes'] ?? '') . "\n[Client reschedule] Fee may apply: $" . number_format($check['cancel_fee'], 2))
                : trim((string) ($booking['notes'] ?? '') . "\n[Client reschedule] Free");
            db()->prepare(
                'UPDATE bookings SET staff_id=?, starts_at=?, ends_at=?, notes=?, status=? WHERE id=? AND tenant_id=?'
            )->execute([
                $resolvedStaff,
                $starts->format('Y-m-d H:i:s'),
                $ends->format('Y-m-d H:i:s'),
                $note,
                'pending',
                $bookingId,
                $tenantId,
            ]);
            reminder_schedule_for_booking($bookingId);
            $flash = 'Rescheduled to ' . $starts->format('D, M j · g:i A') . '. ' . ($check['fee_applies'] ? $check['message'] : '');
        } else {
            throw new RuntimeException('Unknown action.');
        }
    } catch (Throwable $e) {
        $error = $e->getMessage();
    }
}

$upcoming = db()->prepare(
    'SELECT b.*, s.name AS service_name, sb.name AS staff_name
     FROM bookings b
     LEFT JOIN services s ON s.id = b.service_id
     LEFT JOIN staff_barbers sb ON sb.id = b.staff_id
     WHERE b.tenant_id = ? AND b.user_id = ? AND b.starts_at >= NOW() AND b.status NOT IN (\'cancelled\',\'completed\')
     ORDER BY b.starts_at ASC'
);
$upcoming->execute([$tenantId, (int) $user['id']]);
$upcomingRows = $upcoming->fetchAll();

$past = db()->prepare(
    'SELECT b.*, s.name AS service_name, sb.name AS staff_name
     FROM bookings b
     LEFT JOIN services s ON s.id = b.service_id
     LEFT JOIN staff_barbers sb ON sb.id = b.staff_id
     WHERE b.tenant_id = ? AND b.user_id = ? AND (b.starts_at < NOW() OR b.status IN (\'cancelled\',\'completed\'))
     ORDER BY b.starts_at DESC
     LIMIT 20'
);
$past->execute([$tenantId, (int) $user['id']]);
$pastRows = $past->fetchAll();

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

client_layout_header('My appointments · ' . shop_company_name(null, $tenant), $tenant, $tenantParam, $user);
?>
<section class="client-wrap">
  <h1>Hi, <?= htmlspecialchars($user['name']) ?></h1>
  <p class="muted"><?= htmlspecialchars((string) $user['email']) ?></p>

  <div class="policy-box">
    <strong>Shop policy:</strong>
    <?= (int) $policy['notice_hours'] ?>-hour notice for free changes.
    Inside that window, a $<?= number_format((float) $policy['cancel_fee'], 2) ?> fee may apply.
    <?= htmlspecialchars((string) ($policy['fee_note'] ?? '')) ?>
  </div>

  <?php if ($flash): ?><div class="book-flash ok"><?= htmlspecialchars($flash) ?></div><?php endif; ?>
  <?php if ($error): ?><div class="book-flash err"><?= htmlspecialchars($error) ?></div><?php endif; ?>

  <p>
    <a class="btn" href="<?= APP_BASE ?>/?tenant=<?= urlencode($tenantParam) ?>#book">Book another appointment</a>
    <a class="btn ghost dark" href="<?= APP_BASE ?>/shop.php?tenant=<?= urlencode($tenantParam) ?>">Shop products</a>
  </p>

  <h2 style="margin-top:2rem">Upcoming</h2>
  <?php if (!$upcomingRows): ?>
    <p class="muted">No upcoming appointments.</p>
  <?php endif; ?>
  <?php foreach ($upcomingRows as $b):
    $check = client_policy_check($tenantId, (string) $b['starts_at']);
    ?>
    <article class="client-card" id="b-<?= (int) $b['id'] ?>">
      <h3><?= htmlspecialchars((string) ($b['service_name'] ?? 'Appointment')) ?></h3>
      <p class="client-meta">
        <?= htmlspecialchars(date('D, M j, Y · g:i A', strtotime((string) $b['starts_at']))) ?>
        · with <?= htmlspecialchars((string) ($b['staff_name'] ?? 'any barber')) ?>
        · <span class="tag"><?= htmlspecialchars((string) $b['status']) ?></span>
      </p>
      <p class="muted" style="font-size:.85rem"><?= htmlspecialchars($check['message']) ?></p>
      <?php if ($check['fee_applies']): ?><div class="fee-warn"><?= htmlspecialchars($check['message']) ?></div><?php endif; ?>

      <div class="client-actions">
        <?php if (!empty($policy['allow_reschedule']) && $check['allowed']): ?>
          <button type="button" class="btn small secondary toggle-reschedule" data-id="<?= (int) $b['id'] ?>">Reschedule</button>
        <?php endif; ?>
        <?php if (!empty($policy['allow_cancel']) && $check['allowed']): ?>
          <form method="post" onsubmit="return confirm('Cancel this appointment?<?= $check['fee_applies'] ? ' A fee may apply.' : '' ?>')">
            <input type="hidden" name="tenant" value="<?= htmlspecialchars($tenantParam) ?>">
            <input type="hidden" name="action" value="cancel">
            <input type="hidden" name="booking_id" value="<?= (int) $b['id'] ?>">
            <button class="btn small danger" type="submit">Cancel</button>
          </form>
        <?php endif; ?>
      </div>

      <form method="post" class="book-form reschedule-form" id="reschedule-<?= (int) $b['id'] ?>" style="display:none;margin-top:1rem">
        <input type="hidden" name="tenant" value="<?= htmlspecialchars($tenantParam) ?>">
        <input type="hidden" name="action" value="reschedule">
        <input type="hidden" name="booking_id" value="<?= (int) $b['id'] ?>">
        <input type="hidden" name="staff_id" value="<?= (int) ($b['staff_id'] ?? 0) ?>">
        <label>New date</label>
        <input type="date" name="date" required min="<?= date('Y-m-d') ?>" class="rs-date" data-service="<?= (int) $b['service_id'] ?>" data-staff="<?= (int) ($b['staff_id'] ?? 0) ?>" data-booking="<?= (int) $b['id'] ?>">
        <label>Available times</label>
        <div class="slot-grid rs-slots" id="slots-<?= (int) $b['id'] ?>"></div>
        <input type="hidden" name="time" class="rs-time" required>
        <button class="btn" type="submit">Save new time</button>
      </form>
    </article>
  <?php endforeach; ?>

  <h2 style="margin-top:2.5rem">Past / cancelled</h2>
  <?php if (!$pastRows): ?>
    <p class="muted">Nothing here yet.</p>
  <?php endif; ?>
  <?php foreach ($pastRows as $b): ?>
    <article class="client-card">
      <h3><?= htmlspecialchars((string) ($b['service_name'] ?? 'Appointment')) ?></h3>
      <p class="client-meta">
        <?= htmlspecialchars(date('D, M j, Y · g:i A', strtotime((string) $b['starts_at']))) ?>
        · <?= htmlspecialchars((string) $b['status']) ?>
      </p>
    </article>
  <?php endforeach; ?>
</section>
<script>
(function(){
  const APP_BASE = <?= json_encode(APP_BASE) ?>;
  const tenant = <?= json_encode($tenantParam) ?>;
  document.querySelectorAll('.toggle-reschedule').forEach(btn => {
    btn.addEventListener('click', () => {
      const form = document.getElementById('reschedule-' + btn.dataset.id);
      form.style.display = form.style.display === 'none' ? 'block' : 'none';
    });
  });

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

  async function loadSlots(dateInput) {
    const bookingId = dateInput.dataset.booking;
    const grid = document.getElementById('slots-' + bookingId);
    const timeInput = document.querySelector('#reschedule-' + bookingId + ' .rs-time');
    timeInput.value = '';
    grid.innerHTML = 'Loading…';
    const params = new URLSearchParams({
      action: 'slots',
      service_id: dateInput.dataset.service,
      date: dateInput.value,
      tenant: tenant,
      exclude_booking: bookingId
    });
    if (dateInput.dataset.staff && dateInput.dataset.staff !== '0') {
      params.set('staff_id', dateInput.dataset.staff);
    }
    const res = await fetch(APP_BASE + '/api/availability.php?' + params.toString());
    const data = await res.json();
    grid.innerHTML = '';
    if (!data.ok || !data.slots || !data.slots.length) {
      grid.textContent = 'No open times that day.';
      return;
    }
    data.slots.forEach(slot => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'slot-btn';
      b.textContent = formatTime(slot.time);
      b.addEventListener('click', () => {
        grid.querySelectorAll('.slot-btn').forEach(x => x.classList.remove('selected'));
        b.classList.add('selected');
        timeInput.value = slot.time;
      });
      grid.appendChild(b);
    });
  }

  document.querySelectorAll('.rs-date').forEach(inp => {
    inp.addEventListener('change', () => loadSlots(inp));
  });
})();
</script>
<?php client_layout_footer(); ?>
