/* ===================================================================
   data.jsx — sample game state for the Embers tabletop prototype
   =================================================================== */

// ---- Party members (players present in the room) ----
const PARTY = [
  { id: 'dm',    name: 'Marlow',  role: 'Dungeon Master', color: '#7d2330', initial: 'M', sprite: '🧙', isDM: true,  ping: 24 },
  { id: 'p1',    name: 'Brakka',  char: 'Brakka Stonefist', cls: 'Barbarian', lvl: 5, color: '#9a6f28', initial: 'B', sprite: '🪓', ping: 41,
    hp: 44, hpMax: 52, ac: 16, init: 18, sheet: { STR:18, DEX:12, CON:16, INT:8,  WIS:11, CHA:10, speed:40 } },
  { id: 'p2',    name: 'Sora',    char: 'Sora Nightbreeze', cls: 'Ranger',    lvl: 5, color: '#3f5d42', initial: 'S', sprite: '🏹', ping: 33,
    hp: 38, hpMax: 38, ac: 15, init: 22, sheet: { STR:12, DEX:18, CON:13, INT:11, WIS:16, CHA:10, speed:35 } },
  { id: 'p3',    name: 'Elowen',  char: 'Elowen Vale',      cls: 'Cleric',    lvl: 5, color: '#5b4b8a', initial: 'E', sprite: '✨', ping: 28,
    hp: 31, hpMax: 40, ac: 18, init: 9,  sheet: { STR:10, DEX:12, CON:14, INT:13, WIS:18, CHA:12, speed:30 } },
  { id: 'p4',    name: 'Pip',     char: 'Pip Underbough',   cls: 'Rogue',     lvl: 5, color: '#a23644', initial: 'P', sprite: '🗡️', ping: 55,
    hp: 27, hpMax: 33, ac: 15, init: 25, sheet: { STR:9,  DEX:18, CON:12, INT:14, WIS:11, CHA:16, speed:30 } },
];

// ---- Monsters / hidden tokens the DM has staged ----
const MONSTERS = [
  { id: 'm1', name: 'Goblin Sentry',  sprite: '👺', color: '#3f5d42', hp: 7,  hpMax: 7,  ac: 15, hidden: true,  reveal: 'proximity' },
  { id: 'm2', name: 'Goblin Sentry',  sprite: '👺', color: '#3f5d42', hp: 7,  hpMax: 7,  ac: 15, hidden: true,  reveal: 'proximity' },
  { id: 'm3', name: 'Cave Bear',      sprite: '🐻', color: '#5a3a23', hp: 34, hpMax: 34, ac: 11, hidden: true,  reveal: 'manual' },
  { id: 'm4', name: 'Spike Trap',     sprite: '🜏', color: '#7d2330', hp: 1,  hpMax: 1,  ac: 10, hidden: true,  reveal: 'proximity', trap: true },
  { id: 'm5', name: 'Hobgoblin Boss', sprite: '💀', color: '#2a1a10', hp: 58, hpMax: 58, ac: 18, hidden: true,  reveal: 'scripted', note: 'Round 3' },
  { id: 'm6', name: 'Selverain Thorne', portrait: '/tabletop/portraits/selverain-thorne.png', sprite: '🔥', color: '#c2568a',
    hp: 120, hpMax: 120, ac: 17, hidden: true, reveal: 'manual', boss: true, scope: 'bloom',
    notes: [
      'Master of the Bloom Tower, bound to the Bloom Kraken',
      'Reveal at the Observatory Roof — casts pollen storms each round',
      'Flees toward the lunar stone rings below 40 HP',
    ] },
];

// ---- Tokens placed on the board (id ties to PARTY/MONSTERS) ----
// grid coords on a 24x16 cell map
const START_TOKENS = [
  { ref: 'p1', x: 3,  y: 11 },
  { ref: 'p2', x: 4,  y: 12 },
  { ref: 'p3', x: 3,  y: 13 },
  { ref: 'p4', x: 5,  y: 11 },
  { ref: 'm1', x: 12, y: 6 },
  { ref: 'm2', x: 14, y: 7 },
  { ref: 'm4', x: 9,  y: 9 },
  { ref: 'm3', x: 18, y: 4 },
  { ref: 'm5', x: 20, y: 3 },
  { ref: 'm6', x: 11, y: 8 },
];

// ---- Maps available in the campaign ----
const MAPS = [
  { id: 'map1', name: 'Emberhold Caverns', sub: 'Act II · The Deep Roads', cells: { w: 24, h: 16 }, active: true },
  { id: 'map2', name: 'The Drowned Chapel', sub: 'Act II · Side Delve',     cells: { w: 24, h: 16 }, active: false },
  { id: 'map3', name: 'Sablewood Crossing', sub: 'Act I · Overland',        cells: { w: 24, h: 16 }, active: false },
  { id: 'map4', name: "Tavern: The Gilded Stag", sub: 'Social · Safe Haven', cells: { w: 24, h: 16 }, active: false },
  { id: 'map5', name: 'Mistvale, Town of Echoes', sub: 'Town · Overland Hub', cells: { w: 24, h: 24 }, active: false,
    url: '/maps-img/mistvale.png' },
  { id: 'bloom-overview', name: 'The Bloom Tower', sub: 'Act III · Observatory & Grounds', cells: { w: 32, h: 18 }, active: false,
    url: '/maps-img/bloom-tower-overview.png', image: true,
    pois: [
      { n: 1, name: 'Observatory Roof',   x: 11.2, y: 2.5,  text: 'Broken telescope, moon dial, and star charts scattered across the cracked dome.' },
      { n: 2, name: 'Upper Laboratories', x: 12.7, y: 4.9,  text: 'Alchemical stations, glass tubes of spores, and contaminated experiments.' },
      { n: 3, name: 'Spiral Stairwell',   x: 11.4, y: 6.85, text: 'A winding descent through flooded levels and hidden chambers.' },
      { n: 4, name: 'Main Entrance',      x: 12.2, y: 8.8,  text: 'Locked by lunar rings; the entrance is often hidden by magical illusions.' },
      { n: 5, name: 'Lunar Stone Rings',  x: 18.0, y: 7.4,  text: "Rotate to align the moon phases and unlock the tower's ancient wards." },
      { n: 6, name: 'Flooded Gardens',    x: 23.8, y: 7.1,  text: 'Overgrown magical flora, shattered greenhouses, and glowing spores.' },
    ] },
  { id: 'bloom-obs',   name: 'Observatory Roof',   sub: 'Bloom Tower · Top Level',   cells: { w: 22, h: 22 }, active: false, url: '/maps-img/bloom-observatory.png', image: true },
  { id: 'bloom-lab',   name: 'Upper Laboratories', sub: 'Bloom Tower · Mid Level',   cells: { w: 22, h: 22 }, active: false, url: '/maps-img/bloom-upper-lab.png',   image: true },
  { id: 'bloom-stair', name: 'Spiral Stairwell',   sub: 'Bloom Tower · Lower Level', cells: { w: 22, h: 22 }, active: false, url: '/maps-img/bloom-stairwell.png',   image: true },
  // 1080x833 source (~1.3:1) -> 26x20 grid keeps cells near-square.
  { id: 'weeping-lab', name: 'The Weeping Labyrinth', sub: 'Nephalot · The Sunken Maze', cells: { w: 26, h: 20 }, active: false, url: '/maps-img/weeping-labyrinth-nephalot.png', image: true },
];

// ---- Elements / Power ----
// A DM palette of elemental "spells" that act on a target.
//   kind: 'damage' | 'heal' | 'control' | 'buff'
//   dice: rolled for damage/heal · status: badge applied to the target
//   verb: third-person, acting ON the target (for the chat narration)
const ELEMENTS = [
  // — Basic —
  { id:'el_power',    name:'Power',     tier:'basic', glyph:'✊', color:'#b5462f', kind:'damage', dice:'2d6',  verb:'crushes' },
  { id:'el_dark',     name:'Darkness',  tier:'basic', glyph:'🌑', color:'#2c2733', kind:'control', status:'blinded',    verb:'shrouds' },
  { id:'el_fire',     name:'Fire',      tier:'basic', glyph:'🔥', color:'#d2691e', kind:'damage', dice:'2d6',  status:'burning', verb:'sears' },
  { id:'el_wind',     name:'Wind',      tier:'basic', glyph:'🌬️', color:'#b9c06a', kind:'control', status:'staggered',  verb:'buffets' },
  { id:'el_fear',     name:'Fear',      tier:'basic', glyph:'😱', color:'#c06a2f', kind:'control', status:'frightened', verb:'terrifies' },
  { id:'el_thunder',  name:'Thunder',   tier:'basic', glyph:'⚡', color:'#3f6f9e', kind:'damage', dice:'2d8',  verb:'shocks' },
  { id:'el_ice',      name:'Ice',       tier:'basic', glyph:'❄️', color:'#6fc2e0', kind:'control', status:'frozen',     verb:'freezes' },
  // — Complex —
  { id:'el_weaponm',  name:'Weapon Mastery', tier:'complex', glyph:'⚔️', color:'#c2a14a', kind:'buff', status:'+2 to hit',   verb:'empowers' },
  { id:'el_light',    name:'Light',     tier:'complex', glyph:'🌟', color:'#f2d98a', kind:'heal',   dice:'2d8',  verb:'mends' },
  { id:'el_poison',   name:'Poison',    tier:'complex', glyph:'☠️', color:'#6fae3f', kind:'damage', dice:'1d8',  status:'poisoned', verb:'poisons' },
  { id:'el_shadow',   name:'Shadow',    tier:'complex', glyph:'🌒', color:'#4a3d6b', kind:'control', status:'blinded',  verb:'engulfs' },
  { id:'el_meta',     name:'Metamorph', tier:'complex', glyph:'🦋', color:'#2f8e6a', kind:'control', status:'transformed', verb:'warps' },
  { id:'el_illusion', name:'Illusion',  tier:'complex', glyph:'👁️', color:'#4aa0c0', kind:'control', status:'confused', verb:'deceives' },
  { id:'el_gravity',  name:'Gravity',   tier:'complex', glyph:'🕳️', color:'#3f6fae', kind:'damage', dice:'2d6',  status:'restrained', verb:'crushes' },
  { id:'el_phoenix',  name:'Phoenix',   tier:'complex', glyph:'🦅', color:'#2f9e6a', kind:'heal',   dice:'3d8',  verb:'revives' },
  { id:'el_blood',    name:'Bloodshed', tier:'complex', glyph:'🩸', color:'#9e2f2f', kind:'damage', dice:'2d10', verb:'rends' },
  { id:'el_mind',     name:'Mind',      tier:'complex', glyph:'🧠', color:'#9a9aa2', kind:'control', status:'dominated', verb:'dominates' },
  { id:'el_beast',    name:'Beast',     tier:'complex', glyph:'🐾', color:'#3f7d4a', kind:'damage', dice:'2d8',  verb:'mauls' },
  { id:'el_weaponry', name:'Weaponry',  tier:'complex', glyph:'🗡️', color:'#b07a3a', kind:'buff', status:'+1d6 weapon', verb:'arms' },
  { id:'el_solid',    name:'Solid',     tier:'complex', glyph:'🛡️', color:'#8a8a90', kind:'buff', status:'+3 AC',       verb:'fortifies' },
  { id:'el_hell',     name:'Hell',      tier:'complex', glyph:'👹', color:'#7a2f8a', kind:'damage', dice:'2d10', status:'burning', verb:'scorches' },
  { id:'el_magma',    name:'Magma',     tier:'complex', glyph:'🌋', color:'#d2691e', kind:'damage', dice:'3d6',  verb:'incinerates' },
  { id:'el_curse',    name:'Curse',     tier:'complex', glyph:'💀', color:'#7a4f8a', kind:'control', status:'cursed', verb:'curses' },
  { id:'el_sound',    name:'Sound',     tier:'complex', glyph:'🔊', color:'#3f8a8a', kind:'damage', dice:'1d8',  status:'deafened', verb:'deafens' },
  { id:'el_nature',   name:'Nature',    tier:'complex', glyph:'🌿', color:'#3f9e5a', kind:'heal',   dice:'2d6',  verb:'restores' },
  { id:'el_prism',    name:'Prism',     tier:'complex', glyph:'🔮', color:'#b04fae', kind:'buff', status:'resist all', verb:'refracts' },
  // — Legendary —
  { id:'el_celestial',name:'Celestial', tier:'legendary', glyph:'🌠', color:'#cdd7e8', kind:'heal',   dice:'4d8',  verb:'blesses' },
  { id:'el_divine',   name:'Divine',    tier:'legendary', glyph:'✨', color:'#e8d27a', kind:'heal',   dice:'3d10', verb:'sanctifies' },
  { id:'el_void',     name:'Void',      tier:'legendary', glyph:'⚫', color:'#2a2438', kind:'damage', dice:'4d6',  status:'banished', verb:'annihilates' },
  { id:'el_ash',      name:'Ash',       tier:'legendary', glyph:'🌫️', color:'#8a8076', kind:'damage', dice:'2d8',  status:'withered', verb:'withers' },
  { id:'el_mirror',   name:'Mirror',    tier:'legendary', glyph:'🪞', color:'#9ab4cd', kind:'buff', status:'reflecting', verb:'reflects' },
  { id:'el_arcane',   name:'Arcane',    tier:'legendary', glyph:'🔱', color:'#3f7d6f', kind:'damage', dice:'3d8',  verb:'unravels' },
  { id:'el_frostfire',name:'Frostfire', tier:'legendary', glyph:'☄️', color:'#9a6fd0', kind:'damage', dice:'3d8',  status:'frozen', verb:'immolates' },
];

// ---- Dice sets ----
const DICE_TYPES = [
  { d: 4,  color: '#3f5d42' },
  { d: 6,  color: '#5a3a23' },
  { d: 8,  color: '#5b4b8a' },
  { d: 10, color: '#9a6f28' },
  { d: 12, color: '#7d2330' },
  { d: 20, color: '#c1933f' },
  { d: 100,color: '#2a2017' },
];

const SAVED_ROLLS = [
  { id: 's1', who: 'p1', label: 'Greataxe',     formula: '1d12+4', tag: 'attack' },
  { id: 's2', who: 'p2', label: 'Longbow',      formula: '1d20+7', tag: 'attack' },
  { id: 's3', who: 'p3', label: 'Cure Wounds',  formula: '2d8+4',  tag: 'heal' },
  { id: 's4', who: 'p4', label: 'Sneak Attack', formula: '3d6',    tag: 'damage' },
];

// ---- Chat & roll log ----
const CHAT = [
  { id: 1, who: 'dm', kind: 'narrate', text: 'Cold air drifts up from the dark of the Deep Roads. Somewhere ahead, a chittering echo.' },
  { id: 2, who: 'p4', kind: 'say',     text: 'I creep ahead and check the floor for tripwires.' },
  { id: 3, who: 'p4', kind: 'roll',    text: 'Perception', formula: '1d20+5', total: 19, dice: [14] },
  { id: 4, who: 'dm', kind: 'whisper', text: 'You spot a faint glint of pressure plate two squares north. (Only you can see this.)' },
  { id: 5, who: 'p1', kind: 'say',     text: 'Stay back. I do not like this place.' },
  { id: 6, who: 'p2', kind: 'roll',    text: 'Stealth', formula: '1d20+6', total: 23, dice: [17] },
];

// ---- Settings poll (player-suggested house rules) ----
const POLLS = [
  { id: 'poll1', status: 'open', by: 'p1',
    title: 'Use flanking advantage rules?',
    desc: 'Two allies on opposite sides of a foe both gain advantage on melee attacks.',
    options: [
      { id: 'a', label: 'Yes — flanking grants advantage', votes: ['p1', 'p2'] },
      { id: 'b', label: 'No — by-the-book only',          votes: ['p3'] },
      { id: 'c', label: 'Flanking grants +2, not advantage', votes: ['p4'] },
    ] },
  { id: 'poll2', status: 'closed', by: 'p3',
    title: 'Potions as a bonus action?',
    desc: 'Drinking a potion costs a bonus action instead of an action.',
    result: 'Passed',
    options: [
      { id: 'a', label: 'Bonus action', votes: ['p1','p2','p3','p4'] },
      { id: 'b', label: 'Full action',  votes: [] },
    ] },
];

const SUGGESTIONS_QUEUE = [
  { id: 'sg1', by: 'p4', text: 'Critical hits = max damage + roll', up: 2 },
  { id: 'sg2', by: 'p2', text: 'Inspiration refreshes each session', up: 3 },
];

// ---- Illustrated pregen heroes (portrait art, quick-pick at the table) ----
const PREGEN_HEROES = [
  { id: 'h1', name: 'Aldric', char: 'Sir Aldric Vayne', cls: 'Paladin', race: 'Human', lvl: 5,
    color: '#d0a93f', initial: 'A', sprite: '', portrait: '/tabletop/portraits/paladin.png', ping: 30,
    hp: 44, hpMax: 44, ac: 18, init: 0,  sheet: { STR:16, DEX:10, CON:14, INT:9,  WIS:12, CHA:13, speed:30 } },
  { id: 'h2', name: 'Vesryn', char: 'Vesryn the Bound', cls: 'Warlock', race: 'Tiefling', lvl: 5,
    color: '#5b4b8a', initial: 'V', sprite: '', portrait: '/tabletop/portraits/warlock.png', ping: 30,
    hp: 38, hpMax: 38, ac: 13, init: 2,  sheet: { STR:9,  DEX:14, CON:14, INT:11, WIS:10, CHA:16, speed:30 } },
  { id: 'h3', name: 'Tibbin', char: 'Tibbin Greenbarrow', cls: 'Ranger', race: 'Halfling', lvl: 5,
    color: '#3f5d42', initial: 'T', sprite: '', portrait: '/tabletop/portraits/ranger.png', ping: 30,
    hp: 44, hpMax: 44, ac: 15, init: 3,  sheet: { STR:12, DEX:16, CON:14, INT:10, WIS:13, CHA:8,  speed:25 } },
  { id: 'h4', name: 'Cassio', char: 'Cassio Lir', cls: 'Bard', race: 'Half-Elf', lvl: 5,
    color: '#c25664', initial: 'C', sprite: '', portrait: '/tabletop/portraits/bard.png', ping: 30,
    hp: 33, hpMax: 38, ac: 14, init: 2,  sheet: { STR:8,  DEX:14, CON:13, INT:12, WIS:11, CHA:16, speed:30 } },
];

const byId = (id) => PARTY.find(p => p.id === id) || PREGEN_HEROES.find(h => h.id === id) || MONSTERS.find(m => m.id === id) || { name: '?', color: '#777', sprite: '❓' };

/* ---- 5e classes (per the 5e Companion app roster) ---- */
const CLASSES_5E = [
  { name: 'Artificer',  hd: 8,  prime: 'INT', sprite: '⚙️', color: '#6d8a3f' },
  { name: 'Barbarian',  hd: 12, prime: 'STR', sprite: '🪓', color: '#9a6f28' },
  { name: 'Bard',       hd: 8,  prime: 'CHA', sprite: '🎵', color: '#c25664' },
  { name: 'Cleric',     hd: 8,  prime: 'WIS', sprite: '✨', color: '#5b7fd0' },
  { name: 'Druid',      hd: 8,  prime: 'WIS', sprite: '🍃', color: '#2f8478' },
  { name: 'Fighter',    hd: 10, prime: 'STR', sprite: '⚔️', color: '#7d2330' },
  { name: 'Monk',       hd: 8,  prime: 'DEX', sprite: '👊', color: '#c9a23f' },
  { name: 'Paladin',    hd: 10, prime: 'STR', sprite: '🛡️', color: '#d0a93f' },
  { name: 'Ranger',     hd: 10, prime: 'DEX', sprite: '🏹', color: '#3f5d42' },
  { name: 'Rogue',      hd: 8,  prime: 'DEX', sprite: '🗡️', color: '#5a6473' },
  { name: 'Sorcerer',   hd: 6,  prime: 'CHA', sprite: '🔮', color: '#a23644' },
  { name: 'Warlock',    hd: 8,  prime: 'CHA', sprite: '👁️', color: '#5b4b8a' },
  { name: 'Wizard',     hd: 6,  prime: 'INT', sprite: '📖', color: '#3b62a8' },
];

/* ---- 5e races (per the 5e Companion app roster) ---- */
const RACES_5E = [
  { name: 'Human',      speed: 30, size: 'Medium' },
  { name: 'Elf',        speed: 30, size: 'Medium' },
  { name: 'Dwarf',      speed: 25, size: 'Medium' },
  { name: 'Halfling',   speed: 25, size: 'Small'  },
  { name: 'Dragonborn', speed: 30, size: 'Medium' },
  { name: 'Gnome',      speed: 25, size: 'Small'  },
  { name: 'Half-Elf',   speed: 30, size: 'Medium' },
  { name: 'Half-Orc',   speed: 30, size: 'Medium' },
  { name: 'Tiefling',   speed: 30, size: 'Medium' },
  { name: 'Aasimar',    speed: 30, size: 'Medium' },
  { name: 'Goliath',    speed: 30, size: 'Medium' },
  { name: 'Tabaxi',     speed: 30, size: 'Medium' },
  { name: 'Firbolg',    speed: 30, size: 'Medium' },
  { name: 'Tortle',     speed: 30, size: 'Medium' },
  { name: 'Genasi',     speed: 30, size: 'Medium' },
  { name: 'Aarakocra',  speed: 25, size: 'Medium', fly: 50 },
  { name: 'Kenku',      speed: 30, size: 'Medium' },
  { name: 'Lizardfolk', speed: 30, size: 'Medium' },
  { name: 'Triton',     speed: 30, size: 'Medium' },
  { name: 'Goblin',     speed: 30, size: 'Small'  },
  { name: 'Hobgoblin',  speed: 30, size: 'Medium' },
  { name: 'Kobold',     speed: 30, size: 'Small'  },
  { name: 'Orc',        speed: 30, size: 'Medium' },
  { name: 'Warforged',  speed: 30, size: 'Medium' },
];

const CHAR_COLORS = ['#c25664','#5b7fd0','#2f8478','#9a6f28','#a23644','#5b4b8a','#3f5d42','#c9a23f','#3b62a8','#7d2330'];

// Build a default level-5 character from race + class choices
function buildCharacter({ name, race, cls, portrait, color }) {
  const klass = CLASSES_5E.find(c => c.name === cls) || CLASSES_5E[5];
  const rc = RACES_5E.find(r => r.name === race) || RACES_5E[0];
  const lvl = 5;
  // standard array, prime ability gets the 15(+1)
  const base = { STR:10, DEX:13, CON:14, INT:8, WIS:12, CHA:10 };
  base[klass.prime] = 16;
  const conMod = Math.floor((base.CON - 10) / 2);
  const dexMod = Math.floor((base.DEX - 10) / 2);
  const hpMax = klass.hd + conMod + (lvl - 1) * (Math.floor(klass.hd / 2) + 1 + conMod);
  return {
    char: name, name: name.split(' ')[0], cls: klass.name, race: rc.name, lvl,
    color: color || klass.color, sprite: portrait ? '' : klass.sprite, portrait: portrait || null,
    hp: hpMax, hpMax, ac: 12 + dexMod, init: 0,
    sheet: { ...base, speed: rc.speed, fly: rc.fly || 0 },
    custom: true,
  };
}

Object.assign(window, { CLASSES_5E, RACES_5E, CHAR_COLORS, buildCharacter });

Object.assign(window, {
  PARTY, MONSTERS, START_TOKENS, MAPS, DICE_TYPES, SAVED_ROLLS,
  CHAT, POLLS, SUGGESTIONS_QUEUE, byId, PREGEN_HEROES, ELEMENTS,
});
