/* global React */
const APPLY_DS = window.OORTDesignSystem_b4ed3c;
const Icon = window.Icon;

/* ---------- small helpers ---------- */
function StepHead({ kicker, title, lead }) {
  return (
    <React.Fragment>
      <span className="eyebrow ion">{kicker}</span>
      <h2>{title}</h2>
      <p className="lead">{lead}</p>
    </React.Fragment>
  );
}

function Choice({ on, onToggle, title, desc }) {
  return (
    <div className={'choice' + (on ? ' is-on' : '')} onClick={onToggle} role="checkbox" aria-checked={on} tabIndex={0}
      onKeyDown={(e) => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); onToggle(); } }}>
      <span className="choice__box"><Icon name="check" /></span>
      <span>
        <span className="choice__t">{title}</span>
        {desc ? <span className="choice__d">{desc}</span> : null}
      </span>
    </div>
  );
}

/* ---------- step definitions ---------- */
/* Identity comes LAST now: the ring vets you first, and only checks your name
   at the very end — which is, of course, where it finds you out. */
const STEPS = ['Means', 'Suite', 'Provenance', 'Disposition', 'Discretion', 'Identity'];

const NET_WORTH = [
  { value: '', label: 'Select a band…' },
  { value: '50-250m', label: '$50M – $250M' },
  { value: '250m-1b', label: '$250M – $1B' },
  { value: '1-10b', label: '$1B – $10B' },
  { value: '10b+', label: '$10B and up' },
  { value: 'decline', label: 'Prefer not to disclose' },
];
const CLEARANCE = [
  { value: '', label: 'Select a tier…' },
  { value: 'economy', label: 'Cuck Airlock — $2.4M / yr' },
  { value: 'business', label: 'Breeder Berth — $18M / yr' },
  { value: 'founder', label: "Founder's Circle — by bloodline" },
];
const GRAVITY = [
  { value: '0', label: '0 g — full float' },
  { value: '0.2', label: '0.2 g — gentle drift' },
  { value: '0.4', label: '0.4 g — recline' },
  { value: '1', label: 'Earth-normal (whatever for?)' },
];
const TEMPO = [
  { value: 'languid', label: 'Languid' },
  { value: 'spirited', label: 'Spirited' },
  { value: 'crew', label: "At the crew's discretion" },
];
const PREFS = [
  ['zerog', 'Zero-gravity recreation', 'The headline feature. Most guests never ask for the ring back.'],
  ['themed', 'Themed and ceremonial evenings', 'Robes, masks, the occasional liturgy. The wardrobe crew has seen everything and recalls none of it.'],
  ['apparatus', 'Apparatus and equipment', 'The ring keeps a discreet, well-maintained inventory. Itemise on arrival, or leave the line blank.'],
  ['audience', 'An audience, or none', 'Some guests prefer no witnesses; others, a carefully vetted few. State your number.'],
  ['protocol', 'Honorifics and house rules', 'Titles, hierarchies, and protocols of your own design — rehearsed by the crew before you dock.'],
  ['apothecary', "The apothecary's discretion", "A licensed curator handles the evening's chemistry. Recreational, monitored, off-record."],
  ['companionship', 'Companionship, arranged', 'Introductions handled entirely by the concierge. Vetted, willing, and never named.'],
  ['maxdisc', 'Maximum-discretion protocol', 'You were never here. Neither was anyone — or anything — you brought.'],
];

/* ---- the eerie/coded vetting (provenance + disposition) ---- */
const ORIGIN = [
  { value: '', label: 'Select…' },
  { value: 'inherited', label: 'Inherited — and so was theirs' },
  { value: 'quiet', label: 'Made quietly, several lines back' },
  { value: 'loud', label: 'Made loudly, this generation' },
  { value: 'always', label: 'It was always simply there' },
];
const LINE = [
  { value: '', label: 'Select…' },
  { value: 'short', label: 'Three names, then the record stops' },
  { value: 'founding', label: 'Unbroken to the founding' },
  { value: 'older', label: 'Older than the record that would hold it' },
  { value: 'counted', label: 'We are not counted. We count.' },
];
const PROVENANCE = [
  ['skip', 'I have never stood in a line I could not have skipped.'],
  ['faces', 'There are people in my employ whose faces I have never learned.'],
  ['living', 'Nothing I keep was given to me by anyone still living.'],
  ['year', 'I can name the year my family stopped being counted and began counting.'],
];

const AFTERIMAGE = [
  { value: '', label: 'Select…' },
  { value: 'nothing', label: 'Nothing at all' },
  { value: 'warmth', label: 'A faint, agreeable warmth' },
  { value: 'vindicated', label: 'Quietly vindicated' },
  { value: 'never', label: 'I have never pictured them' },
];
const DISPOSITION = [
  ['remade', "I accept that boarding means being unmade, and remade, in the Founder's image."],
  ['sever', 'I would sever any tie beneath the airlock to keep the one above it.'],
  ['glass', 'I have always known which side of the glass I was born on.'],
  ['sealed', 'When the doors seal, I expect to be counted among those inside.'],
];

const CONSENT = [
  ['manifest', 'I understand the guest manifest does not exist.'],
  ['reentry', 'I accept that re-entry is scheduled at the Founder’s discretion.'],
  ['silence', 'I will not discuss the Palace — in this life, or in this orbit.'],
  ['age', 'I am over 18 and of sound, solvent, well-capitalised mind.'],
];

const PROC_LINES = [
  ['file-search', 'Lifting provenance from your declared name…'],
  ['users', 'Matching your line against the founding families…'],
  ['wallet', 'Weighing your means against your origin…'],
  ['orbit', 'Measuring your distance from the surface…'],
  ['loader', 'Returning the ring’s verdict…'],
];

function makeCase(name) {
  let h = 0;
  const s = (name || 'applicant') + Date.now();
  for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0;
  const hex = h.toString(16).toUpperCase().slice(0, 6).padStart(6, '0');
  return { file: 'RJ-' + hex };
}

/* ============================================================ */
function ApplyFlow({ onClose }) {
  const { Button, Input, Select, Switch } = APPLY_DS;
  const [step, setStep] = React.useState(0);
  const [phase, setPhase] = React.useState('form'); // form | processing | rejected
  const [data, setData] = React.useState({
    worth: '', clearance: '',
    prefs: {}, gravity: '0', tempo: 'spirited', safeword: true, autoSun: true,
    origin: '', line: '', provenance: {},
    afterimage: '', disposition: {},
    consent: {},
    name: '', callsign: '', email: '',
  });
  const set = (k, v) => setData((d) => ({ ...d, [k]: v }));
  const toggle = (group, key) => setData((d) => ({ ...d, [group]: { ...d[group], [key]: !d[group][key] } }));

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

  /* validation — indices align with STEPS */
  const emailOk = /.+@.+\..+/.test(data.email);
  const stepValid = [
    !!data.worth && !!data.clearance,        // 0 Means
    true,                                     // 1 Suite
    !!data.origin && !!data.line,             // 2 Provenance
    !!data.afterimage,                        // 3 Disposition
    CONSENT.every(([k]) => data.consent[k]),  // 4 Discretion
    data.name.trim().length > 1 && emailOk,   // 5 Identity
  ][step];

  const next = () => {
    if (!stepValid) return;
    if (step < STEPS.length - 1) setStep(step + 1);
    else runProcessing();
  };
  const back = () => { if (step > 0) setStep(step - 1); };

  /* processing animation */
  const [procShown, setProcShown] = React.useState(0);
  const [procPct, setProcPct] = React.useState(6);
  function runProcessing() {
    setPhase('processing');
    setProcShown(0); setProcPct(6);
    PROC_LINES.forEach((_, i) => {
      setTimeout(() => { setProcShown(i + 1); setProcPct(Math.round(((i + 1) / PROC_LINES.length) * 92) + 8); }, 520 * (i + 1));
    });
    setTimeout(() => setPhase('rejected'), 520 * (PROC_LINES.length + 1) + 420);
  }

  const rec = React.useMemo(() => makeCase(data.name), [phase]);

  /* ---------- render phases ---------- */
  if (phase === 'processing') {
    const { Progress } = APPLY_DS;
    return (
      <div className="apply">
        <div className="apply__bar"><Brandline /></div>
        <div className="apply__body">
          <div className="proc">
            <Icon name="loader" className="proc-loader spin" />
            <h2>The ring is reading you</h2>
            <Progress value={procPct} label="Determination" tone="ion" />
            <div className="proc__log">
              {PROC_LINES.map(([icon, txt], i) => (
                <div className={'proc__line' + (i < procShown ? ' show' : '')} key={txt}>
                  <Icon name={i < procShown ? 'check' : icon} />{txt}
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
  }

  if (phase === 'rejected') {
    const tierLabel = (CLEARANCE.find((c) => c.value === data.clearance) || {}).label || 'Cuck Airlock';
    const first = data.name.trim().split(' ')[0] || 'Applicant';
    return (
      <div className="apply">
        <div className="apply__bar">
          <Brandline />
          <div style={{ marginLeft: 'auto' }}>
            <Button variant="ghost" size="sm" onClick={onClose}>Close</Button>
          </div>
        </div>
        <div className="apply__body">
          <div className="declined">
            <span className="declined__stamp"><Icon name="ban" /> Declined</span>
            <h2>Thank you, {first}.<br /><span className="crit">The answer is no.</span></h2>
            <p>
              The review was instant, and unanimous. Your liquidity is loud, your name
              returns results, and your line does not survive a second glance. You are —
              the ring regrets nothing — of the <span className="crit">unwashed masses</span>.
              The airlock was never going to open for you.
            </p>

            <div className="dossier">
              <div className="dossier__top">
                <span className="dossier__brand"><Icon name="file-search" /> ZHOSS ORBITAL · DETERMINATION</span>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-muted)' }}>{rec.file}</span>
              </div>
              <div className="dossier__grid">
                <div className="dossier__cell"><div className="dossier__k">Applicant</div><div className="dossier__v">{data.name || 'Applicant'}</div></div>
                <div className="dossier__cell"><div className="dossier__k">Verdict</div><div className="dossier__v crit">DECLINED</div></div>
                <div className="dossier__cell"><div className="dossier__k">Tier requested</div><div className="dossier__v struck">{tierLabel.split(' — ')[0]}</div></div>
                <div className="dossier__cell"><div className="dossier__k">Provenance</div><div className="dossier__v">Recent</div></div>
                <div className="dossier__cell"><div className="dossier__k">Origin</div><div className="dossier__v">Detectable</div></div>
                <div className="dossier__cell"><div className="dossier__k">Standing</div><div className="dossier__v">None</div></div>
                <div className="dossier__cell full">
                  <div className="dossier__k">Classification · final</div>
                  <div className="dossier__bars">
                    {Array.from({ length: 52 }).map((_, i) => (
                      <i key={i} style={{ height: (((rec.file.charCodeAt(i % rec.file.length) + i * 7) % 4) + 1) * 22 + '%' }} />
                    ))}
                  </div>
                  <div className="dossier__v" style={{ marginTop: 10, letterSpacing: '0.18em' }}>UNWASHED · COMMON · SURFACE-BOUND</div>
                </div>
              </div>
            </div>

            <div style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
              <Button variant="primary" className="lux" onClick={onClose}>Return to the surface</Button>
              <Button variant="secondary" onClick={() => { setPhase('form'); setStep(0); }}>Reapply (it won't help)</Button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  /* ---------- form ---------- */
  return (
    <div className="apply">
      <div className="apply__bar">
        <Brandline />
        <div className="apply__steps">
          {STEPS.map((label, i) => (
            <div className={'pip' + (i === step ? ' is-active' : i < step ? ' is-done' : '')} key={label}>
              {i > 0 ? <span className="pip__line" /> : null}
              <span className="pip__dot">{i < step ? <Icon name="check" /> : i + 1}</span>
              <span className="pip__label">{label}</span>
            </div>
          ))}
        </div>
        <Button variant="ghost" size="sm" onClick={onClose} aria-label="Close">✕</Button>
      </div>

      <div className="apply__body">
        <div className="apply__panel" key={step}>
          {step === 0 && (
            <React.Fragment>
              <StepHead kicker="// Step 1 — Means" title="A formality. The airlock isn't cheap."
                lead="We don't verify on this screen — but we will. Discretion runs both ways." />
              <div className="field-grid">
                <Select label="Declared net worth" options={NET_WORTH} value={data.worth}
                  onChange={(e) => set('worth', e.target.value)} />
                <Select label="Clearance tier requested" options={CLEARANCE} value={data.clearance}
                  onChange={(e) => set('clearance', e.target.value)}
                  hint={data.clearance === 'founder' ? "The Founder's Circle is by bloodline — applying opens a hereditary review." : ''} />
              </div>
            </React.Fragment>
          )}

          {step === 1 && (
            <React.Fragment>
              <StepHead kicker="// Step 2 — Suite" title="Configure your stay."
                lead="Select everything that appeals. The ring is reconfigured per guest, between visits, by a crew you'll never meet twice." />
              <div className="choices">
                {PREFS.map(([k, t, d]) => (
                  <Choice key={k} on={!!data.prefs[k]} onToggle={() => toggle('prefs', k)} title={t} desc={d} />
                ))}
              </div>
              <div className="field-grid two" style={{ marginTop: 22 }}>
                <Select label="Preferred resident gravity" options={GRAVITY} value={data.gravity}
                  onChange={(e) => set('gravity', e.target.value)} />
                <Select label="Evening tempo" options={TEMPO} value={data.tempo}
                  onChange={(e) => set('tempo', e.target.value)} />
              </div>
              <div className="field-grid two" style={{ marginTop: 18 }}>
                <div style={{ display: 'flex', alignItems: 'center' }}>
                  <Switch checked={data.safeword} onChange={(e) => set('safeword', e.target.checked)} label="Keep a house safeword on file" />
                </div>
                <div style={{ display: 'flex', alignItems: 'center' }}>
                  <Switch checked={data.autoSun} onChange={(e) => set('autoSun', e.target.checked)} label="Schedule sunrises automatically" />
                </div>
              </div>
            </React.Fragment>
          )}

          {step === 2 && (
            <React.Fragment>
              <StepHead kicker="// Step 3 — Provenance" title="Where do you come from?"
                lead="The ring reads provenance before it reads anything else. Answer plainly — it already knows when you don't." />
              <div className="field-grid two">
                <Select label="Your money is…" options={ORIGIN} value={data.origin}
                  onChange={(e) => set('origin', e.target.value)} />
                <Select label="Your line runs…" options={LINE} value={data.line}
                  onChange={(e) => set('line', e.target.value)} />
              </div>
              <div className="choices" style={{ marginTop: 22 }}>
                {PROVENANCE.map(([k, t]) => (
                  <Choice key={k} on={!!data.provenance[k]} onToggle={() => toggle('provenance', k)} title={t} />
                ))}
              </div>
            </React.Fragment>
          )}

          {step === 3 && (
            <React.Fragment>
              <StepHead kicker="// Step 4 — Disposition" title="What the ring asks of its own."
                lead="There are no wrong answers here. Only revealing ones. The crew has long since stopped flinching." />
              <div className="choices">
                {DISPOSITION.map(([k, t]) => (
                  <Choice key={k} on={!!data.disposition[k]} onToggle={() => toggle('disposition', k)} title={t} />
                ))}
              </div>
              <div className="field-grid" style={{ marginTop: 22 }}>
                <Select label="The ones who stay on the surface — when you picture them, you feel…"
                  options={AFTERIMAGE} value={data.afterimage}
                  onChange={(e) => set('afterimage', e.target.value)} />
              </div>
            </React.Fragment>
          )}

          {step === 4 && (
            <React.Fragment>
              <StepHead kicker="// Step 5 — Discretion" title="The terms of the airlock."
                lead="All four are required. They are also the only contract the Palace keeps." />
              <div className="choices">
                {CONSENT.map(([k, t]) => (
                  <Choice key={k} on={!!data.consent[k]} onToggle={() => toggle('consent', k)} title={t} />
                ))}
              </div>
            </React.Fragment>
          )}

          {step === 5 && (
            <React.Fragment>
              <StepHead kicker="// Step 6 — Identity" title="And finally — who's been answering?"
                lead="We take the name last, and on purpose. It is the easiest thing in the world to check." />
              <div className="field-grid">
                <Input label="Full name" placeholder="Your legal name" value={data.name}
                  onChange={(e) => set('name', e.target.value)} />
                <div className="field-grid two">
                  <Input label="Call sign (optional)" mono placeholder="RESIDENT-001" value={data.callsign}
                    onChange={(e) => set('callsign', e.target.value)} hint="How crew would address you, in private." />
                  <Input label="Private email" type="email" placeholder="you@empire.com" value={data.email}
                    onChange={(e) => set('email', e.target.value)}
                    error={data.email && !emailOk ? 'A reachable address, please.' : ''} />
                </div>
              </div>
            </React.Fragment>
          )}
        </div>
      </div>

      <div className="apply__foot">
        {step > 0
          ? <Button variant="ghost" onClick={back} icon={<Icon name="arrow-left" />}>Back</Button>
          : <Button variant="ghost" onClick={onClose}>Cancel</Button>}
        <span className="spacer" />
        <span className="apply__hint">Step {step + 1} of {STEPS.length}</span>
        <Button variant="primary" className="lux" disabled={!stepValid} onClick={next}
          iconRight={<Icon name={step === STEPS.length - 1 ? 'rocket' : 'arrow-right'} />}>
          {step === STEPS.length - 1 ? 'Submit application' : 'Continue'}
        </Button>
      </div>
    </div>
  );
}

function Brandline() {
  return (
    <div className="brand">
      <svg className="brand__mark" viewBox="0 0 32 32" fill="none" aria-hidden="true">
        <circle cx="16" cy="16" r="11" stroke="currentColor" strokeWidth="1.4" />
        <ellipse cx="16" cy="16" rx="14.5" ry="5.4" stroke="currentColor" strokeWidth="1.1" opacity="0.7" transform="rotate(-28 16 16)" />
        <circle cx="16" cy="16" r="3.1" fill="currentColor" />
      </svg>
      <span className="brand__name">ZHOSS ORBITAL</span>
      <span className="brand__sub">Application</span>
    </div>
  );
}

Object.assign(window, { ApplyFlow });
