
(() => {
  const form = document.querySelector('form[data-ajax-contact]');
  if (!form) return;
  const status = form.querySelector('.form-status');
  const siteInput = form.querySelector('[name="site_id"]');
  const serviceInput = form.querySelector('[name="servico"]');
  const staffInput = form.querySelector('[name="profissional"]');
  const staffNameInput = form.querySelector('[name="profissional_nome"]');
  const extrasInput = form.querySelector('[name="extras"]');
  const dateInput = form.querySelector('[name="data_preferida"]');
  const timeInput = form.querySelector('[name="hora_preferida"]');
  const slotsTarget = form.querySelector('[data-booking-slots]');
  const summaryTarget = form.querySelector('[data-booking-summary]');
  const calendarTarget = form.querySelector('[data-booking-calendar]');
  const dateHint = form.querySelector('[data-booking-date-hint]');
  const dateShortcuts = form.querySelector('[data-booking-date-shortcuts]');
  const bookingExpectation = form.querySelector('[data-booking-expectation]');
  const bookingSteps = form.querySelectorAll('[data-booking-step]');
  const bookingProgress = form.querySelectorAll('[data-booking-progress]');
  const widgetRoot = document.querySelector('[data-uneed-booking-widget]');
  const businessPhone = String(widgetRoot?.getAttribute('data-business-phone') || '').replace(/\D/g, '');
  const stepOrder = ['staff','service','extras','schedule','client'];
  let currentStep = 'staff';
  let staffTouched = true;
  let calendarMonth = new Date();
  const apiOrigin = () => (window.location.protocol === 'http:' && window.location.port === '3333') ? window.location.origin : 'http://localhost:3333';
  const esc = value => String(value || '').replace(/[&<>"']/g, char => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[char]));
  const dateValue = date => date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
  const parseDate = value => value ? new Date(value + 'T00:00:00') : null;
  const addDays = (date, days) => { const next = new Date(date); next.setDate(next.getDate() + days); return next; };
  const monthLabel = date => date.toLocaleDateString('pt-PT', { month:'long', year:'numeric' });
  const whatsappText = (data, reference) => [
    'Olá, quero confirmar a minha marcação.',
    data.serviceLabel ? 'Serviço: ' + data.serviceLabel : '',
    data.staffLabel ? 'Profissional: ' + data.staffLabel : '',
    data.date || data.time ? 'Data/Hora: ' + [data.date, data.time].filter(Boolean).join(' às ') : '',
    data.client ? 'Nome: ' + data.client : '',
    reference ? 'Referência: ' + reference : ''
  ].filter(Boolean).join('\n');
  const queueNotification = async (siteId, leadId) => {
    if (!siteId || !leadId) return null;
    try {
      const fd = new FormData();
      fd.set('site_id', siteId);
      fd.set('lead_id', leadId);
      fd.set('event', 'confirm');
      const res = await fetch(apiOrigin() + '/api/notifications/queue', { method:'POST', body:fd });
      return await res.json();
    } catch {
      return null;
    }
  };
  function initBookingDateLimits(){
    if (!dateInput) return;
    const minNoticeHours = Number(dateInput.getAttribute('data-min-notice-hours') || 0);
    const maxAdvanceDays = Number(dateInput.getAttribute('data-max-advance-days') || 45);
    const now = new Date();
    dateInput.min = dateValue(new Date(now.getTime() + (Number.isFinite(minNoticeHours) ? minNoticeHours : 0) * 60 * 60 * 1000));
    dateInput.max = dateValue(addDays(now, Number.isFinite(maxAdvanceDays) && maxAdvanceDays > 0 ? maxAdvanceDays : 45));
    if (dateHint) { dateHint.hidden = false; dateHint.textContent = 'Pode escolher datas entre ' + dateInput.min + ' e ' + dateInput.max + '.'; }
    calendarMonth = parseDate(dateInput.value || dateInput.min) || new Date();
    renderBookingCalendar();
  }
  function renderBookingCalendar(){
    if (!calendarTarget || !dateInput) return;
    const selected = parseDate(dateInput.value);
    const min = parseDate(dateInput.min);
    const max = parseDate(dateInput.max);
    const first = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth(), 1);
    const startDay = (first.getDay() + 6) % 7;
    const daysInMonth = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth() + 1, 0).getDate();
    let cells = '';
    for (let i = 0; i < startDay; i += 1) cells += '<span class="booking-calendar-empty"></span>';
    for (let day = 1; day <= daysInMonth; day += 1) {
      const date = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth(), day);
      const value = dateValue(date);
      const disabled = (min && date < min) || (max && date > max);
      const active = selected && value === dateValue(selected);
      cells += '<button type="button" data-booking-calendar-day="' + value + '" class="' + (active ? 'is-selected ' : '') + (disabled ? 'is-disabled' : '') + '"' + (disabled ? ' disabled aria-disabled="true"' : '') + '>' + day + '</button>';
    }
    calendarTarget.innerHTML = '<div class="booking-calendar-head"><strong>' + esc(monthLabel(calendarMonth)) + '</strong><span><button type="button" data-booking-calendar-prev aria-label="Mes anterior">‹</button><button type="button" data-booking-calendar-next aria-label="Mes seguinte">›</button></span></div><div class="booking-calendar-week"><span>S</span><span>T</span><span>Q</span><span>Q</span><span>S</span><span>S</span><span>D</span></div><div class="booking-calendar-grid">' + cells + '</div>';
  }
  function renderBookingDateShortcuts(){
    if (!dateShortcuts || !dateInput || !dateInput.min) return;
    const min = new Date(dateInput.min + 'T00:00:00');
    const max = dateInput.max ? new Date(dateInput.max + 'T00:00:00') : null;
    const labels = [['Primeira data',0],['Dia seguinte',1],['Mais 2 dias',2],['Proxima semana',7]];
    const used = new Set();
    const options = labels.map(([label, offset]) => {
      const date = addDays(min, offset);
      const value = dateValue(date);
      if (used.has(value) || (max && date > max)) return null;
      used.add(value);
      return { label, value };
    }).filter(Boolean);
    dateShortcuts.hidden = !options.length;
    dateShortcuts.innerHTML = options.map(option => '<button type="button" data-booking-date-shortcut="' + option.value + '">' + option.label + ' · ' + option.value + '</button>').join('');
    syncBookingDateShortcuts();
  }
  function syncBookingDateShortcuts(){
    if (!dateShortcuts || !dateInput) return;
    dateShortcuts.querySelectorAll('[data-booking-date-shortcut]').forEach(button => button.classList.toggle('is-selected', button.getAttribute('data-booking-date-shortcut') === dateInput.value));
  }
  function bookingWindowMessage(reason){
    return {'past-date':'Esta data ja passou. Escolha uma data futura.','max-advance':'Esta data esta fora da janela maxima de marcacao.','min-notice':'Este horario nao respeita a antecedencia minima.','invalid-date':'Escolha uma data valida.','invalid-time':'Escolha uma hora valida.'}[reason] || '';
  }
  function summary(){
    return {
      serviceLabel: serviceInput?.value || '',
      staffLabel: staffInput?.selectedOptions?.[0]?.textContent || 'Qualquer profissional disponivel',
      extrasLabel: extrasInput?.value || '',
      date: dateInput?.value || '',
      time: timeInput?.value || '',
      client: form.querySelector('[name="nome"]')?.value || ''
    };
  }
  function setStep(step){
    if (!stepOrder.includes(step)) return;
    currentStep = step;
    if (step === 'schedule' && dateInput && !dateInput.value && dateInput.min) {
      dateInput.value = dateInput.min;
      calendarMonth = parseDate(dateInput.value) || calendarMonth;
      renderBookingCalendar();
      loadBookingSlots();
    }
    bookingSteps.forEach(item => item.classList.toggle('is-active', item.getAttribute('data-booking-step') === step));
    bookingProgress.forEach(item => item.classList.toggle('is-active', item.getAttribute('data-booking-progress') === step));
    const copy = form.querySelector('[data-booking-step-copy]');
    if (copy) {
      copy.textContent = {
        staff:'Escolha quem o vai atender.',
        service:'Escolha o servico principal.',
        extras:'Adicione extras se fizer sentido.',
        schedule:'Escolha a data e um horario disponivel.',
        client:'Preencha os dados para receber a confirmacao.'
      }[step] || 'Complete a marcacao.';
    }
  }
  function nextStep(){
    const index = stepOrder.indexOf(currentStep);
    setStep(stepOrder[Math.min(index + 1, stepOrder.length - 1)]);
  }
  function previousStep(){
    const index = stepOrder.indexOf(currentStep);
    setStep(stepOrder[Math.max(index - 1, 0)]);
  }
  function canLeaveCurrentStep(){
    if (currentStep === 'staff') return staffTouched || !staffInput;
    if (currentStep === 'service') return !!serviceInput?.value;
    if (currentStep === 'schedule') return !!(dateInput?.value && timeInput?.value);
    return true;
  }
  function showStepError(message){
    if (!status) return;
    status.textContent = message;
    setTimeout(() => { if (status.textContent === message) status.textContent = ''; }, 2600);
  }
  function updateBookingProgress(){
    const complete = {
      staff: staffTouched || !staffInput,
      service: !!serviceInput?.value,
      extras: true,
      schedule: !!(dateInput?.value && timeInput?.value),
      client: !!(form.querySelector('[name="nome"]')?.value && form.querySelector('[name="telefone"]')?.value)
    };
    bookingSteps.forEach(step => step.classList.toggle('is-complete', !!complete[step.getAttribute('data-booking-step')]));
    bookingProgress.forEach(item => item.classList.toggle('is-complete', !!complete[item.getAttribute('data-booking-progress')]));
    const data = summary();
    if (summaryTarget) {
      const show = data.serviceLabel || data.date || data.time || data.client;
      summaryTarget.hidden = false;
      summaryTarget.innerHTML = show ? '<strong>Resumo da marcacao</strong><span>' + esc(data.serviceLabel || 'Servico por escolher') + ' · ' + esc(data.staffLabel) + '</span>' + (data.extrasLabel ? '<span>Extras: ' + esc(data.extrasLabel) + '</span>' : '') + '<span>' + esc(data.date || 'Data por escolher') + (data.time ? ' as ' + esc(data.time) : '') + '</span>' + (data.client ? '<span>Cliente: ' + esc(data.client) + '</span>' : '') : '<strong>A sua marcacao</strong><span>Escolha um profissional para começar.</span>';
    }
    if (bookingExpectation) {
      const parts = [data.serviceLabel || 'o servico pretendido', data.date ? 'em ' + data.date : '', data.time ? 'as ' + data.time : '', data.staffLabel && data.staffLabel !== 'Qualquer profissional disponivel' ? 'com ' + data.staffLabel : ''].filter(Boolean).join(' ');
      bookingExpectation.innerHTML = '<strong>' + (data.serviceLabel && data.date && data.time ? 'Esta quase pronto.' : 'Pedido sem compromisso imediato.') + '</strong><span>' + (parts ? 'Vamos validar ' + esc(parts) + ' e confirmar rapidamente por telefone, email ou WhatsApp.' : 'A equipa confirma a marcacao ou sugere uma alternativa se o horario deixar de estar livre.') + '</span>';
    }
  }
  function syncChoice(name){
    const select = form.querySelector('[name="' + name + '"]');
    if (!select) return;
    form.querySelectorAll('[data-booking-choice="' + name + '"]').forEach(button => button.classList.toggle('is-selected', button.getAttribute('data-value') === select.value));
    if (name === 'profissional' && staffNameInput) staffNameInput.value = select.selectedOptions?.[0]?.textContent || '';
  }
  function selectedServiceId(){ return form.querySelector('[data-booking-choice="servico"].is-selected')?.getAttribute('data-service-id') || ''; }
  function staffCanDo(target){
    const serviceId = selectedServiceId();
    if (!serviceId || !target) return true;
    const ids = String(target.getAttribute('data-service-ids') || '').split(',').map(item => item.trim()).filter(Boolean);
    return !ids.length || ids.includes(serviceId);
  }
  function filterStaffForService(){
    if (!staffInput) return;
    form.querySelectorAll('[data-booking-choice="profissional"]').forEach(button => { const any = !button.getAttribute('data-value'); button.hidden = !any && !staffCanDo(button); });
    Array.from(staffInput.options || []).forEach(option => { const any = !option.value; option.disabled = !any && !staffCanDo(option); });
    if (staffInput.value && staffInput.selectedOptions?.[0]?.disabled) { staffInput.value = ''; syncChoice('profissional'); }
  }
  async function loadBookingSlots(){
    if (!slotsTarget || !siteInput || !dateInput?.value) return;
    if (serviceInput && !serviceInput.value) { slotsTarget.hidden = false; slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>Escolha primeiro o servico.</strong><em>Assim conseguimos mostrar horarios com a duracao certa.</em></p>'; return; }
    if ((dateInput.min && dateInput.value < dateInput.min) || (dateInput.max && dateInput.value > dateInput.max)) { slotsTarget.hidden = false; slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>Data fora das regras de marcacao.</strong><em>Escolha uma das datas sugeridas acima.</em></p>'; return; }
    slotsTarget.hidden = false;
    slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>A procurar horarios disponiveis...</strong><em>Estamos a cruzar servico, profissional e disponibilidade.</em></p>';
    try {
      const qs = new URLSearchParams({ site_id:siteInput.value || '', date:dateInput.value || '', service:serviceInput ? serviceInput.value : '', staff:staffInput ? staffInput.value : '' });
      const res = await fetch(apiOrigin() + '/api/public/booking/availability?' + qs.toString());
      const data = await res.json();
      const msg = bookingWindowMessage(data.windowStatus?.reason);
      const allSlots = Array.isArray(data.slots) ? data.slots.slice(0, 18) : [];
      const availableSlots = allSlots.filter(slot => slot.available);
      if (msg) { slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>' + esc(msg) + '</strong><em>Experimente uma das datas rapidas ou altere a hora.</em></p>'; return; }
      if (!allSlots.length) { slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>Sem horarios para esta selecao.</strong><em>Experimente outro profissional, outra data ou escolha qualquer profissional disponivel.</em></p>'; return; }
      slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>Horarios</strong><em><span class="booking-slot-dot is-free"></span><span class="booking-slot-dot is-busy"></span></em></p>' + allSlots.map(slot => {
        const available = !!slot.available;
        return '<button type="button" class="' + (available ? 'is-available' : 'is-unavailable') + '" data-booking-slot="' + esc(slot.start) + '" data-booking-staff="' + esc(slot.staffId || '') + '"' + (available ? '' : ' disabled aria-disabled="true"') + '>' + esc(slot.start) + '</button>';
      }).join('') + (!availableSlots.length ? '<p class="booking-slot-note booking-slot-warning"><strong>Nao ha vagas livres nesta data.</strong><em>Escolha outra data ou outro profissional.</em></p>' : '');
    } catch {
      slotsTarget.innerHTML = '<p class="booking-slot-note"><strong>Nao foi possivel carregar horarios.</strong><em>Pode escrever a hora manualmente e a equipa confirma depois.</em></p>';
    }
  }
  form.querySelectorAll('[data-booking-choice]').forEach(button => button.addEventListener('click', () => {
    const name = button.getAttribute('data-booking-choice');
    const select = form.querySelector('[name="' + name + '"]');
    if (!select) return;
    select.value = button.getAttribute('data-value') || '';
    if (name === 'profissional') staffTouched = true;
    select.dispatchEvent(new Event('change', { bubbles:true }));
    syncChoice(name);
    updateBookingProgress();
    if (name === 'profissional' && currentStep === 'staff') nextStep();
    if (name === 'servico' && currentStep === 'service') nextStep();
  }));
  form.querySelectorAll('[data-booking-extra]').forEach(button => button.addEventListener('click', () => {
    button.classList.toggle('is-selected');
    if (extrasInput) {
      extrasInput.value = Array.from(form.querySelectorAll('[data-booking-extra].is-selected'))
        .map(item => item.getAttribute('data-value') || '')
        .filter(Boolean)
        .join(', ');
    }
    updateBookingProgress();
  }));
  form.querySelectorAll('[data-booking-next]').forEach(button => button.addEventListener('click', () => {
    if (!canLeaveCurrentStep()) {
      showStepError(currentStep === 'service' ? 'Escolha um servico para continuar.' : currentStep === 'schedule' ? 'Escolha data e hora para continuar.' : 'Escolha uma opcao para continuar.');
      return;
    }
    nextStep();
    updateBookingProgress();
  }));
  form.querySelectorAll('[data-booking-prev]').forEach(button => button.addEventListener('click', () => {
    previousStep();
    updateBookingProgress();
  }));
  serviceInput?.addEventListener('change', () => { syncChoice('servico'); filterStaffForService(); loadBookingSlots(); });
  staffInput?.addEventListener('change', () => { syncChoice('profissional'); loadBookingSlots(); });
  dateInput?.addEventListener('change', () => { syncBookingDateShortcuts(); loadBookingSlots(); });
  calendarTarget?.addEventListener('click', event => {
    const prev = event.target.closest('[data-booking-calendar-prev]');
    const next = event.target.closest('[data-booking-calendar-next]');
    const day = event.target.closest('[data-booking-calendar-day]');
    if (prev) {
      calendarMonth = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth() - 1, 1);
      renderBookingCalendar();
      return;
    }
    if (next) {
      calendarMonth = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth() + 1, 1);
      renderBookingCalendar();
      return;
    }
    if (day && dateInput) {
      dateInput.value = day.getAttribute('data-booking-calendar-day') || '';
      timeInput.value = '';
      renderBookingCalendar();
      loadBookingSlots();
      updateBookingProgress();
    }
  });
  dateShortcuts?.addEventListener('click', event => {
    const button = event.target.closest('[data-booking-date-shortcut]');
    if (!button || !dateInput) return;
    dateInput.value = button.getAttribute('data-booking-date-shortcut') || '';
    dateInput.dispatchEvent(new Event('change', { bubbles:true }));
  });
  slotsTarget?.addEventListener('click', event => {
    const button = event.target.closest('[data-booking-slot]');
    if (!button || !timeInput) return;
    timeInput.value = button.getAttribute('data-booking-slot') || '';
    if (staffInput && button.getAttribute('data-booking-staff')) { staffInput.value = button.getAttribute('data-booking-staff'); syncChoice('profissional'); }
    slotsTarget.querySelectorAll('[data-booking-slot]').forEach(item => item.classList.remove('is-selected'));
    button.classList.add('is-selected');
    updateBookingProgress();
  });
  form.addEventListener('input', updateBookingProgress);
  form.addEventListener('change', updateBookingProgress);
  form.addEventListener('submit', async event => {
    event.preventDefault();
    if (status) status.textContent = 'A enviar...';
    try {
      const fd = new FormData(form);
      const res = await fetch(apiOrigin() + '/api/public/booking/requests', { method:'POST', body:fd });
      const data = await res.json();
      if (data && (data.type === 'success' || data.ok)) {
        const s = summary();
        const manageHref = '../../booking-manage.html?ref=' + encodeURIComponent(data.reference || '') + '&token=' + encodeURIComponent(data.customerToken || '');
        const queued = await queueNotification(siteInput?.value || '', data.leadId || '');
        const waHref = businessPhone ? 'https://wa.me/' + encodeURIComponent(businessPhone) + '?text=' + encodeURIComponent(whatsappText(s, data.reference || '')) : '';
        const whatsappState = queued?.summary?.jobs ? 'Mensagem WhatsApp colocada na fila de confirmacao.' : (businessPhone ? 'Pode abrir o WhatsApp com a mensagem ja preenchida.' : 'A equipa recebe o pedido e confirma pelos contactos indicados.');
        const whatsappAction = waHref ? '<a href="' + waHref + '" target="_blank" rel="noopener">Abrir WhatsApp</a>' : '';
        if (status) status.innerHTML = '<div class="booking-reference"><strong>Pedido registado com sucesso.</strong><span>Referencia: <code>' + esc(data.reference || '') + '</code></span><div class="booking-reference-grid"><span>Servico <b>' + esc(s.serviceLabel || 'A confirmar') + '</b></span><span>Profissional <b>' + esc(s.staffLabel || 'A confirmar') + '</b></span><span>Data <b>' + esc(s.date || 'A confirmar') + '</b></span><span>Hora <b>' + esc(s.time || 'A confirmar') + '</b></span></div><small class="booking-whatsapp-note">' + esc(whatsappState) + '</small><div class="booking-reference-actions"><a href="' + manageHref + '" target="_top">Gerir pedido</a>' + whatsappAction + '</div></div>';
        form.reset(); syncChoice('servico'); syncChoice('profissional'); updateBookingProgress();
      } else if (status) status.textContent = data?.text || 'Erro ao enviar.';
    } catch {
      if (status) status.textContent = 'Erro de ligacao. Tente novamente.';
    }
  });
  initBookingDateLimits();
  syncChoice('servico');
  syncChoice('profissional');
  filterStaffForService();
  setStep('staff');
  updateBookingProgress();
})();
