/* IntakeForm + ScanResult.

   Submitting POSTs to /api/scan (scripts/site/serve.py), which captures the
   lead under clients/<slug>/intake/ and runs the real free scan from
   scripts/scan/free_scan.py against the submitted domain. What comes back are
   that site's actual findings, and that is what renders.

   Served as a plain static file with no endpoint behind it, the POST fails and
   the page falls back to the canned findings — still shown, still labelled
   "Sample result", exactly as before. Never present canned findings as if they
   came from the visitor's site. */

/* Where to send the submission. Same origin by default; an absolute origin
   from the lojo-api-base meta tag when the page is hosted apart from the scan
   (a static host cannot run /api/scan itself). */
function apiBase() {
  const tag = document.querySelector('meta[name="lojo-api-base"]');
  return ((tag && tag.content) || '').replace(/\/+$/, '');
}

function normalizeUrl(raw) {
  let v = (raw || '').trim().replace(/^https?:\/\//i, '').replace(/^www\./i, '').replace(/\/+$/, '');
  return v.toLowerCase();
}
function isValidDomain(raw) {
  const v = normalizeUrl(raw);
  return /^[a-z0-9-]+(\.[a-z0-9-]+)+(:\d{1,5})?(\/.*)?$/.test(v);
}
const ROLES = ['Founder / CEO', 'Marketing', 'Growth / SEO', 'Operations', 'Other'];

function Field({ label, children, error }) {
  return (
    <label style={{ display: 'block' }}>
      <span style={{ display: 'block', fontSize: 12.5, fontWeight: 500, color: 'var(--fg-muted)', marginBottom: 6, fontFamily: 'var(--font-sans)' }}>{label}</span>
      {children}
      <span style={{ display: 'block', minHeight: 15, marginTop: 4, fontSize: 11.5, color: 'var(--crit)', fontFamily: 'var(--font-mono)' }}>{error || ''}</span>
    </label>);

}

const inputStyle = (bad) => ({
  width: '100%', padding: '12px 13px', borderRadius: 'var(--r-md)', fontSize: 15,
  fontFamily: 'var(--font-sans)', color: 'var(--fg)', background: 'var(--navy)',
  border: '1px solid ' + (bad ? 'var(--crit)' : 'var(--line-strong)'),
  outline: 'none', transition: 'border-color .15s', boxSizing: 'border-box'
});

function IntakeForm() {
  const [v, setV] = React.useState({ name: '', email: '', company: '', website: '', role: '', describe: '' });
  const [err, setErr] = React.useState({});
  const [touched, setTouched] = React.useState({});
  const [phase, setPhase] = React.useState('form'); // form | running | result
  const [scan, setScan] = React.useState(null);     // /api/scan response, or null
  const set = (k) => (e) => setV((s) => ({ ...s, [k]: e.target.value }));

  const validate = () => {
    const e = {};
    if (!v.name.trim()) e.name = 'Required';
    if (!v.email.trim()) e.email = 'Required';else
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.email)) e.email = 'Enter a valid email';
    if (!v.company.trim()) e.company = 'Required';
    if (!v.website.trim()) e.website = 'Required';else
    if (!isValidDomain(v.website)) e.website = 'Enter a valid website';
    if (!v.role) e.role = 'Required';
    setErr(e);
    return Object.keys(e).length === 0;
  };

  const submit = async () => {
    setTouched({ name: 1, email: 1, company: 1, website: 1, role: 1 });
    if (!validate()) return;
    setPhase('running');
    const startedAt = Date.now();
    let next = null;
    try {
      const res = await fetch(apiBase() + '/api/scan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(v)
      });
      const data = await res.json();
      if (!res.ok && data && data.errors) {
        // The server validates too; surface its errors on the form.
        setErr(data.errors);
        setPhase('form');
        return;
      }
      if (data && data.ok && data.mode === 'scanned') next = data;
      else if (data && data.ok) next = { mode: 'captured', domain: data.domain };
    } catch (e) {
      next = null; // no endpoint behind the page — fall back to the sample
    }
    // Let the run log finish its beat rather than snapping between states.
    const elapsed = Date.now() - startedAt;
    setTimeout(() => { setScan(next); setPhase('result'); }, Math.max(0, 1800 - elapsed));
  };

  if (phase === 'result') return <ScanResult scan={scan} lead={v} domain={normalizeUrl(v.website)} name={v.name} onReset={() => {setScan(null);setPhase('form');}} />;

  if (phase === 'running') {
    return (
      <div style={formShell}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: 320, gap: 18, textAlign: 'center' }}>
          <span style={{ color: 'var(--accent)' }}><Icon name="spinner" size={40} stroke={1.6} /></span>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 500 }}>Reading {normalizeUrl(v.website)} the way AI does…</div>
          <RunLog />
        </div>
      </div>);

  }

  return (
    <div style={{ ...formShell, height: 'auto', minHeight: '100%', display: 'flex', flexDirection: 'column', gap: 'clamp(16px,2.2vw,22px)' }} id="audit">
      <div style={{ marginBottom: 0 }}>
        <div style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(22px,2.4vw,27px)', fontWeight: 600, letterSpacing: '-0.02em', lineHeight: 1.1 }}>Get your free AI visibility analysis

        </div>
        <p style={{ margin: '8px 0 0', color: 'var(--fg-muted)', fontSize: "18px" }}>Results within 24 hours.</p>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 'clamp(14px,2vw,20px)' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 14px' }}>
          <Field label="Name" error={touched.name && err.name}>
            <input style={inputStyle(touched.name && err.name)} value={v.name} onChange={set('name')} onBlur={() => setTouched((t) => ({ ...t, name: 1 }))} placeholder="Jordan Lee" />
          </Field>
          <Field label="Work email" error={touched.email && err.email}>
            <input style={inputStyle(touched.email && err.email)} value={v.email} onChange={set('email')} onBlur={() => setTouched((t) => ({ ...t, email: 1 }))} placeholder="jordan@brand.com" />
          </Field>
          <Field label="Company" error={touched.company && err.company}>
            <input style={inputStyle(touched.company && err.company)} value={v.company} onChange={set('company')} onBlur={() => setTouched((t) => ({ ...t, company: 1 }))} placeholder="CircadiaZen" />
          </Field>
          <Field label="Website" error={touched.website && err.website}>
            <input style={inputStyle(touched.website && err.website)} value={v.website} onChange={set('website')} onBlur={() => setTouched((t) => ({ ...t, website: 1 }))} placeholder="circadiazen.com" />
          </Field>
        </div>
        <Field label={<span>Describe your business <span style={{ color: 'var(--fg-subtle)', fontWeight: 400 }}>(optional)</span></span>}>
          <textarea style={{ ...inputStyle(false), minHeight: 64, resize: 'vertical', lineHeight: 1.5 }}
            value={v.describe} onChange={set('describe')} rows={2}
            placeholder="In 1–2 sentences, what does your business do?" />
        </Field>
        <Field label="Your role" error={touched.role && err.role}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {ROLES.map((r) =>
            <button key={r} type="button" onClick={() => {setV((s) => ({ ...s, role: r }));setTouched((t) => ({ ...t, role: 1 }));}}
            style={{ padding: '8px 13px', borderRadius: 'var(--r-pill)', fontSize: 13, fontFamily: 'var(--font-sans)', cursor: 'pointer',
              border: '1px solid ' + (v.role === r ? 'var(--accent)' : 'var(--line-strong)'),
              background: v.role === r ? 'var(--accent)' : 'transparent', color: v.role === r ? 'var(--on-accent)' : 'var(--fg-muted)',
              fontWeight: v.role === r ? 600 : 400 }}>
                {r}
              </button>
            )}
          </div>
        </Field>
      </div>

      <button className="btn btn-primary btn-lg" style={{ width: '100%', justifyContent: 'center', marginTop: 'auto' }} onClick={submit}>
        Run my free analysis <Icon name="arrow-right" size={19} />
      </button>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7, marginTop: -6, color: 'var(--fg-subtle)' }}>
        <Icon name="lock" size={13} />
        <span className="mono" style={{ fontSize: 11 }}>No card needed. We only read your public site.</span>
      </div>
    </div>);

}

const formShell = {
  background: 'var(--navy-2)', border: '1px solid var(--line-strong)', borderRadius: 'var(--r-2xl)',
  padding: 'clamp(22px,2.6vw,32px)', boxShadow: 'var(--sh-lg)',
  height: '100%', width: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center'
};

// Mirrors the phases of scripts/scan/free_scan.py, so what the visitor watches
// is what the scanner is actually doing.
function RunLog() {
  const lines = ['Reading robots.txt and crawler rules', 'Walking the sitemap', 'Fetching pages without JavaScript', 'Parsing structured data', 'Counting answerable buyer questions'];
  const [n, setN] = React.useState(0);
  React.useEffect(() => {const id = setInterval(() => setN((x) => Math.min(x + 1, lines.length)), 560);return () => clearInterval(id);}, []);
  return (
    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5, color: 'var(--fg-subtle)', display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'flex-start' }}>
      {lines.slice(0, n).map((l) =>
      <div key={l} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          <span style={{ color: 'var(--good)' }}><Icon name="check" size={13} stroke={2.4} /></span>{l}
        </div>
      )}
    </div>);

}

// ---------------- Result (real scan, or the labelled sample) ----------------

/* Used only when /api/scan is not reachable — a page hosted as a static file.
   Presented as a sample of the kind of thing the scan looks for, never as a
   result for the visitor's own site. */
const SAMPLE_FINDINGS = [
{ severity: 'crit', title: 'A “do-not-read” tag is hiding your top product from AI' },
{ severity: 'crit', title: 'Your clinical research page is invisible to AI engines' },
{ severity: 'warn', title: 'You answer 7 of ~80 questions buyers ask AI in your category' }];

const SEV_STYLE = { crit: 'crit', warn: 'warn', ok: 'good' };

function FindingRow({ f, expanded }) {
  const tone = SEV_STYLE[f.severity] || 'warn';
  return (
    <div style={{ display: 'flex', gap: 11, alignItems: 'flex-start', padding: '12px 14px', borderRadius: 'var(--r-md)',
      background: `var(--${tone}-bg)`, border: '1px solid color-mix(in oklab, var(--' + tone + ') 26%, transparent)' }}>
      <span style={{ width: 9, height: 9, borderRadius: '50%', background: `var(--${tone})`, marginTop: 5, flex: '0 0 auto', boxShadow: `0 0 10px var(--${tone})` }}></span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 14, color: 'var(--fg)', lineHeight: 1.45 }}>{f.title}</div>
        {expanded && f.fix &&
        <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', lineHeight: 1.5, marginTop: 5 }}>
            <span style={{ color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)', fontSize: 11 }}>FIX · </span>{f.fix}
          </div>
        }
      </div>
    </div>);

}

function ScanResult({ scan, lead, domain, name, onReset }) {
  const live = scan && scan.mode === 'scanned';
  // idle -> sending -> done. The lead was already captured when the scan ran;
  // this records that they asked for the rest, which is a different signal.
  const [request, setRequest] = React.useState('idle');

  const unlock = async () => {
    if (request !== 'idle') return;
    setRequest('sending');
    try {
      const res = await fetch(apiBase() + '/api/request-report', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: (lead && lead.name) || name || '',
          email: (lead && lead.email) || '',
          company: (lead && lead.company) || '',
          website: (lead && lead.website) || domain,
          critical: live ? scan.counts.critical : null,
          warning: live ? scan.counts.warning : null,
        })
      });
      setRequest(res.ok ? 'done' : 'error');
    } catch (e) {
      setRequest('error');
    }
  };
  const shown = live ? scan.findings.slice(0, 4) : SAMPLE_FINDINGS;
  const remaining = live ? Math.max(0, scan.findings.length - shown.length) : 8;
  const first = name ? name.split(' ')[0] : null;

  const heading = live ?
  (first ? `${first}, here’s what AI sees on ${scan.domain}` : `What AI sees on ${scan.domain}`) :
  (first ? `${first}, here’s a sample` : 'A sample report');

  const blurb = live ?
  `We read ${scan.pages_checked} page${scan.pages_checked === 1 ? '' : 's'} of ${scan.domain} the way an AI crawler does and found ${scan.counts.critical} critical issue${scan.counts.critical === 1 ? '' : 's'} and ${scan.counts.warning} warning${scan.counts.warning === 1 ? '' : 's'}. The full report covers all of them, with step-by-step fixes.` :
  `Based on a real analysis. This is the kind of thing we look for. Your full report covers every finding on ${domain}, with step-by-step fixes.`;

  return (
    <div id="scan-result" style={{ ...formShell, height: 'auto', minHeight: '100%', justifyContent: 'flex-start' }} className="scroll-thin">
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
        {live ?
        <span className="chip" style={{ borderColor: 'var(--good)', color: 'var(--good)' }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--good)' }}></span>Live scan
          </span> :

        <span className="chip" style={{ borderColor: 'var(--warn)', color: 'var(--warn)' }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--warn)' }}></span>Sample result
          </span>
        }
      </div>
      <div style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(20px,2.3vw,25px)', fontWeight: 600, letterSpacing: '-0.02em', lineHeight: 1.15, marginBottom: 6 }}>
        {heading}
      </div>
      <p style={{ margin: '0 0 16px', fontSize: 14, color: 'var(--fg-muted)', lineHeight: 1.5 }}>{blurb}</p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginBottom: 18 }}>
        {shown.map((f, i) => <FindingRow key={i} f={f} expanded={live} />)}
        {remaining > 0 &&
        <div style={{ textAlign: 'center', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-subtle)', paddingTop: 2 }}>
            + {remaining} more in your full report
          </div>
        }
      </div>

      {request === 'done' ?
      <div style={{ padding: '14px 16px', borderRadius: 'var(--r-md)', background: 'var(--good-bg)',
        border: '1px solid color-mix(in oklab, var(--good) 30%, transparent)', textAlign: 'center' }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, color: 'var(--good)', marginBottom: 4 }}>
            <Icon name="check" size={17} stroke={2.4} />
            <span style={{ fontWeight: 600, fontSize: 14.5 }}>Request received</span>
          </div>
          <div style={{ fontSize: 13, color: 'var(--fg-muted)', lineHeight: 1.5 }}>
            We’ll send the full report for {live ? scan.domain : domain} to{' '}
            <span style={{ color: 'var(--fg)' }}>{(lead && lead.email) || 'your inbox'}</span> within 24 hours.
          </div>
        </div> :

      <button className="btn btn-primary btn-lg" style={{ width: '100%', justifyContent: 'center' }}
        onClick={unlock} disabled={request === 'sending'}>
          {request === 'sending' ? 'Sending…' : 'Unlock the full report'}
          {request !== 'sending' && <Icon name="arrow-right" size={19} />}
        </button>
      }
      {request === 'error' &&
      <div style={{ marginTop: 10, textAlign: 'center', fontSize: 12.5, color: 'var(--warn)' }}>
          That didn’t go through. Email us and we’ll send it over.
        </div>
      }
      {live && request !== 'done' &&
      <div style={{ textAlign: 'center', marginTop: 10, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-subtle)', lineHeight: 1.5 }}>
          This scan checks what AI engines can read on your site.<br />
          Whether they name you today is measured in the full benchmark.
        </div>
      }
      <button onClick={onReset} style={{ width: '100%', marginTop: 10, background: 'transparent', border: 'none', color: 'var(--fg-subtle)',
        fontFamily: 'var(--font-mono)', fontSize: 12, cursor: 'pointer', padding: 6 }}>
        ← Run another site
      </button>
    </div>);

}

Object.assign(window, { IntakeForm });