/* Main app shell — wizard navigation, state, aside summary. */

const { useState: useS, useEffect: useE, useMemo: useM } = React;

const STEPS = [
  { id: "clade",      name: "Clade",      key: "cladeId" },
  { id: "species",    name: "Species",    key: "speciesId" },
  { id: "class",      name: "Calling",    key: "classId" },
  { id: "background", name: "History",    key: "backgroundId" },
  { id: "stats",      name: "Abilities",  key: "stats" },
  { id: "skills",     name: "Skills",     key: "skills" },
  { id: "review",     name: "Sign",       key: "name" },
];

const App = ({ data, tweaks, setTweaks }) => {
  const [step, setStep] = useS(0);
  const [state, setState] = useS(() => ({
    data,
    cladeId: "canidae",
    speciesId: data.species.find(s => s.clade_id === "canidae")?.id,
    classId: "fangsworn",
    backgroundId: "pack_raised",
    statMethod: "array",
    statPool: STANDARD_ARRAY.map(v => ({ value: v })),
    statAssign: {},
    statHistory: [],
    chosenSkills: [],
    name: "",
    portraitStyle: "silhouette",
  }));

  const set = (patch) => setState(s => ({ ...s, ...patch }));

  const clade = data.clades.find(c => c.id === state.cladeId);
  const species = data.species.find(s => s.id === state.speciesId);
  const cls = data.classes.find(c => c.id === state.classId);
  const bg = data.backgrounds.find(b => b.id === state.backgroundId);

  // When class changes, reset skill picks
  useE(() => { set({ chosenSkills: [] }); }, [state.classId]);
  // When clade changes, ensure species belongs to it
  useE(() => {
    if (!species || species.clade_id !== state.cladeId) {
      set({ speciesId: data.species.find(s => s.clade_id === state.cladeId)?.id });
    }
  }, [state.cladeId]);

  // Validation per step
  const validate = (i) => {
    if (i === 0) return state.cladeId ? null : "Pick a clade.";
    if (i === 1) return state.speciesId ? null : "Pick a species.";
    if (i === 2) return state.classId ? null : "Pick a calling.";
    if (i === 3) return state.backgroundId ? null : "Pick a background.";
    if (i === 4) return Object.keys(state.statAssign).length === 6 ? null : `Assign all six abilities (${Object.keys(state.statAssign).length}/6).`;
    if (i === 5) return state.chosenSkills.length === (cls?.skills_choose || 0) ? null : `Pick exactly ${cls?.skills_choose} skill${cls?.skills_choose>1?"s":""} (${state.chosenSkills.length}/${cls?.skills_choose}).`;
    if (i === 6) return state.name.trim() ? null : "Enter a name.";
    return null;
  };

  const stepError = validate(step);
  const allValid = STEPS.every((_, i) => !validate(i));

  const StepComp = [
    Steps.StepClade, Steps.StepSpecies, Steps.StepClass, Steps.StepBackground,
    Steps.StepStats, Steps.StepSkills, Steps.StepReview,
  ][step];

  return (
    <div className="app-frame">
      <div className="codex-header">
        <div>
          <h1 className="codex-title">Theriapolis · <em>Codex of Becoming</em></h1>
          <div className="codex-sub" style={{marginTop: 6}}>Folio {romanize(step+1)} of VII — {STEPS[step].name}</div>
        </div>
        <div className="codex-sub" style={{textAlign: "right"}}>
          Seed · 0x4F2A · Phase V · M2
        </div>
      </div>

      <div className="stepper">
        {STEPS.map((s, i) => {
          // A step is locked if any earlier step has unmet requirements.
          // The current step is always reachable; earlier steps are always
          // reachable (so the user can go back and edit).
          const firstIncomplete = STEPS.findIndex((_, j) => validate(j));
          const locked = i > step && firstIncomplete !== -1 && firstIncomplete < i;
          const isComplete = !validate(i) && i !== step;
          return (
            <div
              key={s.id}
              className={"step" + (i === step ? " active" : "") + (isComplete ? " complete" : "") + (locked ? " locked" : "")}
              onClick={() => { if (!locked) setStep(i); }}
              title={locked ? "Complete earlier folios first" : undefined}
            >
              <div className="num">{locked ? "✕" : romanize(i+1)}</div>
              <div className="name">{s.name}</div>
            </div>
          );
        })}
      </div>

      <div className="page">
        <div className="page-main">
          <StepComp state={state} set={set} tweaks={tweaks} goTo={setStep} />
        </div>
        <div className="page-aside">
          <Aside state={state} set={set} tweaks={tweaks} setTweaks={setTweaks} />
        </div>
      </div>

      <div className="nav-bar">
        <button className="btn ghost" disabled={step === 0} onClick={() => setStep(Math.max(0, step-1))}>← Back</button>
        <div style={{display: "flex", alignItems: "center", gap: 24}}>
          <div className={"validation" + (stepError ? "" : " ok")}>
            {stepError || (step < 6 ? "Folio complete" : (allValid ? "Ready to sign" : "Some folios remain"))}
          </div>
          <div className="nav-progress">{step+1} / 7</div>
        </div>
        {step < STEPS.length - 1 ? (
          <button className="btn primary" disabled={!!stepError} onClick={() => setStep(step+1)}>Next ›</button>
        ) : (
          <button className="btn primary" disabled={!allValid} onClick={() => alert(`${state.name} steps into Theriapolis. (Confirmed.)`)}>Confirm & Begin</button>
        )}
      </div>
    </div>
  );
};

const Aside = ({ state, set, tweaks, setTweaks }) => {
  const clade = state.data.clades.find(c => c.id === state.cladeId);
  const species = state.data.species.find(s => s.id === state.speciesId);
  const cls = state.data.classes.find(c => c.id === state.classId);
  const bg = state.data.backgrounds.find(b => b.id === state.backgroundId);

  return (
    <div>
      <div className="codex-sub" style={{marginBottom: 10}}>The Subject</div>

      <Portrait clade={clade} species={species} style="placeholder" name={state.name} />

      <div className="summary-block">
        <h4>Name</h4>
        <div className={"v" + (!state.name ? " empty" : "")}>{state.name || "Unnamed"}</div>
      </div>

      <div className="summary-block">
        <h4>Lineage</h4>
        <div className="v">{species?.name || "—"} <small>{clade?.name} · {SIZE_LABEL[species?.size] || "—"}</small></div>
        {(clade || species) && (
          <div className="trait-chips" style={{marginTop: 8}}>
            {(clade?.traits || []).map(t => (
              <TraitName key={"c-"+t.id} trait={t} suffix="" />
            ))}
            {(species?.traits || []).map(t => (
              <TraitName key={"s-"+t.id} trait={t} suffix="" />
            ))}
            {tweaks.showDetriments && (clade?.detriments || []).map(t => (
              <TraitName key={"cd-"+t.id} trait={t} detriment suffix="" />
            ))}
            {tweaks.showDetriments && (species?.detriments || []).map(t => (
              <TraitName key={"sd-"+t.id} trait={t} detriment suffix="" />
            ))}
          </div>
        )}
      </div>

      <div className="summary-block">
        <h4>Calling & History</h4>
        <div className="v">{cls?.name || "—"} <small>d{cls?.hit_die} · {bg?.name || "no history"}</small></div>
        {cls && (
          <div className="trait-chips" style={{marginTop: 8}}>
            {(cls.level_table?.find(l => l.level === 1)?.features || [])
              .filter(k => !["asi","subclass_select","subclass_feature"].includes(k))
              .map(k => {
                const f = cls.feature_definitions[k];
                if (!f) return null;
                return <TraitName key={"cls-"+k} trait={{ id: cls.id+"_"+k, name: f.name, description: f.description, tag: f.kind }} suffix="" />;
              })}
          </div>
        )}
        {bg && (
          <div className="trait-chips" style={{marginTop: 6}}>
            <TraitName trait={{ id: bg.id+"_feat", name: bg.feature_name, description: bg.feature_description, tag: "feature" }} suffix="" />
          </div>
        )}
      </div>

      <div className="summary-block">
        <h4>Abilities</h4>
        <div className="stat-strip">
          {ABILITIES.map(ab => {
            const base = state.statAssign[ab];
            const cm = clade?.ability_mods[ab] || 0;
            const sm = species?.ability_mods[ab] || 0;
            const f = base != null ? base + cm + sm : null;
            const m = f != null ? abilityMod(f) : null;
            return (
              <div className="cell" key={ab}>
                <div className="ab">{ab}</div>
                <div className="sc">{f ?? "—"}</div>
                <div className={"md" + (m != null && m < 0 ? " neg" : "")}>{m != null ? signed(m) : ""}</div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="summary-block">
        <h4>Skills · {state.chosenSkills.length + (bg?.skill_proficiencies?.length || 0)}</h4>
        <div className="trait-chips aside-skills">
          {(bg?.skill_proficiencies || []).map(s => (
            <SkillChip key={"bg-"+s} id={s} className="from-bg" />
          ))}
          {state.chosenSkills.map(s => (
            <SkillChip key={"cls-"+s} id={s} className="from-cls" />
          ))}
          {(state.chosenSkills.length + (bg?.skill_proficiencies?.length || 0)) === 0 && (
            <span style={{fontFamily: "var(--mono)", fontSize: 10, color: "var(--ink-mute)", letterSpacing: "0.18em"}}>none yet</span>
          )}
        </div>
      </div>
    </div>
  );
};

function romanize(n) {
  return ["I","II","III","IV","V","VI","VII","VIII","IX","X"][n-1] || String(n);
}

window.App = App;
