/* ============================================================
   Character Sheet — live & editable
   Props: { char, patch }
   ============================================================ */
function CharacterSheet({ char, patch }){
  const cls=DND.klass(char.classKey), sp=DND.species(char.speciesKey), bg=DND.resolvedBg(char);
  const final=DND.finalScores(char);
  const pb=DND.profBonus(DND.totalLevel(char));
  const ac=DND.armorClass(char);
  const maxHp=DND.maxHp(char);
  const init=DND.initiative(char);
  const speed=DND.speed(char);
  const attacks=DND.attacks(char);
  const sc=DND.spellStats(char);
  const profs=DND.skillProfs(char);
  const expertise=DND.allExpertise(char);
  const hpCur = char.hpCurrent==null ? maxHp : char.hpCurrent;

  // Collect features
  const classFeats = DND.featuresByLevel(char);
  const speciesTraits = sp?.isCustom ? (char.customSpecies?.traits || []) : (sp ? sp.traits : []);
  const speciesDisplayName = sp?.isCustom ? (char.customSpecies?.name || "Custom Species") : sp?.name;
  const feats = DND.chosenFeats(char);

  // species-granted choice flavor line
  let choiceLine=null;
  if (sp && sp.choice){
    const ck=(char.speciesChoice||{})[sp.choice.id];
    const opt=ck && sp.choice.options.find(o=>o.key===ck);
    if (opt) choiceLine=`${sp.choice.label}: ${opt.name}`;
  }

  const allSpells=[...(char.cantrips||[]),...(char.spells||[])];
  const econ=DND.actionEconomy(char);
  const [tab,setTab]=useState("sheet");
  const [levelingUp,setLevelingUp]=useState(false);
  const story=char.story||{};
  const setStory=(k,v)=>patch({story:{...story,[k]:v}});

  return (
    <div className="sheet-wrap">
      {/* header */}
      <div className="sheet-head">
        <div className="crest">{(char.name||cls?.name||"?").trim()[0]||"?"}</div>
        <div className="id">
          <input className="name-in serif" value={char.name||""} placeholder="Unnamed Adventurer"
            onChange={e=>patch({name:e.target.value})} />
          <div className="subline">
            <span className="pill"><b>{sp ? (speciesDisplayName || "—") : "—"}</b></span>
            {(()=>{
              const mcs=char.multiclasses||[];
              if(mcs.length===0) return (<React.Fragment>
                <span className="pill"><b>{cls?cls.name:"—"}</b></span>
                {char.subclass&&cls&&<span className="pill"><b>{(DND.subclass(cls.key,char.subclass)||{}).name}</b></span>}
              </React.Fragment>);
              return (<React.Fragment>
                <span className="pill"><b>{cls?`${cls.name} ${char.level}`:"—"}</b></span>
                {char.subclass&&cls&&<span className="pill"><b>{(DND.subclass(cls.key,char.subclass)||{}).name}</b></span>}
                {mcs.map(mc=>{const mcCls=DND.klass(mc.classKey);return mcCls?<span key={mc.classKey} className="pill"><b>{mcCls.name} {mc.level}</b></span>:null;})}
              </React.Fragment>);
            })()}
            <span className="pill">{bg?bg.name:"—"}</span>
            <span className="pill">{char.alignment}</span>
            {choiceLine && <span className="pill">{choiceLine}</span>}
          </div>
        </div>
        <div className="lvl">
          <div className="lvl-stepper sheet">
            <button onClick={()=>patch({level:Math.max(1,(char.level||1)-1), subclass:(char.level||1)-1<DND.SUBCLASS_LEVEL?null:char.subclass})} disabled={(char.level||1)<=1}>−</button>
            <div className="n mono">{DND.totalLevel(char)}</div>
            <button onClick={()=>setLevelingUp(true)} disabled={DND.totalLevel(char)>=20}>+</button>
          </div>
          <div className="l">Level</div>
        </div>
      </div>

      {/* tabs */}
      <div className="sheet-tabs">
        <button className={tab==="sheet"?"on":""} onClick={()=>setTab("sheet")}><Ic.sheet/> Character Sheet</button>
        <button className={tab==="story"?"on":""} onClick={()=>setTab("story")}><Ic.book/> Background &amp; Story</button>
      </div>

      <div className={"print-sheet"+(tab==="story"?" screen-hide":"")}>
      {(<React.Fragment>
      {/* core strip */}
      <div className="corestrip">
        <div className="core accent"><div className="cl">Prof. Bonus</div><div className="cv mono">{DND.fmt(pb)}</div></div>
        <div className="core"><div className="cl">Armor Class</div><div className="cv mono">{ac.value}</div><div className="cs">{ac.label}</div></div>
        <div className="core"><div className="cl">Initiative</div><div className="cv mono">{DND.fmt(init)}</div></div>
        <div className="core"><div className="cl">Speed</div><div className="cv mono">{speed}</div><div className="cs">feet</div></div>
        <div className="core hp">
          <div className="cl">Hit Points</div>
          <div className="hpline">
            <input type="number" value={hpCur} onChange={e=>patch({hpCurrent:Math.min(maxHp, Math.max(-99, Number(e.target.value)||0))})} />
            <span className="mx">/ {maxHp}</span>
          </div>
          <div className="temp">Temp <input type="number" value={char.tempHp||0} onChange={e=>patch({tempHp:Math.max(0,Number(e.target.value)||0)})} /></div>
        </div>
        <div className="core"><div className="cl">Hit Dice</div><div className="cv mono">{char.level}d{cls?cls.hd:8}</div><div className="cs">per long rest</div></div>
      </div>

      {/* actions at a glance */}
      <div className="panel actions-card">
        <div className="panel-h">Actions at a Glance<span className="ln"></span><span className="ac-hint">what you can do on your turn</span></div>
        <div className="act-grid">
          <div className="act-col action">
            <h4><span className="ac-dot"></span>Action</h4>
            <ul>{econ.action.map((a,i)=><li key={i}>{a}</li>)}</ul>
          </div>
          <div className="act-col bonus">
            <h4><span className="ac-dot"></span>Bonus Action</h4>
            <ul>{econ.bonus.length?econ.bonus.map((a,i)=><li key={i}>{a}</li>):<li className="none">No notable bonus actions</li>}</ul>
          </div>
          <div className="act-col reaction">
            <h4><span className="ac-dot"></span>Reaction</h4>
            <ul>{econ.reaction.map((a,i)=><li key={i}>{a}</li>)}</ul>
          </div>
        </div>
      </div>

      {/* three columns */}
      <div className="sheet-grid">
        {/* LEFT: abilities + saves */}
        <div>
          <div className="panel">
            <div className="panel-h">Ability Scores<span className="ln"></span></div>
            {DND.ABILITIES.map(a=>{
              const k=a.key, m=DND.mod(final[k]);
              const saveProf=DND.saveProficient(char,k);
              const saveB=DND.saveBonus(char,k);
              return (
                <div className="abil-row" key={k}>
                  <div className="box" style={{borderColor:a.accent+"44"}}>
                    <div className="m mono" style={{color:a.accent}}>{DND.fmt(m)}</div>
                    <div className="s mono">{final[k]}</div>
                  </div>
                  <div className="meta">
                    <div className="nm">{a.name}</div>
                    <div className="sv"><span className={"d"+(saveProf?" on":"")}></span> Saving Throw <span className="b mono">{DND.fmt(saveB)}</span></div>
                  </div>
                </div>
              );
            })}
          </div>

          <div className="panel">
            <div className="panel-h">Species Traits<span className="ln"></span></div>
            {speciesTraits.map((f,i)=>(
              <div className="feat" key={i}>
                <div className="fn"><span className="src sp">{speciesDisplayName}</span>{f.name}</div>
                <div className="ft">{f.text}</div>
              </div>
            ))}
          </div>

          <div className="panel">
            <div className="panel-h">Equipment &amp; Proficiencies<span className="ln"></span></div>
            <div className="gear-line"><span className="gt">Armor</span>{(char.gear.armor==="(None)"?"Unarmored":char.gear.armor)}{char.gear.shield?", Shield":""}</div>
            <div className="gear-line"><span className="gt">Weapons</span>{(char.gear.weapons||[]).join(", ")||"—"}</div>
            {bg && <div className="gear-line"><span className="gt">Tool</span>{(()=>{
              const t = [DND.TOOLS[bg.tool]];
              (char.bonusTools||[]).forEach(k=>t.push(DND.TOOLS[k]));
              if (bg.feat==="Crafter") t.push(...(char.crafterTools||[]));
              if (bg.feat==="Musician") t.push(...(char.musicianInstruments||[]));
              if (char.speciesKey==="custom" && char.customSpecies) {
                const sk=new Set(DND.SKILLS.map(s=>s.key));
                (char.customSpecies.proficiencies||[]).filter(k=>!sk.has(k)).forEach(k=>t.push(DND.TOOLS[k]||k));
              }
              return t.filter(Boolean).join(", ")||"—";
            })()}</div>}
            {cls && <div className="gear-line"><span className="gt">Armor Training</span>{cls.armor}</div>}
            {cls && <div className="gear-line"><span className="gt">Weapon Training</span>{cls.weapons}</div>}
            {(() => {
              let langs = [];
              if (char.speciesLangs && char.speciesLangs.length > 0) {
                langs = [...char.speciesLangs];
              } else {
                // backward-compat fallback for saved characters
                langs = ["Common"];
                if (sp && sp.lang) langs.push(sp.lang);
                else if (sp && sp.isCustom && char.customSpecies?.lang) langs.push(char.customSpecies.lang);
                else if (sp && sp.key==="human" && char.humanLang) langs.push(char.humanLang);
              }
              if (char.bgLang) langs.push(char.bgLang);
              const unique = [...new Set(langs)];
              return <div className="gear-line"><span className="gt">Languages</span>{unique.join(", ")||"—"}</div>;
            })()}
            {char.classKey==="bard" && (char.classInstruments||[]).length>0 && (
              <div className="gear-line"><span className="gt">Instruments</span>{(char.classInstruments||[]).join(", ")}</div>
            )}
            {char.classKey==="monk" && char.monkTool && (
              <div className="gear-line"><span className="gt">Tool/Instrument</span>{char.monkTool}</div>
            )}
            {char.clericOrder && (
              <div className="gear-line"><span className="gt">Divine Order</span>{char.clericOrder==="protector"?"Protector (Martial weapons, Heavy armor)":"Thaumaturge (extra cantrip, Arcana/Religion)"}</div>
            )}
            {char.druidOrder && (
              <div className="gear-line"><span className="gt">Primal Order</span>{char.druidOrder==="magician"?"Magician (extra cantrip, Arcana/Nature)":"Warden (Martial weapons)"}</div>
            )}
            {(char.warlockInvocations||[]).length>0 && (
              <div className="gear-line"><span className="gt">Invocations</span>{(char.warlockInvocations||[]).join(", ")}</div>
            )}
            {char.wildHeartAspect && (()=>{
              const a=(DND.WILD_HEART_ASPECTS||[]).find(x=>x.key===char.wildHeartAspect);
              return a ? <div className="gear-line"><span className="gt">Rage Aspect</span>{a.name}</div> : null;
            })()}
            {char.hunterPrey && (()=>{
              const o=(DND.HUNTER_PREY_OPTIONS||[]).find(x=>x.key===char.hunterPrey);
              return o ? <div className="gear-line"><span className="gt">Hunter's Prey</span>{o.name}</div> : null;
            })()}
            {char.landCircleTerrain && (()=>{
              const t=(DND.LAND_CIRCLE_TERRAINS||[]).find(x=>x.key===char.landCircleTerrain);
              return t ? <div className="gear-line"><span className="gt">Land Terrain</span>{t.name}</div> : null;
            })()}
            {char.draconicAncestry && (()=>{
              const a=(DND.DRACONIC_ANCESTORS||[]).find(x=>x.key===char.draconicAncestry);
              return a ? <div className="gear-line"><span className="gt">Draconic Ancestor</span>{a.name} ({a.damage})</div> : null;
            })()}
            {char.zealotFuryType && (
              <div className="gear-line"><span className="gt">Divine Fury</span>{char.zealotFuryType==="radiant"?"Radiant":"Necrotic"}</div>
            )}
            {bg && <div className="gear-line"><span className="gt">Starting Gear</span>{bg.equipment}</div>}
          </div>
        </div>

        {/* MIDDLE: skills */}
        <div>
          <div className="panel">
            <div className="panel-h">Skills<span className="ln"></span></div>
            {DND.SKILLS.map(s=>{
              const prof=profs.has(s.key), exp=expertise.has(s.key);
              const b=DND.skillBonus(char,s.key);
              const manualProf=(char.bonusSkills||[]).includes(s.key);
              const manualExp=(char.expertise||[]).includes(s.key);
              const toggleProf=()=>{
                if(!prof) patch({bonusSkills:[...(char.bonusSkills||[]),s.key]});
                else if(manualProf) patch({bonusSkills:(char.bonusSkills||[]).filter(k=>k!==s.key),expertise:(char.expertise||[]).filter(k=>k!==s.key)});
              };
              const toggleExp=()=>{
                if(!prof) return;
                if(exp&&!manualExp) return; // fixed expertise (from feat), can't remove here
                const ex=char.expertise||[];
                patch({expertise:manualExp?ex.filter(k=>k!==s.key):[...ex,s.key]});
              };
              return (
                <div className={"skill-row"+(prof?" prof":"")} key={s.key}>
                  <button className={"d"+(exp?" on exp":prof?" on":"")}
                    onClick={toggleProf}
                    style={{cursor:(!prof||manualProf)?"pointer":"default"}}>
                    {exp?<Ic.sparkle style={{fontSize:9}}/>:prof?<Ic.check style={{fontSize:10}}/>:null}
                  </button>
                  <span className="ab">{s.ability}</span>
                  <span className="nm">{s.name}</span>
                  {prof&&<button onClick={toggleExp}
                    title={exp?(manualExp?"Remove expertise":"Expertise from feat"):"Add expertise"}
                    style={{width:14,height:14,borderRadius:"50%",border:"1.5px solid",
                      borderColor:exp?"var(--accent)":"var(--line-2)",
                      background:exp?"var(--accent)":"none",
                      cursor:(!exp||manualExp)?"pointer":"default",
                      padding:0,flexShrink:0,display:"grid",placeItems:"center"}}>
                    {exp&&<Ic.sparkle style={{fontSize:7,color:"#fff"}}/>}
                  </button>}
                  <span className="bn mono">{DND.fmt(b)}</span>
                </div>
              );
            })}
            <div className="passive"><Ic.info/> Passive Perception <b className="mono">{DND.passivePerception(char)}</b></div>
          </div>

          <div className="panel">
            <div className="panel-h">Feats<span className="ln"></span></div>
            {feats.length>0 ? feats.map((f,i)=>(
              <div className="feat" key={i}>
                <div className="fn"><span className="src bg">{f.src}</span>{f.name}</div>
                <div className="ft">{f.text}</div>
              </div>
            )) : <div className="hint">No feats yet — your background grants an Origin feat, and ASI milestones let you take more.</div>}
          </div>
        </div>

        {/* RIGHT: combat, features, spells, gear, notes */}
        <div>
          <div className="panel">
            <div className="panel-h">Attacks<span className="ln"></span></div>
            {attacks.length>0 ? (
              <table className="atk">
                <thead><tr><th>Weapon</th><th>Range</th><th>Atk</th><th>Damage</th></tr></thead>
                <tbody>
                  {attacks.map((a,i)=>(
                    <tr key={i}>
                      <td className="nm">{a.name}{a.mastery&&<div className="mast">{a.mastery}</div>}</td>
                      <td>{a.range}</td>
                      <td className="mono">{a.atk}</td>
                      <td className="mono">{a.dmg}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            ) : <div className="hint">No weapons equipped — add some in the Equipment step.</div>}
          </div>

          {sc && (
            <div className="panel">
              <div className="panel-h">Spellcasting<span className="ln"></span></div>
              <div className="spellstat">
                <div className="ss"><div className="l">Ability</div><div className="v">{abilShort(sc.ability)}</div></div>
                <div className="ss"><div className="l">Save DC</div><div className="v">{sc.dc}</div></div>
                <div className="ss"><div className="l">Atk Bonus</div><div className="v">{sc.atk}</div></div>
                <div className="ss"><div className="l">Cantrips</div><div className="v">{DND.cantripsKnownFor(char)}</div></div>
              </div>
              {(()=>{ const ss=DND.spellSlots(char); if(!ss) return null;
                return (<React.Fragment>
                  {ss.pact ? (
                    <div className="slotrow"><span className="slk">Pact Magic Slots</span><span className="slv mono">{ss.n} × Level {ss.level}</span></div>
                  ) : ss.slots && ss.slots.length>0 ? (
                    <div className="slots">
                      {ss.slots.map((n,i)=>(<div className="slot" key={i}><div className="sn mono">{n}</div><div className="sl">L{i+1}</div></div>))}
                    </div>
                  ) : null}
                  {ss.pactSlots && <div className="slotrow" style={{marginTop:6}}><span className="slk">Pact Magic</span><span className="slv mono">{ss.pactSlots.n} × Level {ss.pactSlots.l}</span></div>}
                </React.Fragment>);
              })()}
              {allSpells.length>0 ? allSpells.map(name=>{
                const s=DND.SPELLBOOK[name]||{};
                return (
                  <div className="spell-item" key={name}>
                    <span className="lv mono">{s.lvl===0?"C":s.lvl}</span>
                    <div><div className="si-name">{name} <span style={{color:"var(--faint)",fontWeight:400,fontSize:12}}>· {s.school}</span></div><div className="si-text">{s.text}</div></div>
                  </div>
                );
              }) : <div className="hint">No spells chosen yet.</div>}
            </div>
          )}

          <div className="panel">
            <div className="panel-h">{cls?cls.name:"Class"} Features<span className="ln"></span></div>
            {classFeats.map((f,i)=>(
              <div className="feat" key={i}>
                <div className="fn"><span className={"src "+f.cat}>{f.cat==="asi"?"ASI":f.cat==="sub"?"Subclass":"Class"}</span>{f.name}<span className="lvtag" style={{marginLeft:"auto"}}>Lv {f.level}</span></div>
                <div className="ft">{f.text}</div>
              </div>
            ))}
          </div>

          {(char.battleMasterManeuvers||[]).length>0 && (()=>{
            const lvl = char.level||1;
            const die = lvl>=10?"d10":"d8";
            const supCount = DND.battleMasterSupDiceCount ? DND.battleMasterSupDiceCount(lvl) : 4;
            return (
            <div className="panel">
              <div className="panel-h">Battle Master Maneuvers<span className="ln"></span>
                <span className="ac-hint">{(char.battleMasterManeuvers||[]).length} known · {supCount}×{die} Superiority Dice</span>
              </div>
              {(char.battleMasterManeuvers||[]).map(name=>{
                const m=(DND.BATTLE_MASTER_MANEUVERS||[]).find(x=>x.name===name);
                return m ? (
                  <div className="feat" key={name}>
                    <div className="fn"><span className="src sub">Maneuver</span>{m.name}</div>
                    <div className="ft">{m.text}</div>
                  </div>
                ) : null;
              })}
            </div>
            );
          })()}
        </div>
      </div>
      </React.Fragment>)}
      </div>
      <div className={"print-story"+(tab==="sheet"?" screen-hide":"")}>
        <StoryTab story={story} setStory={setStory} char={char} />
      </div>

      {levelingUp && <LevelUpWizard char={char} patch={patch} onClose={()=>setLevelingUp(false)} />}
    </div>
  );
}

/* ---- Background & Story tab ---- */
function StoryField({ story, setStory, k, label, prompt, rows }){
  return (
    <div className="panel story-card">
      <div className="panel-h">{label}<span className="ln"></span></div>
      {prompt && <div className="story-prompt">{prompt}</div>}
      <textarea rows={rows||3} value={story[k]||""} placeholder="…" onChange={e=>setStory(k, e.target.value)} />
    </div>
  );
}
function ApField({ story, setStory, k, label }){
  return (
    <div className="ap-field">
      <label>{label}</label>
      <input type="text" value={story[k]||""} placeholder="—" onChange={e=>setStory(k, e.target.value)} />
    </div>
  );
}
function StoryTab({ story, setStory, char }){
  const bg=DND.resolvedBg(char);
  const F=(k,label,prompt,rows)=><StoryField story={story} setStory={setStory} k={k} label={label} prompt={prompt} rows={rows} />;
  const A=(k,label)=><ApField story={story} setStory={setStory} k={k} label={label} />;
  return (
    <div className="story-wrap">
      <div className="callout" style={{marginBottom:"var(--gap-card)"}}>
        <span className="ico"><Ic.book/></span>
        <div>This is your character's inner life — who they are beyond the numbers. {bg&&<>Your <b>{bg.name}</b> background is a great seed for the story below.</>} Everything here saves automatically.</div>
      </div>

      <div className="panel story-card">
        <div className="panel-h">Appearance<span className="ln"></span></div>
        <div className="appearance-grid">
          {A("age","Age")}{A("height","Height")}{A("weight","Weight")}
          {A("eyes","Eyes")}{A("hair","Hair")}{A("skin","Skin")}
          {A("gender","Gender / Pronouns")}{A("faith","Faith / Deity")}{A("size","Size")}
        </div>
      </div>

      {F("backstory","Backstory","Where did your hero come from? What set them on the road to adventure?",7)}

      <div className="story-grid">
        {F("personality","Personality Traits","Two short phrases that capture how you act.")}
        {F("ideals","Ideals","The principles and beliefs that drive you.")}
        {F("bonds","Bonds","People, places, or things you hold dear.")}
        {F("flaws","Flaws","A vice, fear, or weakness others could exploit.")}
      </div>

      <div className="story-grid">
        {F("allies","Allies & Organizations","Companions, factions, contacts, and rivals.",4)}
        {F("notes","Notes & Journal","Session notes, goals, secrets, anything else.",4)}
      </div>
    </div>
  );
}

Object.assign(window, { CharacterSheet, StoryTab });
