/* ═══════════════════════════════════════════════════════════════════════
   BOOKING — modal lead-capture form. Loaded on every public page.
   Writes to localStorage['optitech_cms_v1'].leads which the admin
   Inbox reads. No backend required.
   ═══════════════════════════════════════════════════════════════════════ */

(function () {
  const STORE_KEY = 'optitech_cms_v1';
  const UTM_KEY = 'optitech_utm_v1';
  const SESSION_ID_KEY = 'optitech_session_v1';
  const { useState, useEffect, useRef } = React;

  /* Capture UTM params on first arrival, persist for the session */
  (function captureUtm() {
    try {
      const url = new URL(window.location.href);
      const utm = {};
      ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'ref', 'gclid', 'fbclid'].forEach(k => {
        const v = url.searchParams.get(k);
        if (v) utm[k] = v;
      });
      const existing = sessionStorage.getItem(UTM_KEY);
      if (Object.keys(utm).length > 0) {
        sessionStorage.setItem(UTM_KEY, JSON.stringify({ ...JSON.parse(existing || '{}'), ...utm, referrer: document.referrer || '', landingPath: url.pathname }));
      } else if (!existing) {
        sessionStorage.setItem(UTM_KEY, JSON.stringify({ referrer: document.referrer || '', landingPath: url.pathname }));
      }
      if (!sessionStorage.getItem(SESSION_ID_KEY)) {
        sessionStorage.setItem(SESSION_ID_KEY, 'sess-' + Math.random().toString(36).slice(2, 12));
      }
    } catch (e) { /* noop */ }
  })();

  function uid() { return Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 8); }

  function saveLead(lead) {
    let data;
    try { data = JSON.parse(localStorage.getItem(STORE_KEY) || '{}'); } catch (e) { data = {}; }
    if (!Array.isArray(data.leads)) data.leads = [];
    if (!Array.isArray(data.activity)) data.activity = [];
    data.leads.unshift(lead);
    data.activity.unshift({
      id: uid(),
      ts: Date.now(),
      actor: 'visitor',
      action: 'lead.captured',
      details: `${lead.name} · ${lead.business} · ${lead.trade}`
    });
    localStorage.setItem(STORE_KEY, JSON.stringify(data));
    window.dispatchEvent(new CustomEvent('cms:change'));
  }

  /* ── Form data shape ── */
  function emptyForm() {
    return {
      name: '', business: '', trade: '', otherTrade: '',
      postcode: '', monthlyBookings: '',
      tier: '', preferredSlot: 'morning',
      email: '', phone: '', notes: '',
      consent: false
    };
  }

  /* ── Modal ── */
  function BookingModal({ open, onClose, defaults = {} }) {
    const [step, setStep] = useState(1);
    const [form, setForm] = useState(() => ({ ...emptyForm(), ...defaults }));
    const [submitted, setSubmitted] = useState(false);
    const [errors, setErrors] = useState({});
    const firstRef = useRef(null);

    useEffect(() => {
      if (open) {
        setStep(1);
        setForm(f => ({ ...emptyForm(), ...defaults }));
        setSubmitted(false);
        setErrors({});
        document.body.style.overflow = 'hidden';
        setTimeout(() => firstRef.current?.focus(), 80);
      } else {
        document.body.style.overflow = '';
      }
      return () => { document.body.style.overflow = ''; };
    }, [open]);

    useEffect(() => {
      function onKey(e) { if (e.key === 'Escape' && open) onClose(); }
      window.addEventListener('keydown', onKey);
      return () => window.removeEventListener('keydown', onKey);
    }, [open, onClose]);

    function set(k, v) { setForm(f => ({ ...f, [k]: v })); }

    function validateStep(s) {
      const e = {};
      if (s === 1) {
        if (!form.name.trim()) e.name = 'Required';
        if (!form.business.trim()) e.business = 'Required';
        if (!form.trade) e.trade = 'Pick one';
        if (form.trade === 'other' && !form.otherTrade.trim()) e.otherTrade = 'Tell us your trade';
      }
      if (s === 2) {
        if (!form.postcode.trim()) e.postcode = 'Required';
        else if (!/^[A-Z]{1,2}[0-9][0-9A-Z]?\s*[0-9][A-Z]{2}$/i.test(form.postcode.trim()) && !/^[A-Z]{1,2}[0-9]{1,2}$/i.test(form.postcode.trim())) {
          e.postcode = 'UK postcode format (TQ1, TQ1 2AB)';
        }
        if (!form.monthlyBookings) e.monthlyBookings = 'Pick a band';
      }
      if (s === 3) {
        if (!form.email.trim()) e.email = 'Required';
        else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email.trim())) e.email = 'Not a valid email';
        if (!form.phone.trim()) e.phone = 'Required';
        if (!form.consent) e.consent = 'You must agree';
      }
      setErrors(e);
      return Object.keys(e).length === 0;
    }

    function next() { if (validateStep(step)) setStep(step + 1); }
    function back() { setStep(Math.max(1, step - 1)); setErrors({}); }

    function submit() {
      if (!validateStep(3)) return;
      let utm = {};
      try { utm = JSON.parse(sessionStorage.getItem(UTM_KEY) || '{}'); } catch (e) {}
      const sessionId = sessionStorage.getItem(SESSION_ID_KEY) || '';
      const lead = {
        id: uid(),
        createdAt: Date.now(),
        status: 'new',
        name: form.name.trim(),
        business: form.business.trim(),
        trade: form.trade === 'other' ? form.otherTrade.trim() : form.trade,
        postcode: form.postcode.trim().toUpperCase(),
        monthlyBookings: form.monthlyBookings,
        tier: form.tier || '',
        preferredSlot: form.preferredSlot,
        email: form.email.trim().toLowerCase(),
        phone: form.phone.trim(),
        notes: form.notes.trim(),
        consent: form.consent,
        source: utm.utm_source || utm.referrer ? new URL(utm.referrer || 'https://direct', 'https://x').hostname.replace('x', '') : 'direct',
        utm: utm,
        sessionId,
        page: window.location.pathname,
        notesInternal: [],
        contactedAt: null,
        wonAt: null
      };
      saveLead(lead);
      setSubmitted(true);
    }

    if (!open) return null;

    const tradeOptions = [
      { id: 'plumber', label: 'Plumbing' },
      { id: 'gas', label: 'Gas engineer' },
      { id: 'electric', label: 'Electrical' },
      { id: 'hvac', label: 'HVAC / heating' },
      { id: 'drainage', label: 'Drainage' },
      { id: 'roofing', label: 'Roofing' },
      { id: 'locksmith', label: 'Locksmith' },
      { id: 'gardening', label: 'Gardening / landscaping' },
      { id: 'other', label: 'Other trade' }
    ];
    const bookingBands = [
      { id: '0-30', label: '0–30 / month', sub: 'Just starting' },
      { id: '30-80', label: '30–80 / month', sub: 'Established' },
      { id: '80-200', label: '80–200 / month', sub: 'Growing fast' },
      { id: '200+', label: '200+ / month', sub: 'Scale operation' }
    ];
    const tierOptions = [
      { id: '', label: 'Not sure yet', sub: 'Operator will recommend' },
      { id: 'standard', label: 'Standard · £599/mo', sub: 'Up to 5 workers' },
      { id: 'growth', label: 'Growth · £1,749/mo', sub: 'Up to 25 workers' },
      { id: 'dominator', label: 'Dominator · £3,599/mo', sub: 'Unlimited workers' },
      { id: 'empire', label: 'Empire · £17,599/mo', sub: 'Multi-branch (Q4 2026)' }
    ];

    return (
      <div className="bk-overlay" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
        <div className="bk-modal" role="dialog" aria-modal="true" aria-label="Book a discovery call">
          <button className="bk-close" onClick={onClose} aria-label="Close">×</button>

          {submitted ? (
            <div className="bk-success">
              <div className="bk-success-mark">
                <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
                  <circle cx="24" cy="24" r="22" stroke="#16A34A" strokeWidth="2" />
                  <path d="M14 24l7 7 13-15" stroke="#16A34A" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
              <h2>Booked. We'll call within one business hour.</h2>
              <p>
                You'll get a confirmation at <strong>{form.email}</strong>, and the operator (the one
                actually running every account) will ring <strong>{form.phone}</strong> on your
                preferred slot. No call centre, no junior rep. The number that calls is{' '}
                <strong>+44 1803 ███ ███</strong>.
              </p>
              <p className="bk-success-meta">
                Reference: <code>OTA-{Date.now().toString(36).toUpperCase()}</code> · Saved at{' '}
                {new Date().toLocaleString('en-GB', { dateStyle: 'medium', timeStyle: 'short' })}
              </p>
              <button className="bk-btn bk-btn-primary" onClick={onClose}>Close</button>
            </div>
          ) : (
            <>
              <header className="bk-head">
                <div className="bk-head-text">
                  <div className="bk-eyebrow">Discovery call · 20 minutes</div>
                  <h2>Tell us about your trade.</h2>
                  <p>One operator reads every form. We'll call within one business hour, no call centre, no SDR.</p>
                </div>
                <ol className="bk-steps">
                  {[1, 2, 3].map(n => (
                    <li key={n} className={n === step ? 'is-active' : n < step ? 'is-done' : ''}>
                      <span>{n < step ? '✓' : n}</span>
                      {n === 1 ? 'Your business' : n === 2 ? 'Operation' : 'How to reach you'}
                    </li>
                  ))}
                </ol>
              </header>

              <div className="bk-body">
                {step === 1 && (
                  <div className="bk-step">
                    <div className="bk-grid-2">
                      <label className="bk-field">
                        <span>Your name</span>
                        <input ref={firstRef} type="text" autoComplete="name" value={form.name} onChange={e => set('name', e.target.value)} placeholder="Tom Hartwell" />
                        {errors.name && <em>{errors.name}</em>}
                      </label>
                      <label className="bk-field">
                        <span>Business name</span>
                        <input type="text" autoComplete="organization" value={form.business} onChange={e => set('business', e.target.value)} placeholder="Hartwell Plumbing &amp; Heating" />
                        {errors.business && <em>{errors.business}</em>}
                      </label>
                    </div>

                    <div className="bk-field">
                      <span>Your trade</span>
                      <div className="bk-chips">
                        {tradeOptions.map(t => (
                          <button key={t.id} type="button"
                            className={`bk-chip ${form.trade === t.id ? 'is-active' : ''}`}
                            onClick={() => set('trade', t.id)}>{t.label}</button>
                        ))}
                      </div>
                      {errors.trade && <em>{errors.trade}</em>}
                    </div>
                    {form.trade === 'other' && (
                      <label className="bk-field">
                        <span>What trade?</span>
                        <input type="text" value={form.otherTrade} onChange={e => set('otherTrade', e.target.value)} placeholder="Tree surgery, glazing, signage…" />
                        {errors.otherTrade && <em>{errors.otherTrade}</em>}
                      </label>
                    )}
                  </div>
                )}

                {step === 2 && (
                  <div className="bk-step">
                    <div className="bk-grid-2">
                      <label className="bk-field">
                        <span>Postcode (or postcode area)</span>
                        <input type="text" value={form.postcode} onChange={e => set('postcode', e.target.value)} placeholder="TQ4 7QY · or just TQ4" />
                        {errors.postcode && <em>{errors.postcode}</em>}
                        <small>So we know your county — first-trade-free still has open counties.</small>
                      </label>
                      <label className="bk-field">
                        <span>Preferred call slot</span>
                        <select value={form.preferredSlot} onChange={e => set('preferredSlot', e.target.value)}>
                          <option value="morning">Mornings (7–11)</option>
                          <option value="lunch">Lunchtime (12–14)</option>
                          <option value="afternoon">Afternoons (14–17)</option>
                          <option value="evening">After 17:00</option>
                        </select>
                      </label>
                    </div>

                    <div className="bk-field">
                      <span>Bookings per month right now</span>
                      <div className="bk-options">
                        {bookingBands.map(b => (
                          <button key={b.id} type="button"
                            className={`bk-option ${form.monthlyBookings === b.id ? 'is-active' : ''}`}
                            onClick={() => set('monthlyBookings', b.id)}>
                            <strong>{b.label}</strong>
                            <small>{b.sub}</small>
                          </button>
                        ))}
                      </div>
                      {errors.monthlyBookings && <em>{errors.monthlyBookings}</em>}
                    </div>

                    <div className="bk-field">
                      <span>Tier you're considering <small style={{color:'#6b7280', fontWeight:500}}>(optional)</small></span>
                      <div className="bk-options bk-options-tiers">
                        {tierOptions.map(t => (
                          <button key={t.id} type="button"
                            className={`bk-option ${form.tier === t.id ? 'is-active' : ''}`}
                            onClick={() => set('tier', t.id)}>
                            <strong>{t.label}</strong>
                            <small>{t.sub}</small>
                          </button>
                        ))}
                      </div>
                    </div>
                  </div>
                )}

                {step === 3 && (
                  <div className="bk-step">
                    <div className="bk-grid-2">
                      <label className="bk-field">
                        <span>Email</span>
                        <input type="email" autoComplete="email" value={form.email} onChange={e => set('email', e.target.value)} placeholder="tom@hartwellplumbing.co.uk" />
                        {errors.email && <em>{errors.email}</em>}
                      </label>
                      <label className="bk-field">
                        <span>Phone</span>
                        <input type="tel" autoComplete="tel" value={form.phone} onChange={e => set('phone', e.target.value)} placeholder="07700 900000" />
                        {errors.phone && <em>{errors.phone}</em>}
                      </label>
                    </div>
                    <label className="bk-field">
                      <span>Anything we should know? <small style={{color:'#6b7280', fontWeight:500}}>(optional)</small></span>
                      <textarea rows="3" value={form.notes} onChange={e => set('notes', e.target.value)} placeholder="What's broken, what you've tried, what you actually want from a platform…"></textarea>
                    </label>
                    <label className="bk-consent">
                      <input type="checkbox" checked={form.consent} onChange={e => set('consent', e.target.checked)} />
                      <span>
                        I'm happy for OptitechAutomation to contact me about the discovery call. We
                        don't sell your data, don't add you to marketing lists, and delete the record
                        if you ask. ICO registered.
                      </span>
                    </label>
                    {errors.consent && <em className="bk-error">{errors.consent}</em>}
                  </div>
                )}
              </div>

              <footer className="bk-foot">
                <div className="bk-foot-left">
                  Step <strong>{step}</strong> of 3 · 60 seconds total
                </div>
                <div className="bk-foot-right">
                  {step > 1 && <button className="bk-btn bk-btn-ghost" onClick={back}>← Back</button>}
                  {step < 3 && <button className="bk-btn bk-btn-primary" onClick={next}>Continue →</button>}
                  {step === 3 && <button className="bk-btn bk-btn-primary" onClick={submit}>Book the call →</button>}
                </div>
              </footer>
            </>
          )}
        </div>
      </div>
    );
  }

  /* ── Mount + global API ── */
  let host = null, root = null, isOpen = false, currentDefaults = {};

  function ensureHost() {
    if (host) return;
    host = document.createElement('div');
    host.id = 'optitech-booking-host';
    document.body.appendChild(host);
    root = ReactDOM.createRoot(host);
  }

  function render() {
    ensureHost();
    root.render(<BookingModal open={isOpen} onClose={close} defaults={currentDefaults} />);
  }

  function open(defaults) {
    isOpen = true;
    currentDefaults = defaults || {};
    render();
  }
  function close() {
    isOpen = false;
    render();
  }

  window.OptitechBooking = { open, close };

  /* Wire up any element with data-booking="open" automatically */
  document.addEventListener('click', (e) => {
    const el = e.target.closest('[data-booking="open"]');
    if (el) {
      e.preventDefault();
      const tier = el.getAttribute('data-tier') || '';
      open({ tier });
    }
  });
})();
