/* ============================================================
   mapview.jsx — node map navigation
   ============================================================ */
const { useState, useEffect, useRef } = React;
const NODE_STYLE = {
  battle: { color: '#ff5a3c', icon: 'ic_sword',  label: 'COMBATE', desc:'Combate contra enemigos del abismo.' },
  elite:  { color: '#ff9f1c', icon: 'ic_skull',  label: 'ÉLITE',   desc:'Enemigo Élite: más duro, pero suelta una RELIQUIA.' },
  boss:   { color: '#ff6b8b', icon: 'ic_skull',  label: 'JEFE',    desc:'El KRAKEN ABISAL. Jefe final del descenso.' },
  rest:   { color: '#2ce8d8', icon: 'ic_heart',  label: 'HOGUERA', desc:'Descansa: cúrate o forja (quita una carta).' },
  event:  { color: '#b06bff', icon: 'ic_door',   label: 'EVENTO',  desc:'Una decisión con consecuencias inciertas.' },
  shop:   { color: '#ffd23f', icon: 'ic_coin',   label: 'TIENDA',  desc:'Compra objetos para tu baraja con oro.' },
};

function MapView({ run, onPick, onOpenDeck }) {
  const map = run.map;
  const W = 1000, rowH = 132, padY = 70;
  const H = (map.ROWS - 1) * rowH + padY * 2;

  function nodeXY(r, c, count) {
    const x = (W) * ((c + 0.5) / count);
    const y = padY + r * rowH;
    return { x, y };
  }

  // availability
  let available = [];
  if (!run.pos) available = map.rows[0].map((n, c) => ({ r: 0, c }));
  else {
    const cur = map.rows[run.pos.r][run.pos.c];
    available = cur.links.map(c => ({ r: run.pos.r + 1, c }));
  }
  const isAvail = (r, c) => available.some(a => a.r === r && a.c === c);
  const visited = run.visited || {};

  const scrollRef = useRef(null);
  useEffect(() => {
    const place = () => {
      if (!scrollRef.current) return;
      const r = run.pos ? run.pos.r : 0;
      const y = padY + r * rowH;
      scrollRef.current.scrollTop = Math.max(0, y - scrollRef.current.clientHeight * 0.45);
    };
    requestAnimationFrame(() => requestAnimationFrame(place));
  }, []);

  return (
    <div className="fill col" style={{ background: 'linear-gradient(180deg,#0a1b2a,#0b1d2e)' }}>
      <TopBar run={run} onOpenDeck={onOpenDeck} title={['','EL DESCENSO','EL ABISMO','EL CEMENTERIO','LA FOSA','EL VELO NEGRO','LA CÁMARA DE RESONANCIA','BANCOS MUTANTES','LA SIMA PRESÓRICA','EL PECIO POLAR','EL PRISMA ABISAL'][run.act] || 'EL ABISMO'} />
      <div ref={scrollRef} style={{ flex: 1, minHeight: 0, overflowY: 'auto', position: 'relative' }}>
        <div style={{ position: 'relative', width: W, height: H, margin: '0 auto' }}>
          {/* edges */}
          <svg width={W} height={H} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
            {map.rows.map((row, r) => row.map((node, c) => node.links.map(tc => {
              const a = nodeXY(r, c, row.length);
              const b = nodeXY(r + 1, tc, map.rows[r + 1].length);
              const lit = (run.pos && run.pos.r === r && run.pos.c === c) || (visited[node.id] && visited[`n${r+1}_${tc}`]);
              return <line key={`${r}_${c}_${tc}`} x1={a.x} y1={a.y} x2={b.x} y2={b.y}
                stroke={lit ? '#ffd23f' : '#1d3b54'} strokeWidth={lit ? 4 : 3}
                strokeDasharray={lit ? '' : '2 8'} />;
            })))}
          </svg>
          {/* nodes */}
          {map.rows.map((row, r) => row.map((node, c) => {
            const { x, y } = nodeXY(r, c, row.length);
            const st = NODE_STYLE[node.type];
            const avail = isAvail(r, c);
            const isCur = run.pos && run.pos.r === r && run.pos.c === c;
            const wasVisited = visited[node.id];
            const size = node.type === 'boss' ? 76 : 56;
            return (
              <div key={node.id}
                onClick={() => avail && onPick(node)}
                {...window.tipProps({ title: st.label, color: st.color, icon: st.icon, body: st.desc })}
                style={{ position: 'absolute', left: x - size/2, top: y - size/2, width: size, height: size,
                  cursor: avail ? 'pointer' : 'help', zIndex: 2 }}>
                <div className={avail ? 'bob' : ''} style={{
                  width: size, height: size, borderRadius: node.type==='boss'?'12px':'50%',
                  display:'flex', alignItems:'center', justifyContent:'center',
                  background: avail || isCur ? `radial-gradient(circle at 35% 30%, ${st.color}, ${shade(st.color,-40)})` : '#13293d',
                  boxShadow: isCur ? `0 0 0 4px #07131f, 0 0 0 8px #fff`
                    : avail ? `0 0 0 4px #07131f, 0 0 0 7px ${st.color}, 0 0 24px ${st.color}aa`
                    : `0 0 0 4px #07131f, 0 0 0 5px #1d3b54`,
                  opacity: !avail && !isCur && !wasVisited ? 0.55 : 1,
                  filter: wasVisited && !isCur ? 'grayscale(.7) brightness(.7)' : 'none',
                  transition: 'all .15s',
                }}>
                  <Glyph name={st.icon} scale={node.type==='boss'?5:3.5} color={avail||isCur?'#07131f':'#3a5a72'} />
                </div>
                {(avail || node.type==='boss') && (
                  <div className="pix" style={{ position:'absolute', top:'100%', left:'50%', transform:'translateX(-50%)',
                    marginTop:6, fontSize:7, color: st.color, whiteSpace:'nowrap', textShadow:'1px 1px 0 #000' }}>{st.label}</div>
                )}
              </div>
            );
          }))}
        </div>
      </div>
      {available.length > 0 && (
        <div className="pix" style={{ textAlign:'center', padding:'10px', fontSize:9, color:'#9db8c9', background:'#07131f' }}>
          ▼ ELIGE TU RUTA ▼
        </div>
      )}
    </div>
  );
}

/* shared top bar with hp / gold / deck */
function TopBar({ run, onOpenDeck, title }) {
  const c = run.char;
  const amLabel = 'AMENAZA ' + (run.amenaza || 0);
  return (
    <div className="row" style={{ alignItems:'center', justifyContent:'space-between', padding:'10px 18px',
      background:'#07131f', borderBottom:'4px solid #16242f', gap:14 }}>
      <div className="row" style={{ alignItems:'center', gap:12 }}>
        <Sprite name={c.sprite || 'tuntun'} scale={2} hue={c.hue} />
        <div className="col" style={{ gap:5 }}>
          <div className="row" style={{ alignItems:'center', gap:8 }}>
            <span className="pix" style={{ fontSize:9, color:'#fff' }}>{c.name}</span>
            <span className="pix" style={{ fontSize:7, color:'#ff5a3c', border:'2px solid #ff5a3c', padding:'1px 4px' }}>{amLabel}</span>
          </div>
          <StatBar hp={run.hp} maxHp={c.maxHp} width={150} />
        </div>
      </div>
      <div className="col center" style={{ gap:6 }}>
        <div className="row center" style={{ gap:8, alignItems:'center' }}>
          <span className="pix" style={{ fontSize:7, color:'#2ce8d8', border:'2px solid #2ce8d8', padding:'1px 4px' }}>ACTO {['','I','II','III','IV','V','VI','VII','VIII','IX','X'][run.act] || 'II'}</span>
          <div className="pix" style={{ fontSize:13, color:'#ffd23f', textShadow:'2px 2px 0 #000' }}>{title}</div>
        </div>
        {run.relics && run.relics.length > 0 && (
          <div className="row" style={{ gap:6 }}>
            {run.relics.map((id, i) => { const rel = window.GAME.RELICS[id]; return (
              <div key={i} {...window.tipProps(window.tipForRelic(rel))} className="col center" style={{ width:24, height:24, borderRadius:'50%',
                background:'#0b1d2e', boxShadow:'0 0 0 2px '+rel.color, cursor:'help' }}>
                <Glyph name={rel.icon} scale={2} color={rel.color} />
              </div>
            ); })}
          </div>
        )}
        <LoadoutChips run={run} />
      </div>
      <div className="row" style={{ alignItems:'center', gap:16 }}>
        <div className="row" style={{ alignItems:'center', gap:6 }}>
          <Glyph name="ic_coin" scale={3} color="#ffd23f" />
          <span className="pix" style={{ fontSize:11, color:'#ffd23f' }}>{run.gold}</span>
        </div>
        <Btn onClick={onOpenDeck} style={{ fontSize:9, padding:'8px 12px' }}>BARAJA · {run.deck.length}</Btn>
      </div>
    </div>
  );
}

/* harpoon mods + consumables the player currently carries (read-only chips with tooltips) */
function LoadoutChips({ run }) {
  const mods = run.harpoonMods || [];
  const cons = run.consumables || [];
  if (!mods.length && !cons.length) return null;
  const counts = {}; cons.forEach(id => { counts[id] = (counts[id] || 0) + 1; });
  return (
    <div className="row center" style={{ gap: 6, flexWrap: 'wrap', maxWidth: 320 }}>
      {mods.map((id, i) => { const m = window.GAME.harpoonMod(id); return (
        <div key={'h'+i} {...window.tipProps({ title: m.name, color: m.color, icon: m.icon, body: m.desc, sub: 'MOD DE ARPÓN' })}
          className="col center" style={{ width: 22, height: 22, borderRadius: 4, background:'#0b1d2e', boxShadow:'0 0 0 2px '+m.color, cursor:'help' }}>
          <Glyph name={m.icon} scale={2} color={m.color} />
        </div>
      ); })}
      {Object.entries(counts).map(([id, n], i) => { const c = window.GAME.consumable(id); return (
        <div key={'c'+i} {...window.tipProps({ title: c.name, color: c.color, icon: c.icon, body: c.desc, sub: 'CONSUMIBLE' })}
          className="row center" style={{ gap: 1, padding:'2px 4px', background:'#0b1d2e', boxShadow:'0 0 0 2px '+c.color, cursor:'help' }}>
          <Glyph name={c.icon} scale={2} color={c.color} />
          {n > 1 && <span className="pix" style={{ fontSize: 7, color: c.color }}>{n}</span>}
        </div>
      ); })}
    </div>
  );
}

window.MapView = MapView;
window.TopBar = TopBar;
window.LoadoutChips = LoadoutChips;
