/* global React, BrainMark */
const { useState: useStateUI } = React;

/* ---------------- icons (flow) ---------------- */
const I = {
  check: (s = 14) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17.5 19 7" /></svg>,
  checkDark: (s = 30) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17.5 19 7" /></svg>,
  pencil: (s = 14) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="m15 5 4 4" /><path d="M4 20l1-4L16 5l3 3L8 19l-4 1Z" /></svg>,
  arrow: (s = 16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14" /><path d="m13 5 7 7-7 7" /></svg>,
  back: (s = 16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5" /><path d="m11 5-7 7 7 7" /></svg>,
  chev: (s = 16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m6 9 6 6 6-6" /></svg>,
  home: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 11.5 12 4l9 7.5" /><path d="M5 10.5V20h14v-9.5" /><path d="M10 20v-5h4v5" /></svg>,
  yes: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17.5 19 7" /></svg>,
  no: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M6 6l12 12M18 6 6 18" /></svg>,
  seedling: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 21v-8" /><path d="M12 13c0-3 2-5 6-5 0 3-2 5-6 5Z" /><path d="M12 14c0-3-2-5-6-5 0 3 2 5 6 5Z" /></svg>,
  doc: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M7 3h7l5 5v13H7z" /><path d="M14 3v5h5" /><path d="M10 13h6M10 17h6" /></svg>,
  rocket: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M5 15c-1.5 1.5-2 5-2 5s3.5-.5 5-2" /><path d="M9 13c5-7 9-9 11-9 0 2-2 6-9 11l-4 .5z" /><path d="M9 13l2 2" /><circle cx="15" cy="9" r="1.3" /></svg>,
  building: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="5" y="3" width="14" height="18" rx="1" /><path d="M9 7h2M13 7h2M9 11h2M13 11h2M9 15h2M13 15h2" /></svg>,
  invest: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M4 19h16" /><path d="M7 19v-5M11 19V9M15 19v-8M19 19V6" /></svg>,
  units: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="9" width="8" height="12" /><rect x="13" y="3" width="8" height="18" /><path d="M6 13h2M6 17h2M16 7h2M16 11h2M16 15h2" /></svg>,
  condo: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="6" y="3" width="12" height="18" rx="1" /><path d="M9 7h2M13 7h2M9 11h2M13 11h2M10 21v-3h4v3" /></svg>,
  factory: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 21V10l5 3V10l5 3V7l8 5v9z" /></svg>,
  coop: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="8" r="3" /><circle cx="16" cy="10" r="2.4" /><path d="M4 20c0-3 2-5 5-5s5 2 5 5" /><path d="M14.5 20c.2-2.3 1.4-3.6 3.5-3.6 1.8 0 2.8 1 3 3" /></svg>,
  pin: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 21s7-6 7-11a7 7 0 1 0-14 0c0 5 7 11 7 11Z" /><circle cx="12" cy="10" r="2.4" /></svg>,
  refresh: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M20 7a8 8 0 0 0-14.3-3" /><path d="M4 17a8 8 0 0 0 14.3 3" /><path d="M16.5 4H20v3.5" /><path d="M7.5 20H4v-3.5" /></svg>,
  cash: (s = 24) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="6" width="18" height="12" rx="2" /><circle cx="12" cy="12" r="2.6" /><path d="M6.5 9.5v5M17.5 9.5v5" /></svg>,
  plus: (s = 18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M12 5v14M5 12h14" /></svg>,
  trash: (s = 14) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13" /></svg>,
  user: (s = 22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="4" /><path d="M5 20c0-3.3 3.1-6 7-6s7 2.7 7 6" /></svg>,
  bolt: (s = 22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M13 2 4 14h7l-1 8 9-12h-7z" /></svg>,
  lock: (s = 16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="10" width="16" height="11" rx="2" /><path d="M8 10V7a4 4 0 0 1 8 0v3" /></svg>,
  plusCircle: (s = 18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><circle cx="12" cy="12" r="9" /><path d="M12 8v8M8 12h8" /></svg>,
};

/* ---------------- progress ---------------- */
const POS_SECTIONS = ['Purchase Details', 'Borrower Information', 'Employment & Income', 'Assets', 'Credit / Declarations', 'Review & Submit'];

function Progress({ section = 0, fill = 0, sections = POS_SECTIONS }) {
  return (
    <div className="progress">
      <div className="progress-top">
        <span className="progress-label">{sections[section]}</span>
        <span className="progress-count mono">{section + 1} / {sections.length}</span>
      </div>
      <div className="progress-track">
        {sections.map((s, i) => (
          <div key={s}
            className={'progress-seg ' + (i < section ? 'done' : i === section ? 'active' : '')}
            style={i === section ? { '--fill': fill + '%' } : undefined} />
        ))}
      </div>
    </div>
  );
}

/* ---------------- step header ---------------- */
function StepHead({ title, sub, eyebrow = 'BEVRI' }) {
  return (
    <div className="step-head">
      <span className="step-eyebrow">
        <span className="ava"><BrainMark size={20} /></span>
        <span className="mono">{eyebrow}</span>
      </span>
      <h1 className="step-title">{title}</h1>
      {sub && <p className="step-sub">{sub}</p>}
    </div>
  );
}

/* ---------------- option / select card ---------------- */
function Opt({ icon, title, sub, selected, onClick, twoUp }) {
  return (
    <button className={'opt' + (selected ? ' sel' : '')} onClick={onClick} aria-pressed={selected}>
      {icon && <span className="opt-icon">{icon}</span>}
      <span className="opt-main">
        <span className="opt-title">{title}</span>
        {sub && <span className="opt-sub">{sub}</span>}
      </span>
      <span className="opt-radio">{I.check(13)}</span>
    </button>
  );
}

/* ---------------- tooltip (inline ? popover) ---------------- */
function Tooltip({ text }) {
  const [open, setOpen] = useSH(false);
  return (
    <span className="tt-wrap">
      <button className="tt-btn" type="button" onClick={e => { e.preventDefault(); setOpen(o => !o); }} aria-label="More info">?</button>
      {open && <span className="tt-pop">{text}</span>}
    </span>
  );
}

/* ---------------- select dropdown ---------------- */
function Select({ label, optional, value, onChange, options, placeholder = 'Select…', error, tooltip }) {
  // options: array of strings OR {value,label}
  const opts = (options || []).map(o => typeof o === 'string' ? { value: o, label: o } : o);
  return (
    <label className="field">
      {label && <span className="field-lbl">{label}{optional && <span className="opt-tag">  ·  optional</span>}{tooltip && <Tooltip text={tooltip} />}</span>}
      <span className="select-wrap">
        <select className={'input select' + (error ? ' err' : '') + (value ? '' : ' placeholder')}
          value={value} onChange={e => onChange(e.target.value)}>
          <option value="" disabled>{placeholder}</option>
          {opts.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
        </select>
        <span className="select-chev">{I.chev(18)}</span>
      </span>
      {error && <span className="field-err">{error}</span>}
    </label>
  );
}

/* ---------------- form field ---------------- */
function Field({ label, optional, value, onChange, placeholder, type = 'text', error, prefix, suffix, inputMode, textarea, onBlur, hint, tooltip, autofilled }) {
  return (
    <label className={'field' + (autofilled ? ' field-flash' : '')}>
      <span className="field-lbl">
        {label}{optional && <span className="opt-tag">  ·  optional</span>}
        {tooltip && <Tooltip text={tooltip} />}
      </span>
      {hint && <span className="field-hint">{hint}</span>}
      {textarea
        ? <textarea className={'input input-textarea' + (error ? ' err' : '')} value={value} rows={3}
            onChange={e => onChange(e.target.value)} onBlur={onBlur} placeholder={placeholder} />
        : <span className={'input-prefix' + (suffix ? ' input-suffix' : '')}>
            {prefix && <span>{prefix}</span>}
            <input className={'input' + (error ? ' err' : '')} type={type} value={value}
              inputMode={inputMode}
              onChange={e => onChange(e.target.value)} onBlur={onBlur} placeholder={placeholder} />
            {suffix && <span>{suffix}</span>}
          </span>}
      {error && <span className="field-err">{error}</span>}
    </label>
  );
}

/* ---------------- checkbox ---------------- */
function CheckRow({ checked, onToggle, children }) {
  return (
    <div className="agree-row" onClick={onToggle} role="checkbox" aria-checked={checked} tabIndex={0}
      onKeyDown={e => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); onToggle(); } }}>
      <span className={'checkbox' + (checked ? ' on' : '')}>{I.check(14)}</span>
      <span className="agree-text">{children}</span>
    </div>
  );
}

/* ---------------- nav footer ---------------- */
function NavFooter({ onBack, onNext, nextLabel = 'Next', nextDisabled, backLabel = 'Back' }) {
  return (
    <div className="step-nav">
      <button className="btn btn-secondary" onClick={onBack}>{I.back(16)}{backLabel}</button>
      <button className="btn btn-primary" onClick={onNext} disabled={nextDisabled}>
        {nextLabel}{I.arrow(16)}
      </button>
    </div>
  );
}

/* ---------------- Bevri Operator helper popover ---------------- */
function Helper({ label = "What's the difference?", items }) {
  const [open, setOpen] = useStateUI(false);
  return (
    <div className="helper-wrap">
      <button className={'helper-btn' + (open ? ' open' : '')} onClick={() => setOpen(o => !o)}>
        <span className="ava"><BrainMark size={18} /></span>
        {label}
      </button>
      {open && (
        <div className="helper-pop">
          <div className="helper-pop-head">
            <span className="ava"><BrainMark size={22} /></span>
            <span><b style={{ display: 'block' }}>Bevri Operator</b><span className="mono">here to help</span></span>
          </div>
          <dl>
            {items.map(it => (
              <div key={it.t}><dt>{it.t}</dt><dd>{it.d}</dd></div>
            ))}
          </dl>
        </div>
      )}
    </div>
  );
}

/* ---------------- expandable help link ---------------- */
function HelpLink({ q, a }) {
  const [open, setOpen] = useStateUI(false);
  return (
    <div>
      <button className={'help-link' + (open ? ' open' : '')} onClick={() => setOpen(o => !o)}>
        {q}<span className="chev">{I.chev(16)}</span>
      </button>
      {open && <div className="help-body">{a}</div>}
    </div>
  );
}

/* ---------------- ZIP -> city/state autofill ---------------- */

// Portal's own multi-source lookup (Zippopotam -> FCC -> Census), free and
// keyless, already used by the LOS. Cached per ZIP; fetch failures are not
// cached so a flaky network can retry.
const __bevriZipCache = {};
function bevriZipLookup(zip) {
  const z = String(zip || '').replace(/\D/g, '');
  if (z.length !== 5) return Promise.resolve(null);
  if (__bevriZipCache[z] !== undefined) return Promise.resolve(__bevriZipCache[z]);
  return fetch('/api/location/lookup?zip=' + z, { credentials: 'same-origin' })
    .then(r => (r.ok ? r.json() : null))
    .then(d => {
      const hit = d && d.city && d.state ? { city: d.city, state: d.state, county: d.county || '' } : null;
      __bevriZipCache[z] = hit;
      return hit;
    })
    .catch(() => null);
}

/**
 * ZIP input that looks up city/state when it reaches 5 digits and hands the
 * hit to onFill. The parent applies its own policy (fill empty fields,
 * replace a previous autofill, never touch hand-typed values). Shows a small
 * spinner in the field while the lookup is in flight; an unknown ZIP fails
 * silently and the borrower just types city/state as before.
 */
function ZipField({ value, onChange, onFill, error, placeholder = '94404', label = 'ZIP code' }) {
  const { useState: useZF, useEffect: useZFE, useRef: useZFR } = React;
  const [busy, setBusy] = useZF(false);
  const doneRef = useZFR('');
  const onFillRef = useZFR(onFill);
  onFillRef.current = onFill;
  useZFE(() => {
    const z = String(value || '').replace(/\D/g, '');
    if (z.length !== 5 || doneRef.current === z) { setBusy(false); return undefined; }
    let alive = true;
    setBusy(true);
    bevriZipLookup(z).then(hit => {
      if (!alive) return;
      setBusy(false);
      doneRef.current = z;
      if (hit && onFillRef.current) onFillRef.current(hit);
    });
    return () => { alive = false; };
  }, [value]);
  return (
    <Field label={label} inputMode="numeric" value={value} onChange={onChange} placeholder={placeholder}
      error={error} suffix={busy ? <span className="zip-spin" aria-label="Looking up ZIP" /> : undefined} />
  );
}

Object.assign(window, { I, Progress, StepHead, Opt, Field, Select, CheckRow, NavFooter, Helper, HelpLink, Tooltip, ZipField, bevriZipLookup });
