/* ConsultX — survey app. Depends on schema.js, fields.jsx, tweaks-panel.jsx. */
const { useState, useEffect, useRef, useMemo } = React;

const STORE_KEY = 'cx_survey_v2';
const STEPS = window.CX_STEPS;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#FF771C",
  "radius": 12,
  "density": "regular"
}/*EDITMODE-END*/;

/* ---------- helpers ---------- */
const isEmpty = (f, v) => {
  if (f.type === 'multichips') return !v || v.length === 0;
  if (f.type === 'consent') return !v;
  if (f.type === 'daymonth') return v !== 'Not sure' && !(v && v.day && v.month);
  return v === undefined || v === null || v === '';
};
const emailOK = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);

const visibleFields = (step, answers) => step.fields.filter((f) => (f.when ? f.when(answers) : true));

function loadState() {
  try {
    const raw = localStorage.getItem(STORE_KEY);
    if (raw) {
      const state = JSON.parse(raw);
      // Migrate from v1 to v2_full_logic if needed (add schema_version tracking in future)
      return state;
    }
  } catch (e) {}
  return { answers: {}, step: 0 };
}

// Smart field dependency clearing: when a field changes, clear dependent fields if they become invalid
function clearDependentFields(fieldId, value, currentAnswers) {
  const newAnswers = { ...currentAnswers };

  // Mainland/Free Zone jurisdiction logic
  if (fieldId === 'licence_jurisdiction') {
    delete newAnswers.free_zone;   // only visible for Free Zone
    delete newAnswers.legal_form;  // always reset — options differ by jurisdiction
  }

  // When emirate changes, clear free_zone if no longer valid
  if (fieldId === 'emirate' && currentAnswers.licence_jurisdiction === 'Free Zone') {
    const freeZonesByEmirate = {
      'Dubai': ['DMCC', 'IFZA', 'Meydan Free Zone', 'Dubai South', 'JAFZA', 'DAFZA', 'DWTC', 'DIFC', 'Other Dubai Free Zone', 'Not sure'],
      'Abu Dhabi': ['ADGM', 'KEZAD', 'Other Abu Dhabi Free Zone', 'Not sure'],
      'Sharjah': ['SPC Free Zone', 'SAIF Zone', 'Shams', 'Other Sharjah Free Zone', 'Not sure'],
      'Ras Al Khaimah': ['RAKEZ', 'Other Ras Al Khaimah Free Zone', 'Not sure'],
      'Ajman': ['Ajman Free Zone', 'Other Ajman Free Zone', 'Not sure'],
      'Fujairah': ['Fujairah Creative City', 'Other Fujairah Free Zone', 'Not sure'],
      'Umm Al Quwain': ['UAQ Free Trade Zone', 'Other Umm Al Quwain Free Zone', 'Not sure']
    };
    const validOptions = freeZonesByEmirate[value] || [];
    if (newAnswers.free_zone && !validOptions.includes(newAnswers.free_zone)) {
      delete newAnswers.free_zone; // Clear if no longer valid for this emirate
    }
  }

  // VAT/CT registration change clearing
  if (fieldId === 'vat_registered') {
    // Clear vat_support selections that don't match new registration status
    const currentVatSupport = currentAnswers.vat_support || [];
    let validVatSupport = [];

    if (value === 'Yes') {
      validVatSupport = currentVatSupport.filter(v => !['VAT registration', 'Complete VAT registration'].includes(v));
    } else if (value === 'No') {
      validVatSupport = currentVatSupport.filter(v => !['VAT return filing', 'VAT review before filing'].includes(v));
    } else if (value === 'Application in progress') {
      validVatSupport = currentVatSupport.filter(v => !['VAT return filing', 'VAT review before filing'].includes(v));
    }

    if (validVatSupport.length < currentVatSupport.length) {
      if (validVatSupport.length > 0) {
        newAnswers.vat_support = validVatSupport;
      } else {
        delete newAnswers.vat_support;
      }
    }
  }

  if (fieldId === 'ct_registered') {
    // Clear ct_support selections that don't match new registration status
    const currentCtSupport = currentAnswers.ct_support || [];
    let validCtSupport = [];

    if (value === 'Yes') {
      validCtSupport = currentCtSupport.filter(v => !['Corporate Tax registration', 'Corporate Tax registration deadline assessment', 'Corporate Tax registration assessment'].includes(v));
    } else if (value === 'No') {
      validCtSupport = currentCtSupport.filter(v => !['Corporate Tax return preparation', 'Corporate Tax return filing', 'Return preparation after registration'].includes(v));
    } else if (value === 'Application in progress') {
      validCtSupport = currentCtSupport.filter(v => !['Corporate Tax return filing'].includes(v));
    }

    if (validCtSupport.length < currentCtSupport.length) {
      if (validCtSupport.length > 0) {
        newAnswers.ct_support = validCtSupport;
      } else {
        delete newAnswers.ct_support;
      }
    }
  }

  // Payroll clearing
  if (fieldId === 'num_employees') {
    if (value === '0' && currentAnswers.payroll_support) {
      delete newAnswers.payroll_support;
    }
    if (value === '0' && currentAnswers.employee_pro_support) {
      delete newAnswers.employee_pro_support;
    }
  }

  // Contact: Clear fields based on preferred method
  if (fieldId === 'preferred_contact') {
    if (value !== 'Email') {
      delete newAnswers.email;
    }
    if (value !== 'WhatsApp' && value !== 'Phone call') {
      delete newAnswers.phone;
    }
    if (value !== 'Telegram') {
      delete newAnswers.telegram;
    }
  }

  return newAnswers;
}

// Multi-select mutual exclusivity: negative/exclusive options clear incompatible ones
function applyMultiSelectExclusivity(fieldId, value, currentAnswers) {
  const newAnswers = { ...currentAnswers };
  const exclusivePatterns = {
    'vat_support': ['Not applicable', 'Not sure'],
    'ct_support': ['Not sure'],
    'payroll_support': ['Not required', 'Not sure'],
    'employee_pro_support': ['No support needed', 'Not sure'],
    'company_pro_support': ['No support needed', 'Not sure'],
    'payment_methods': ['Other'],
    'compliance_deadlines': ['Not required at this stage'],
    'aml_needs': ['Not required', 'Not sure'],
  };

  // If user selects an exclusive option, clear other selections
  if (exclusivePatterns[fieldId] && exclusivePatterns[fieldId].includes(value)) {
    newAnswers[fieldId] = [value]; // Keep only the exclusive option
  } else if (exclusivePatterns[fieldId] && newAnswers[fieldId]) {
    // If exclusive option is selected, remove it when user selects something else
    newAnswers[fieldId] = newAnswers[fieldId].filter((v) => !exclusivePatterns[fieldId].includes(v));
  }

  return newAnswers;
}

/* ---------- icons ---------- */
const ArrowR = () => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" /></svg>);
const ArrowL = () => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><line x1="19" y1="12" x2="5" y2="12" /><polyline points="12 19 5 12 12 5" /></svg>);

/* =================================================================== */
function App() {
  const init = loadState();
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [answers, setAnswers] = useState(init.answers);
  const [step, setStep] = useState(Math.min(init.step || 0, STEPS.length - 1));
  const [errors, setErrors] = useState({});
  const [maxReached, setMaxReached] = useState(init.step || 0);
  const [submitting, setSubmitting] = useState(false);
  const [submitFail, setSubmitFail] = useState(false);
  const [done, setDone] = useState(false);
  const [started, setStarted] = useState((init.step || 0) > 0 || Object.keys(init.answers || {}).length > 0);
  const fieldRefs = useRef({});
  const topRef = useRef(null);

  /* persist */
  useEffect(() => {
    try { localStorage.setItem(STORE_KEY, JSON.stringify({ answers, step, started })); } catch (e) {}
  }, [answers, step, started]);

  /* apply tweaks to CSS vars */
  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty('--accent', t.accent);
    r.style.setProperty('--accent-hover', `color-mix(in srgb, ${t.accent} 86%, #000)`);
    r.style.setProperty('--accent-soft', `color-mix(in srgb, ${t.accent} 9%, #fff)`);
    r.style.setProperty('--accent-tint', `color-mix(in srgb, ${t.accent} 18%, #fff)`);
    r.style.setProperty('--radius', t.radius + 'px');
    r.style.setProperty('--radius-sm', Math.max(4, t.radius - 4) + 'px');
    r.style.setProperty('--radius-lg', (t.radius + 4) + 'px');
    r.setAttribute('data-density', t.density);
  }, [t]);

  const cur = STEPS[step];
  const vis = useMemo(() => visibleFields(cur, answers), [cur, answers]);
  const effReq = (f) => (f.requiredWhen ? f.requiredWhen(answers) : !!f.required);

  const setVal = (id, v) => {
    setAnswers((a) => {
      let updated = { ...a, [id]: v };
      // Apply dependency clearing
      updated = clearDependentFields(id, v, updated);
      // Apply multi-select exclusivity for multichips fields
      if (Array.isArray(v) && v.length > 0) {
        updated = applyMultiSelectExclusivity(id, v[v.length - 1], updated);
      }
      return updated;
    });
    setErrors((e) => { if (!e[id]) return e; const n = { ...e }; delete n[id]; return n; });
  };

  const validateStep = () => {
    const errs = {};
    vis.forEach((f) => {
      if (effReq(f) && isEmpty(f, answers[f.id])) {
        errs[f.id] = f.type === 'text' || f.type === 'email' || f.type === 'textarea'
          ? 'This field is required.'
          : f.type === 'consent' ? 'Please confirm to continue.' : 'Please make a selection.';
      } else if (f.type === 'email' && answers[f.id] && !emailOK(answers[f.id])) {
        errs[f.id] = 'Please enter a valid email address.';
      }
    });
    return errs;
  };

  const scrollToTop = () => {
    const el = topRef.current;
    if (!el) return;
    const y = el.getBoundingClientRect().top + window.scrollY - 90;
    window.scrollTo({ top: Math.max(0, y), behavior: 'smooth' });
  };

  const scrollToError = (id) => {
    const el = fieldRefs.current[id];
    if (!el) return;
    const y = el.getBoundingClientRect().top + window.scrollY - 120;
    window.scrollTo({ top: Math.max(0, y), behavior: 'smooth' });
  };

  const goNext = () => {
    const errs = validateStep();
    if (Object.keys(errs).length) {
      setErrors(errs);
      const first = vis.find((f) => errs[f.id]);
      if (first) scrollToError(first.id);
      return;
    }
    setErrors({});
    if (step < STEPS.length - 1) {
      const ns = step + 1;
      setStep(ns);
      setMaxReached((m) => Math.max(m, ns));
      scrollToTop();
    } else {
      submit();
    }
  };

  const goBack = () => {
    if (step === 0) return;
    setErrors({});
    setStep(step - 1);
    scrollToTop();
  };

  const goTo = (i) => {
    if (i <= maxReached && i !== step) { setErrors({}); setStep(i); scrollToTop(); }
  };

  const submit = async () => {
    setSubmitting(true);
    setSubmitFail(false);
    try {
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(answers),
      });

      let data;
      try {
        data = await response.json();
      } catch (e) {
        console.error('Failed to parse response:', response.status, response.statusText);
        setSubmitFail(true);
        setSubmitting(false);
        return;
      }

      if (!response.ok || !data.ok) {
        console.error('API error:', data);
        setSubmitFail(true);
        setSubmitting(false);
        return;
      }

      setDone(true);
      try { localStorage.removeItem(STORE_KEY); } catch (e) {}
      window.scrollTo({ top: 0, behavior: 'smooth' });
    } catch (error) {
      console.error('Submit error:', error);
      setSubmitFail(true);
      setSubmitting(false);
    }
  };

  const resetAll = () => {
    setAnswers({}); setStep(0); setMaxReached(0); setErrors({}); setDone(false); setSubmitFail(false); setStarted(false);
  };

  const beginSurvey = () => {
    setStarted(true);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const isLast = step === STEPS.length - 1;
  const urgent = answers.urgent_deadline && answers.urgent_deadline !== 'No';

  /* numbering: count non-consent visible fields */
  let counter = 0;
  let lastSection = null;

  return (
    <div className="cx-page">
      <Header tweakOn />
      <div className="cx-shell">
        <div className="cx-card" ref={topRef}>
          {done ? (
            <Success />
          ) : !started ? (
            <Intro onStart={beginSurvey} />
          ) : (
            <React.Fragment>
              <Rail step={step} maxReached={maxReached} goTo={goTo} />
              <div className="cx-form">
                <div className="cx-mform">
                  <MobileHead step={step} />
                  <div className="cx-step-head">
                    <div className="k">Step {step + 1} of {STEPS.length}</div>
                    <h2>{cur.title}</h2>
                    {cur.intro ? <p>{cur.intro}</p> : <p>{cur.blurb}</p>}
                  </div>

                  {submitFail && (
                    <div className="cx-banner" role="alert">
                      <AlertCircle />
                      <span><b>Submission could not be completed.</b> Please check your internet connection and try again. If the issue continues, you may contact ConsultX directly and we will assist you.</span>
                    </div>
                  )}

                  <div className="cx-grid cx-step-enter" key={step}>
                    {vis.map((f) => {
                      const nodes = [];
                      if (f.section && f.section !== lastSection) {
                        lastSection = f.section;
                        nodes.push(<SubHead key={'sec-' + f.section} label={f.section} />);
                      }
                      const num = f.type === 'consent' ? null : ++counter;
                      const resolvedOpts = typeof f.options === 'function' ? f.options(answers) : f.options;
                      nodes.push(
                        <Field key={f.id} field={f} num={num} required={effReq(f)} value={answers[f.id]} error={errors[f.id]}
                          resolvedOpts={resolvedOpts}
                          onChange={(v) => setVal(f.id, v)}
                          fieldRef={(el) => { fieldRefs.current[f.id] = el; }} />
                      );
                      return nodes;
                    })}
                  </div>

                  <div className="cx-nav">
                    {step > 0 ? (
                      <button className="cx-btn cx-btn-ghost" onClick={goBack}><ArrowL />Back</button>
                    ) : <span />}
                    <button className="cx-btn cx-btn-primary" onClick={goNext} disabled={submitting}>
                      {submitting ? <React.Fragment><span className="sp" />Submitting…</React.Fragment>
                        : isLast ? <React.Fragment>Submit survey<ArrowR /></React.Fragment>
                          : <React.Fragment>Continue<ArrowR /></React.Fragment>}
                    </button>
                  </div>
                </div>
              </div>
            </React.Fragment>
          )}
        </div>
        <p className="cx-foot">
          This pre-quotation survey is used for preliminary scope assessment only. Submission of this form does not create an engagement, accounting appointment, tax representation or advisory relationship until a proposal is issued and accepted.
        </p>
      </div>
      <TweakUI t={t} setTweak={setTweak} />
    </div>
  );
}

/* ---------- header ---------- */
function Header() {
  return (
    <header className="cx-header">
      <div className="cx-header-inner">
        <img className="cx-logo" src="assets/consultx-logo.png" alt="ConsultX — Boutique Corporate Solutions" />
        <div className="cx-header-label">Accounting &amp; Compliance Survey</div>
      </div>
    </header>
  );
}

/* ---------- intro / welcome (first screen) ---------- */
const INTRO_BADGES = ['Accounting', 'VAT', 'Corporate Tax', 'WPS', 'Compliance Follow-Up'];
function Intro({ onStart }) {
  return (
    <div className="cx-intro-screen">
      <p className="cx-eyebrow">ConsultX · Pre-Quotation Survey</p>
      <h1 className="cx-intro-title">Accounting &amp; Compliance Pre-Quotation Survey</h1>
      <p className="cx-intro-lead">Answer a few structured questions so we can assess your accounting volume, tax obligations, payroll requirements and compliance deadlines before recommending the most suitable package.</p>

      <div className="cx-intro-meta">
        <div className="cx-meta-item"><span className="v">5</span><span className="l">short steps</span></div>
        <div className="cx-meta-sep" />
        <div className="cx-meta-item"><span className="v">~5 min</span><span className="l">to complete</span></div>
        <div className="cx-meta-sep" />
        <div className="cx-meta-item"><span className="v">Auto-saved</span><span className="l">resume anytime</span></div>
      </div>

      <ol className="cx-intro-steps">
        {STEPS.map((s, i) => (
          <li key={s.key}><span className="n">{i + 1}</span><span className="t">{s.key}</span></li>
        ))}
      </ol>

      <div className="cx-intro-badges">{INTRO_BADGES.map((b) => <span className="cx-badge" key={b}>{b}</span>)}</div>

      <button className="cx-btn cx-btn-primary cx-intro-start" onClick={onStart}>Start survey<span className="ar"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" /></svg></span></button>

      <p className="cx-intro-note">This is a short pre-quotation survey. It is not the full onboarding form and does not create an engagement until a proposal is issued and accepted.</p>
    </div>
  );
}

/* ---------- left rail ---------- */
const BADGES = ['Accounting', 'VAT', 'Corporate Tax', 'WPS', 'Compliance Follow-Up'];
function Rail({ step, maxReached, goTo }) {
  return (
    <aside className="cx-rail">
      <p className="cx-eyebrow">Pre-Quotation Survey</p>
      <h1 className="cx-title">Accounting &amp; Compliance Pre-Quotation Survey</h1>
      <p className="cx-intro">Answer a few structured questions so we can assess your accounting volume, tax obligations, payroll requirements and compliance deadlines before recommending the most suitable package.</p>
      <p className="cx-note">This is a short pre-quotation survey. It is not the full onboarding form and does not create an engagement until a proposal is issued and accepted.</p>
      <div className="cx-badges">{BADGES.map((b) => <span className="cx-badge" key={b}>{b}</span>)}</div>
      <ol className="cx-steps">
        {STEPS.map((s, i) => {
          const done = i !== step && i <= maxReached;
          const stateCls = i === step ? 'is-active' : done ? 'is-done' : '';
          return (
            <li className={`cx-step ${stateCls}`} key={s.key} onClick={() => done && goTo(i)}>
              <span className="cx-step-marker">{done ? <Check /> : i + 1}</span>
              <span className="cx-step-line" />
              <span className="cx-step-body">
                <div className="cx-step-k">Step {i + 1}</div>
                <div className="cx-step-name">{s.key}</div>
              </span>
            </li>
          );
        })}
      </ol>
    </aside>
  );
}

/* ---------- mobile progress head ---------- */
function MobileHead({ step }) {
  const pct = Math.round(((step + 1) / STEPS.length) * 100);
  return (
    <div className="cx-mhead">
      <div className="row">
        <span className="of">Step {step + 1} of {STEPS.length}</span>
        <span className="pct">{pct}% complete</span>
      </div>
      <h2>{STEPS[step].title}</h2>
      <div className="cx-mbar"><i style={{ width: pct + '%' }} /></div>
    </div>
  );
}

/* ---------- success ---------- */
function Success() {
  const [ref] = React.useState(function() {
    return 'CSX-ACC-' + String(Math.floor(100000 + Math.random() * 900000));
  });
  return (
    <div className="cx-success cxs-wrap">
      <div className="cxs-inner">
        <div className="cxs-mark"><Check /></div>
        <div className="cxs-badge">Submission received</div>
        <h2 className="cxs-heading">Thank you — your quotation is in motion.</h2>
        <p className="cxs-sub">We've received your company details and our team is already reviewing everything needed to prepare your personalised quotation. There's nothing more you need to do right now.</p>
        <div className="cxs-stats">
          <div className="cxs-stat">
            <span className="cxs-stat-label">Prepared within</span>
            <span className="cxs-stat-value">48–72 hours</span>
          </div>
          <div className="cxs-stat-divider" />
          <div className="cxs-stat">
            <span className="cxs-stat-label">Reference</span>
            <span className="cxs-stat-value cxs-ref">{ref}</span>
          </div>
        </div>
        <div className="cxs-next-head">What happens next</div>
        <div className="cxs-steps">
          {[
            { title: 'We review your details', desc: 'Our specialists assess your accounting volume, tax position, payroll and compliance needs to scope the right package.' },
            { title: 'A quick check-in — only if needed', desc: 'If anything needs clarification, we will reach out using your preferred contact method. Otherwise, we proceed directly.' },
            { title: 'Your tailored quotation', desc: 'You receive a clear, itemised proposal built around what your company actually needs.' },
          ].map(function(s, i) {
            return (
              <div key={i} className="cxs-step" style={{ animationDelay: (0.55 + i * 0.12) + 's' }}>
                <div className="cxs-step-num">{i + 1}</div>
                <div className="cxs-step-body">
                  <div className="cxs-step-title">{s.title}</div>
                  <div className="cxs-step-desc">{s.desc}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

/* ---------- tweaks ---------- */
function TweakUI({ t, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Accent" />
      <TweakColor label="Accent color" value={t.accent}
        options={['#FF771C', '#E65F00', '#F2941D', '#D2562B', '#161616']}
        onChange={(v) => setTweak('accent', v)} />
      <TweakSection label="Shape & density" />
      <TweakSlider label="Corner radius" value={t.radius} min={2} max={20} step={1} unit="px"
        onChange={(v) => setTweak('radius', v)} />
      <TweakRadio label="Density" value={t.density} options={['compact', 'regular', 'comfy']}
        onChange={(v) => setTweak('density', v)} />
    </TweaksPanel>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
