function EstimateModal({ open, onClose, ctaLabel }) {
  const [step, setStep] = React.useState(0);
  const [answers, setAnswers] = React.useState({});
  const [errors, setErrors] = React.useState({});
  const [submitted, setSubmitted] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);
  const partialSentRef = React.useRef(false);
  const eventIdRef = React.useRef(null);

  React.useEffect(() => {
    if (!open) {
      setTimeout(() => {
        setStep(0); setAnswers({}); setErrors({});
        setSubmitted(false); setSubmitting(false);
        partialSentRef.current = false;
        eventIdRef.current = null;
      }, 400);
    }
  }, [open]);

  // Browser back button navigates steps
  React.useEffect(() => {
    if (!open) return;
    window.history.pushState({ modalStep: step }, '');
    const onPopState = () => {
      if (step > 0 && step < 4) {
        setStep(s => Math.max(0, s - 1));
        window.history.pushState({ modalStep: step - 1 }, '');
      } else if (step === 0) {
        onClose();
      }
    };
    window.addEventListener('popstate', onPopState);
    return () => window.removeEventListener('popstate', onPopState);
  }, [open, step]);

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

  if (!open) return null;

  const totalSteps = 5; // q1..q3, contact, success

  const select = (key, val) => {
    setAnswers(a => ({ ...a, [key]: val }));
    setErrors(e => ({ ...e, [key]: null }));
    if (key === "home_age" && window.fbq) fbq('trackCustom', 'FormStarted');
    // auto-advance for single-choice steps
    if (["home_age", "panel_upgraded", "timeline"].includes(key)) {
      setTimeout(() => setStep(s => s + 1), 180);
    }
  };

  const progress = Math.min(100, ((step) / (totalSteps - 1)) * 100);

  const SHEETS_URL = "https://script.google.com/macros/s/AKfycbw0ZsdrnnUFFFY-CwWJoZb3c2ZI3DF4FsD0Jm7T0PhshuZecOwKYwAMxv_Z0MhGthcS/exec";

  // Read tracking context
  const buildContext = () => {
    const params = new URLSearchParams(window.location.search);
    const cookies = Object.fromEntries(document.cookie.split(';').map(c => c.trim().split('=').map(decodeURIComponent)).filter(p => p[0]));
    return {
      utm_source: params.get('utm_source') || '',
      utm_medium: params.get('utm_medium') || '',
      utm_campaign: params.get('utm_campaign') || '',
      utm_adset: params.get('utm_adset') || '',
      utm_content: params.get('utm_content') || '',
      utm_term: params.get('utm_term') || '',
      fbclid: params.get('fbclid') || '',
      gclid: params.get('gclid') || '',
      page_url: window.location.href,
      referrer: document.referrer || '',
      fbp: cookies._fbp || '',
      fbc: cookies._fbc || '',
      ghl_session: cookies.lc_session_heaAO9KfuhCMWCmKu3fX || '',
    };
  };

  // Send to Google Sheets (fire-and-forget)
  const sendToSheets = (payload) => {
    try {
      fetch(SHEETS_URL, {
        method: 'POST',
        mode: 'no-cors',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
    } catch (_) { /* silent */ }
  };

  const toE164 = (raw) => {
    const digits = (raw || '').replace(/\D/g, '');
    if (!digits) return '';
    if (digits.length === 10) return '+1' + digits;
    if (digits.length === 11 && digits.startsWith('1')) return '+' + digits;
    return '+' + digits;
  };

  // Partial capture — fire as soon as email looks valid on Step 4
  const sendPartial = async (email) => {
    if (partialSentRef.current) return;
    if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return;
    partialSentRef.current = true;
    const ctx = buildContext();
    const payload = {
      partial: true,
      firstName: answers.firstName || '',
      lastName: answers.lastName || '',
      email,
      phone: toE164(answers.phone),
      home_age: answers.home_age || '',
      panel_upgraded: answers.panel_upgraded || '',
      timeline: answers.timeline || '',
      ...ctx,
    };
    try {
      await fetch('/api/lead-bevy', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
    } catch (_) { /* silent */ }
  };

  const validateContact = () => {
    const errs = {};
    if (!answers.firstName?.trim()) errs.firstName = "Required";
    if (!answers.lastName?.trim()) errs.lastName = "Required";
    if (!answers.email?.trim()) errs.email = "Please enter your email";
    else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(answers.email)) errs.email = "Please enter a valid email";
    if (!answers.phone?.trim()) errs.phone = "Please enter your phone";
    else if (answers.phone.replace(/\D/g,'').length < 10) errs.phone = "Please enter a valid phone";
    setErrors(errs);
    return Object.keys(errs).length === 0;
  };

  const submit = async () => {
    if (!validateContact() || submitting) return;
    setSubmitting(true);

    // Unique event_id for CAPI dedup later
    const eventId = "lead_" + Date.now() + "_" + Math.random().toString(36).slice(2, 10);
    eventIdRef.current = eventId;

    if (window.fbq) {
      fbq('track', 'Lead', {}, { eventID: eventId });
    }

    const ctx = buildContext();
    const payload = {
      partial: false,
      firstName: answers.firstName,
      lastName: answers.lastName,
      email: answers.email,
      phone: toE164(answers.phone),
      home_age: answers.home_age || '',
      panel_upgraded: answers.panel_upgraded || '',
      timeline: answers.timeline || '',
      event_id: eventId,
      ...ctx,
    };
    sendToSheets(payload);
    try {
      await fetch('/api/lead-bevy', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
    } catch (_) { /* silent — don't block UX */ }

    setSubmitted(true);
    setStep(4);
  };

  // Format phone live as user types — US format
  const formatPhone = (v) => {
    const digits = v.replace(/\D/g, '').slice(0, 10);
    if (digits.length >= 7) return `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`;
    if (digits.length >= 4) return `(${digits.slice(0,3)}) ${digits.slice(3)}`;
    if (digits.length > 0) return `(${digits}`;
    return '';
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="modal-header">
          {step > 0 && step < 4 ? (
            <button className="modal-back" onClick={() => setStep(s => Math.max(0, s-1))} aria-label="Go back">
              <Ic.arrow style={{transform:'rotate(180deg)'}} /> Back
            </button>
          ) : <span className="modal-back modal-back--placeholder" aria-hidden="true" />}
          {step < 4 && (
            <>
              <div className="modal-progress">
                <div className="modal-progress-bar" style={{width: progress + "%"}} />
              </div>
              <div className="modal-step-count">Step {Math.min(step+1, 4)} of 4</div>
            </>
          )}
          {step === 4 && <div style={{flex:1}} />}
          <button className="modal-close" onClick={onClose}><Ic.close /></button>
        </div>

        <div className="modal-body">
          {step === 0 && (
            <Step
              eyebrow="Quick question"
              title="How old is your home?"
              sub="This helps us figure out if your panel is likely to need an upgrade."
              options={["Built after 2000", "1980 - 2000", "Before 1980", "Not sure"]}
              value={answers.home_age}
              onSelect={v => select("home_age", v)}
            />
          )}
          {step === 1 && (
            <Step
              eyebrow="Your panel"
              title="Has your electrical panel ever been upgraded?"
              sub="If you're not sure, that's fine — we include a free panel check with every estimate."
              options={["Yes", "No", "Not sure"]}
              value={answers.panel_upgraded}
              onSelect={v => select("panel_upgraded", v)}
            />
          )}
          {step === 2 && (
            <Step
              eyebrow="Your timeline"
              title="When are you looking to get your EV charger installed?"
              sub="A rough target is fine — we'll confirm a date in the consultation."
              options={["ASAP", "Within 30 days", "1-3 months", "Just exploring"]}
              value={answers.timeline}
              onSelect={v => select("timeline", v)}
            />
          )}
          {step === 3 && (
            <>
              <span className="eyebrow" style={{marginBottom:12}}>Almost done</span>
              <h3>Where should we send your estimate?</h3>
              <p className="sub modal-promise">
                We won't spam you or sell your information <Ic.lock />
              </p>
              <div className="step-fields">
                <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:14}}>
                  <Field label="First name" name="firstName" value={answers.firstName || ""} error={errors.firstName} onChange={v => setAnswers(a => ({...a, firstName: v}))} placeholder="Jane" autoComplete="given-name" />
                  <Field label="Last name" name="lastName" value={answers.lastName || ""} error={errors.lastName} onChange={v => setAnswers(a => ({...a, lastName: v}))} placeholder="Doe" autoComplete="family-name" />
                </div>
                <Field
                  label="Email"
                  name="email"
                  type="email"
                  value={answers.email || ""}
                  error={errors.email}
                  onChange={v => setAnswers(a => ({...a, email: v}))}
                  onBlur={() => sendPartial(answers.email)}
                  placeholder="jane@example.com"
                  autoComplete="email"
                />
                <PhoneField
                  value={answers.phone || ""}
                  error={errors.phone}
                  onChange={v => setAnswers(a => ({...a, phone: formatPhone(v)}))}
                />
              </div>
            </>
          )}
          {step === 4 && submitted && (
            <div className="modal-success">
              <div className="check-big"><Ic.check size={32} /></div>
              <h3 style={{marginBottom:10}}>You're in. Thanks!</h3>
              <p style={{color:'var(--ink-2)', lineHeight:1.6, margin:'0 auto 24px', maxWidth:420}}>
                A Bevy Electric team member will reach out within minutes to confirm your free estimate and panel capacity check. Keep an eye on your phone.
              </p>
              <div style={{background:'var(--green-tint)', borderRadius:12, padding:'16px 18px', textAlign:'left', maxWidth:420, margin:'0 auto', display:'flex', gap:12}}>
                <div style={{color:'var(--green)', flexShrink:0}}><Ic.shield size={22} /></div>
                <div>
                  <div style={{fontWeight:600, fontSize:14, color:'var(--ink)'}}>Your spot is reserved</div>
                  <div style={{fontSize:13, color:'var(--ink-2)', marginTop:2}}>Free Level 2 charger estimate + free panel capacity check. Most installs done in one day.</div>
                </div>
              </div>
            </div>
          )}
        </div>

        {step === 3 && (
          <div className="modal-footer">
            <button className="btn btn-primary btn-lg" onClick={submit} disabled={submitting}>
              {submitting ? "Submitting…" : (ctaLabel || "Get Free Estimate & Panel Check")} <Ic.arrow />
            </button>
            <div className="modal-disclaimer">
              By submitting this form, you agree to be contacted by Bevy Electric via call, text, and email. Message &amp; data rates may apply. Reply STOP to opt out.
            </div>
          </div>
        )}
        {step === 4 && (
          <div className="modal-footer modal-footer--divider">
            <button className="btn btn-dark btn-lg" onClick={onClose}>Close</button>
          </div>
        )}
      </div>
    </div>
  );
}

function Step({ eyebrow, title, sub, options, value, onSelect }) {
  return (
    <>
      <span className="eyebrow" style={{marginBottom:12}}>{eyebrow}</span>
      <h3>{title}</h3>
      <p className="sub">{sub}</p>
      <div className="step-options">
        {options.map(opt => (
          <button
            key={opt}
            className={"step-option " + (value === opt ? "is-selected" : "")}
            onClick={() => onSelect(opt)}
          >
            <span className="radio" />
            <span>{opt}</span>
          </button>
        ))}
      </div>
    </>
  );
}

function Field({ label, name, type="text", value, onChange, onBlur, error, placeholder, autoComplete }) {
  return (
    <div className={"field " + (error ? "has-error" : "")}>
      <label htmlFor={name}>{label}</label>
      <input
        id={name}
        type={type}
        value={value}
        onChange={e => onChange(e.target.value)}
        onBlur={onBlur}
        placeholder={placeholder}
        autoComplete={autoComplete}
      />
      {error && <div className="err">{error}</div>}
    </div>
  );
}

function PhoneField({ value, error, onChange }) {
  return (
    <div className={"field " + (error ? "has-error" : "")}>
      <label htmlFor="phone">Phone number</label>
      <div className="phone-input-wrap">
        <span className="phone-prefix" aria-label="United States, +1">
          <span className="phone-flag" aria-hidden="true">🇺🇸</span>
          <span className="phone-code">+1</span>
        </span>
        <input
          id="phone"
          type="tel"
          inputMode="tel"
          value={value}
          onChange={e => onChange(e.target.value)}
          placeholder="(916) 886-1304"
          autoComplete="tel"
        />
      </div>
      {error && <div className="err">{error}</div>}
    </div>
  );
}

window.EstimateModal = EstimateModal;
