// app.jsx — state, validation, persistence, layout switching, tweaks
const { useState, useEffect, useRef } = React;

const STORE_KEY = 'ff_intake_v1';

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "layout": "Index",
  "indexMark": "Horizontal sans",
  "accent": "Subtle",
  "eyebrow": "Serif",
  "questionType": "Sans"
}/*EDITMODE-END*/;

function loadSaved() {
  try {
    const raw = localStorage.getItem(STORE_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return { values: {}, index: 0 };
}

function validateStep(step, values) {
  const errs = {};
  if (!step.groups) return errs;
  step.groups.forEach((g) => g.rows.forEach((r) => r.forEach((id) => {
    const f = window.FF_FIELDS[id];
    if (!f.required) return;
    const v = values[id];
    const empty = v == null || v === '' || (Array.isArray(v) && v.length === 0);
    if (empty) errs[id] = f.type === 'checkbox' ? 'Select at least one option.'
      : f.type === 'scale' ? 'Choose a value from 1 to 5.'
      : f.type === 'email' ? 'This field is required.'
      : 'This field is required.';
    else if (f.type === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) errs[id] = 'Enter a valid email address.';
  })));
  return errs;
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const saved = useRef(loadSaved());
  const [values, setValues] = useState(saved.current.values);
  const [index, setIndex] = useState(saved.current.index || 0);
  const [errors, setErrors] = useState({});
  const [submitted, setSubmitted] = useState(false);
  const scrollRef = useRef(null);

  const steps = window.FF_STEPS;
  const step = steps[index];

  // persist
  useEffect(() => {
    try { localStorage.setItem(STORE_KEY, JSON.stringify({ values, index })); } catch (e) {}
  }, [values, index]);

  // scroll to top on step change
  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = 0;
  }, [index, submitted]);

  function onChange(id, val) {
    setValues((v) => ({ ...v, [id]: val }));
    setErrors((e) => { if (!e[id]) return e; const n = { ...e }; delete n[id]; return n; });
  }

  function goTo(i) {
    setErrors({});
    setIndex(Math.max(0, Math.min(steps.length - 1, i)));
  }

  const [isSending, setIsSending] = useState(false);

  async function onNext() {
    if (step.review) {
      let allErrs = {};
      let firstBad = -1;
      steps.forEach((s, i) => {
        const e = validateStep(s, values);
        if (Object.keys(e).length && firstBad < 0) firstBad = i;
        allErrs = { ...allErrs, ...e };
      });
      if (firstBad >= 0) { setErrors(allErrs); setIndex(firstBad); return; }

      // Build labeled payload from schema
      const payload = [];
      steps.filter((s) => !s.review).forEach((s) => {
        s.groups.forEach((g) => g.rows.forEach((row) => row.forEach((id) => {
          const f = window.FF_FIELDS[id];
          const v = values[id];
          if (v == null || v === '' || (Array.isArray(v) && v.length === 0)) return;
          payload.push({
            section: s.title,
            label: f.review || f.label,
            value: Array.isArray(v) ? v.join(', ') : f.type === 'scale' ? `${v} / 5` : String(v),
          });
        })));
      });

      setIsSending(true);
      try {
        await fetch('/api/send-intake', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ payload, replyTo: values.email }),
        });
      } catch (err) {
        console.error('Email send failed:', err);
        // Non-blocking: still show success screen even if email fails
      } finally {
        setIsSending(false);
      }

      setSubmitted(true);
      try { localStorage.removeItem(STORE_KEY); } catch (e) {}
      return;
    }

    const e = validateStep(step, values);
    if (Object.keys(e).length) { setErrors(e); return; }
    goTo(index + 1);
  }

  function onBack() { goTo(index - 1); }
  function onJump(i) { if (i <= index) goTo(i); }       // only jump backward freely (stage/split)
  function onEditStep(stepId) { goTo(steps.findIndex((s) => s.id === stepId)); }

  function onReset() {
    setValues({}); setErrors({}); setIndex(0); setSubmitted(false);
  }

  const layoutMap = {
    'Spread': window.SpreadLayout,
    'Index': window.IndexLayout,
    'Document': window.DocumentLayout,
  };
  const Layout = layoutMap[t.layout] || window.SpreadLayout;

  const accentClass = 'accent-' + (t.accent || 'Subtle').toLowerCase();
  const qClass = t.questionType === 'Serif' ? ' q-serif' : '';
  const rootStyle = { '--eyebrow-font': t.eyebrow === 'Sans' ? 'var(--tff-sans)' : 'var(--tff-serif)' };

  return (
    <div className={'ff-root on-dark ' + accentClass + qClass} style={rootStyle}>
      {submitted ? (
        <SuccessScreen values={values} onReset={onReset} />
      ) : (
        <Layout
          index={index}
          step={step}
          values={values}
          errors={errors}
          markStyle={t.indexMark}
          onChange={onChange}
          onNext={onNext}
          onBack={onBack}
          onJump={onJump}
          onEditStep={onEditStep}
          scrollRef={scrollRef}
          isSending={isSending}
        />
      )}

      <TweaksPanel>
        <TweakSection label="Composition" />
        <TweakRadio
          label="Layout"
          value={t.layout}
          options={['Spread', 'Index', 'Document']}
          onChange={(v) => setTweak('layout', v)}
        />
        <TweakRadio
          label="Sidebar mark"
          value={t.indexMark}
          options={['Horizontal sans', 'Stacked serif']}
          onChange={(v) => setTweak('indexMark', v)}
        />
        <TweakSection label="Detail" />
        <TweakRadio
          label="Coral accent"
          value={t.accent}
          options={['None', 'Subtle', 'Signature']}
          onChange={(v) => setTweak('accent', v)}
        />
        <TweakRadio
          label="Eyebrow type"
          value={t.eyebrow}
          options={['Serif', 'Sans']}
          onChange={(v) => setTweak('eyebrow', v)}
        />
        <TweakRadio
          label="Field labels"
          value={t.questionType}
          options={['Sans', 'Serif']}
          onChange={(v) => setTweak('questionType', v)}
        />
      </TweaksPanel>
    </div>
  );
}

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