/* global React, EnemyCard, PartyCard, AbilityBlock, ZoneBackdrop, StateIconGroup, Timer, WaveCounter, FloatingNumber, Portrait, HpBar, ResourceBar, CastBar, formatNum, useCombat, makeParty */
const { useState: useStateSC, useEffect: useEffectSC, useRef: useRefSC, useMemo: useMemoSC } = React;

const G = window.GAME_DATA;

// ============================================================
// TOP BAR (shared)
// ============================================================

function TopBar({ zone, wave, totalWaves, isBoss, time, onAbandon }) {
  return (
    <div className="top-bar">
      <div className="top-bar-left">
        <div className="zone-name">
          {zone.name}
          <span className="tier">{zone.tier}</span>
        </div>
        <WaveCounter wave={wave} total={totalWaves} isBoss={isBoss} />
      </div>
      <div className="top-bar-center">
        <div className="state-icons">
          <StateIconGroup icons={G?.ZONE_BUFFS ?? []} kind="buff" />
          <StateIconGroup icons={G?.ZONE_DEBUFFS ?? []} kind="debuff" />
        </div>
      </div>
      <div className="top-bar-right">
        <Timer seconds={time} />
        <button className="btn btn-ghost">Offline</button>
        <button className="btn btn-danger" onClick={onAbandon}>Abandonar</button>
      </div>
    </div>
  );
}

// ============================================================
// COMBAT LOG STRIP
// ============================================================

function CombatLog({ log, show, onToggle }) {
  const bodyRef = useRefSC(null);
  useEffectSC(() => {
    if (bodyRef.current) {
      bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    }
  }, [log.length]);
  return (
    <div className={`combat-log ${!show ? 'hidden' : ''}`}>
      <button className="log-collapse-btn" onClick={onToggle}>
        {show ? '▼ Ocultar registro' : '▲ Mostrar registro'}
      </button>
      <div className="combat-log-head">
        <span className="title">
          <span className="pulse"></span>
          Registro de combate · Motor Worker activo
        </span>
        <span className="title" style={{ color: 'var(--ink-3)' }}>{log.length} eventos</span>
      </div>
      <div className="combat-log-body scrollbar" ref={bodyRef}>
        {log.slice(-4).map((l, i) => (
          <LogLine key={l.id} entry={l} />
        ))}
      </div>
    </div>
  );
}

function LogLine({ entry }) {
  if (entry.system) {
    return <div className="log-line system">{entry.text}</div>;
  }
  return (
    <div className={`log-line ${entry.crit ? 'crit' : ''}`}>
      <span className="t">[{entry.t}]</span>
      <span className="actor">{entry.actor}</span>
      {entry.missed
        ? <> falló <span className="ability">{entry.ability}</span> en <span className="target">{entry.target}</span></>
        : entry.heal
          ? <> usó <span className="ability">{entry.ability}</span> en <span className="target">{entry.target}</span>. <span className="heal">+{formatNum(entry.heal)} HP</span></>
          : entry.dmg > 0
            ? <> usó <span className="ability">{entry.ability}</span> en <span className="target">{entry.target}</span> por <span className="dmg">{formatNum(entry.dmg)}{entry.crit ? ' (¡CRIT!)' : ''}</span></>
            : <> activó <span className="ability">{entry.ability}</span></>
      }
    </div>
  );
}

// ============================================================
// PRE-COMBAT LOADOUT SCREEN
// ============================================================

function LoadoutScreen({ zone, partyConfig, onChange, onStart }) {
  const [editing, setEditing] = useStateSC(null); // char index
  return (
    <div className="loadout-screen" data-screen-label="01 Pre-combat">
      <ZoneBackdrop zone={zone} />

      <div className="loadout-head" style={{ zIndex: 5, position: 'relative' }}>
        <div className="loadout-title">
          <span className="eyebrow">Preparación de incursión · Fase I</span>
          <span>{zone.name}</span>
        </div>
        <div className="loadout-summary">
          <span className="big">{G.WAVES.length} oleadas</span>
          <span className="small">{zone.tier} · Dificultad heroica</span>
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'flex-end', gap: 14 }}>
          <div className="ready-pill"><span className="dot"></span> Grupo listo</div>
        </div>
      </div>

      <div className="loadout-grid" style={{ zIndex: 5, position: 'relative' }}>
        {partyConfig.map((c, idx) => (
          <PartyLoadoutCard
            key={c.id}
            char={c}
            isYou={idx === 0}
            hotkey={idx + 1}
            onEdit={() => setEditing(idx)}
            onToggleAuto={() => onChange(idx, { autoCast: !c.autoCast })}
          />
        ))}
      </div>

      <div className="loadout-foot" style={{ zIndex: 5, position: 'relative' }}>
        <div className="ready-state">
          <div className="ready-pill"><span className="dot" style={{ background: 'var(--accent)' }}></span> 4 héroes</div>
          <div className="ready-pill"><span className="dot" style={{ background: 'var(--mp)' }}></span> {partyConfig.filter(c => c.autoCast).length} en autocast</div>
          <div className="ready-pill"><span className="dot" style={{ background: 'var(--ene)' }}></span> Motor Worker disponible</div>
        </div>
        <button className="btn btn-accent btn-xl" onClick={onStart}>Iniciar Combate ›</button>
      </div>

      {editing != null && (
        <AbilitySwapDrawer
          char={partyConfig[editing]}
          current={partyConfig[editing].abilityId}
          onSelect={(id) => { onChange(editing, { abilityId: id }); setEditing(null); }}
          onClose={() => setEditing(null)}
        />
      )}
    </div>
  );
}

function PartyLoadoutCard({ char, isYou, hotkey, onEdit, onToggleAuto }) {
  const ability = G.ABILITIES[char.abilityId];
  const [imgFailedLC, setImgFailedLC] = useStateSC(false);
  const showImgLC = !!char.portraitImg && !imgFailedLC;
  return (
    <div className="party-card">
      <div className="pc-portrait" style={{ background: `radial-gradient(ellipse at center, ${char.portraitTint}22 0%, transparent 65%), var(--bg-1)`, position: 'relative', overflow: 'hidden' }}>
        {showImgLC ? (
          <img
            src={char.portraitImg}
            alt={char.name}
            onError={() => setImgFailedLC(true)}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'top center', opacity: 0.95 }}
          />
        ) : (
          <span className="glyph">{char.portraitGlyph}</span>
        )}
        {!showImgLC && <span className="slot-tag">character portrait</span>}
      </div>
      <div className="pc-info">
        <div className="nm">
          {char.name}
          {isYou && <span className="you">tú</span>}
        </div>
        <div className="meta">{char.cls} · Nivel {char.lvl} · {char.role}</div>
      </div>
      <div className="pc-stats">
        <div className="stat-row"><span className="k">HP</span><span className="v">{formatNum(char.hp)}</span></div>
        {char.resource === 'mp' && <div className="stat-row"><span className="k">MP</span><span className="v">{formatNum(char.mpMax || char.mp)}</span></div>}
        {char.resource === 'fur' && <div className="stat-row"><span className="k">Furia máx.</span><span className="v">{char.furMax}</span></div>}
        {char.resource === 'ene' && <div className="stat-row"><span className="k">Energía máx.</span><span className="v">{char.eneMax}</span></div>}
      </div>
      <div className="pc-ability">
        <span className="ab-label">Habilidad activa</span>
        <div className="ab-current" onClick={onEdit}>
          <div className="ab-glyph">{ability.glyph}</div>
          <div className="ab-text">
            <div className="n">{ability.name}</div>
            <div className="d">{ability.desc}</div>
            <div className="tags">
              <span className="tag">{ability.tag}</span>
              <span className="tag">CD {ability.cd}s</span>
            </div>
          </div>
          <span className="swap">Cambiar</span>
        </div>
        <div className="autocast-row">
          <div className="auto-toggle" onClick={onToggleAuto} style={{ cursor: 'pointer' }}>
            <span className="lbl">Autocast</span>
            <div className={`toggle ${char.autoCast ? 'on' : ''}`}></div>
          </div>
          <div className="hot">Tecla <b>{hotkey}</b></div>
        </div>
      </div>
    </div>
  );
}

function AbilitySwapDrawer({ char, current, onSelect, onClose }) {
  const all = Object.values(G.ABILITIES);
  return (
    <div className="swap-drawer-bg" onClick={onClose}>
      <div className="swap-drawer" onClick={e => e.stopPropagation()}>
        <div className="swap-drawer-head">
          <div>
            <div className="ttl">Banco de habilidades — {char.name}</div>
            <div className="sub">{char.cls} · Nivel {char.lvl} · 1 habilidad activa por personaje</div>
          </div>
          <button className="btn" onClick={onClose}>Cerrar ✕</button>
        </div>
        <div className="swap-drawer-body scrollbar">
          {all.map(ab => (
            <div
              key={ab.id}
              className={`swap-card ${ab.id === current ? 'selected' : ''}`}
              onClick={() => onSelect(ab.id)}
            >
              <div className="sc-glyph">{ab.glyph}</div>
              <div className="sc-text">
                <div className="n">{ab.name}</div>
                <div className="d">{ab.desc}</div>
                <div className="meta">
                  <span className="tag">{ab.tag}</span>
                  <span>CD {ab.cd}s</span>
                  {ab.cost > 0 && <span>{ab.cost} {ab.costType.toUpperCase()}</span>}
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ============================================================
// MAIN COMBAT SCREEN
// ============================================================

function CombatScreen({ zone, partyConfig, showLog, onLogToggle, onVictory, onDefeat, dmgStyle }) {
  const [log, setLog] = useStateSC([]);
  const [floats, setFloats] = useStateSC([]);
  const logIdRef = useRefSC(0);
  const floatIdRef = useRefSC(0);

  const pushLog = (entry) => {
    const t = new Date();
    const stamp = `${String(t.getMinutes()).padStart(2, '0')}:${String(t.getSeconds()).padStart(2, '0')}`;
    setLog(prev => [...prev.slice(-50), { ...entry, id: ++logIdRef.current, t: stamp }]);
  };

  const pushFloat = (f) => {
    const id = ++floatIdRef.current;
    setFloats(prev => [...prev, { ...f, id }]);
    setTimeout(() => setFloats(prev => prev.filter(x => x.id !== id)), 1400);
  };

  const combat = useCombat({
    wave: 0,
    partyConfig,
    zone,
    onVictory,
    onDefeat,
    pushFloat,
    pushLog,
  });

  // keyboard hotkeys
  useEffectSC(() => {
    const handler = (e) => {
      if (e.key === '1' || e.key === '2' || e.key === '3' || e.key === '4') {
        const idx = parseInt(e.key, 10) - 1;
        if (window.__castAbility) window.__castAbility(idx);
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, []);

  // initial system log
  useEffectSC(() => {
    pushLog({ system: true, text: `— Oleada 1 — Motor Worker activo` });
  }, []);

  return (
    <div className="combat-screen" data-screen-label="02 Combat" style={{ position: 'absolute', inset: 0 }}>
      <ZoneBackdrop zone={zone} />
      <TopBar
        zone={zone}
        wave={combat.waveIndex + 1}
        totalWaves={G.WAVES.length}
        time={combat.time}
        onAbandon={onDefeat}
      />

      <div className={`arena ${showLog ? 'with-log' : ''}`}>
        <span className="row-label enemies">Enemigos · Oleada {combat.waveIndex + 1}</span>
        <div className="row-enemies">
          {combat.enemies.map((e, i) => (
            <div key={e.id} style={{ position: 'relative' }} data-unit-id={e.id}>
              <EnemyCard
                unit={e}
                isCasting={!!e.casting}
                castProgress={e.castProgress}
                isTargeted={i === 0 && e.hp > 0}
              />
              {floats.filter(f => f.targetId === e.id).map(f => (
                <FloatingNumber
                  key={f.id}
                  id={f.id}
                  kind={f.kind}
                  value={f.value}
                  x={135 - (f.kind === 'crit' ? 60 : 40) + (f.id % 5) * 14 - 28}
                  y={120 + (f.id % 3) * 10 - 10}
                />
              ))}
            </div>
          ))}
        </div>

        <div className="vs-divider">
          <div className="vs-line"></div>
          <div className="vs-badge">VS</div>
          <div className="vs-line"></div>
        </div>

        <span className="row-label party">Tu grupo</span>
        <div className="row-party">
          {combat.party.map((p, i) => (
            <div key={p.id} style={{ position: 'relative' }} data-unit-id={p.id}>
              <PartyCard
                unit={p}
                ability={G.ABILITIES[p.abilityId]}
                isActive={i === combat.activeChar}
                isCasting={!!p.casting}
                castProgress={p.castProgress}
              />
              {floats.filter(f => f.targetId === p.id).map(f => (
                <FloatingNumber
                  key={f.id}
                  id={f.id}
                  kind={f.kind}
                  value={f.value}
                  x={135 - 40 + (f.id % 5) * 12 - 24}
                  y={130 + (f.id % 3) * 8 - 8}
                />
              ))}
            </div>
          ))}
        </div>
      </div>

      <div className={`ability-dock ${showLog ? 'with-log' : ''}`}>
        <div className="dock-side">
          <div className="lbl-stack">
            <span className="l1">Habilidades</span>
            <span className="l2">1 / personaje</span>
          </div>
        </div>
        {combat.party.map((p, i) => {
          const ability = G.ABILITIES[p.abilityId];
          return (
            <AbilityBlock
              key={p.id}
              unit={p}
              ability={ability}
              cd={p.cd}
              cdMax={ability?.cd || 5}
              ready={p.cd <= 0 && !p.casting && p.hp > 0}
              casting={!!p.casting}
              hotkey={i + 1}
              isYou={i === 0}
              autoCast={p.autoCast}
              onCast={() => combat.castAbility(i)}
              onToggleAuto={() => window.__toggleAuto && window.__toggleAuto(i)}
            />
          );
        })}
        <div className="dock-side">
          <div className="lbl-stack">
            <span className="l1">Atajos</span>
            <span className="l2">1 · 2 · 3 · 4</span>
          </div>
        </div>
      </div>

      {showLog && <CombatLog log={log} show={showLog} onToggle={onLogToggle} />}
      {!showLog && (
        <button
          className="log-collapse-btn"
          style={{ position: 'absolute', right: 32, bottom: 100, zIndex: 9 }}
          onClick={onLogToggle}
        >▲ Mostrar registro</button>
      )}
    </div>
  );
}

window.LoadoutScreen = LoadoutScreen;
window.CombatScreen = CombatScreen;
window.TopBar = TopBar;
window.CombatLog = CombatLog;
