/** * Dev-only visual probe for the JOB BOARD console (js/ui/JobBoardWindow.js): * boots the real flow (menu → new game → land on the home world → surface), * then parks at the stage named in the URL hash, with a report in a DOM *
 the screenshot can always read:
 *
 *   #drawer (default) — the HOME world's EXPLORE: no drawer at all (the
 *        Job Board slot is absent — data/actionbar.json →
 *        `isHomeSystem: false`, safe space), the slot's press is a no-op
 *        with the console's ack ("NOTHING TO EXPLORE HERE").
 *   #board            — the board console OPEN over the surface (nearly
 *        full-screen, depth 80 — over the deck + drawer + the upper-left
 *        HUD), driven through the scene's own seams (the slot's press →
 *        the toggle): the left feed (assets/videos/jobboard.mp4, muted
 *        loop), the right JOB BOARD title + the AVAILABLE JOBS / JOB
 *        DETAILS placeholder sections, the deck stood down (the slot's
 *        press stays live as the second door; the ✕ is the way-out).
 *        PROBE STAGING: the home world's isHomeSystem flag is flipped
 *        for this shot so the slot exists here (on a real non-home world
 *        it exists naturally — the drawer's item list is the
 *        where-clause's, covered by dev/explore.test.mjs).
 *   #left             — …and back: the slot's press again (the second
 *        door) — the console down, the deck live, the slot still JOB
 *        BOARD (no relabel either way).
 *
 *   node dev/server.mjs 8080
 *   brave --headless --disable-gpu --remote-debugging-port=9333 --window-size=1280,720 about:blank
 *   node dev/cdp-shot.mjs "http://127.0.0.1:8080/dev/jobboard-shot.html#drawer" jb-drawer.png "window.__JB && window.__JB.stage && !/FAILED/.test(window.__JB.stage)" 45000
 *   node dev/cdp-shot.mjs "http://127.0.0.1:8080/dev/jobboard-shot.html#board" jb-board.png "window.__JB && window.__JB.stage && !/FAILED/.test(window.__JB.stage)" 45000
 *   node dev/cdp-shot.mjs "http://127.0.0.1:8080/dev/jobboard-shot.html#left" jb-left.png "window.__JB && window.__JB.stage && !/FAILED/.test(window.__JB.stage)" 45000
 */
import Phaser from '../js/vendor/phaser.js';
import { config } from '../js/config/Config.js';
import { ConfigLoader } from '../js/config/ConfigLoader.js';
import { createGameConfig } from '../js/config/GameConfig.js';
import { MenuScene } from '../js/scenes/MenuScene.js';
import { GameScene } from '../js/scenes/GameScene.js';
import { SurfaceScene } from '../js/scenes/SurfaceScene.js';

const data = await ConfigLoader.load();
config.init(data);

// Capture console errors + uncaught exceptions for the report.
const errors = [];
const origErr = console.error.bind(console);
console.error = (...a) => { errors.push(a.map(String).join(' ')); origErr(...a); };
window.addEventListener('error', (e) => errors.push(String(e.message)));
window.addEventListener('unhandledrejection', (e) => errors.push(`rejection: ${e.reason}`));

const gameConfig = createGameConfig();
gameConfig.scene = [MenuScene, GameScene, SurfaceScene];
const game = new Phaser.Game(gameConfig);
window.game = game;

const report = document.createElement('pre');
report.id = 'report';
report.style.cssText = 'position:fixed;left:10px;top:10px;z-index:9999;max-width:72%;margin:0;padding:8px 12px;font:13px/1.5 monospace;color:#eaf6ff;background:rgba(6,20,16,0.92);border:1px solid #1b3a5a;white-space:pre-wrap;';
document.body.appendChild(report);
const setReport = (lines) => { report.textContent = (Array.isArray(lines) ? lines : [lines]).join('\n'); };
setReport('booting… (menu → new game → home world → surface)');

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function waitFor(fn, tries = 200, everyMs = 100) {
  for (let i = 0; i < tries; i++) {
    const v = fn();
    if (v) return v;
    await sleep(everyMs);
  }
  return null;
}

const STAGE = (location.hash || '#drawer').slice(1) || 'drawer';
const deckReport = (ss) =>
  (ss.actionBar?.slots ?? []).filter((s) => s.live).map((s) => `${s.id}:${s.disabled ? 'off' : 'on'}`);
const slotLabel = (ss) => {
  const b = (ss.exploreSubBar?.buttons ?? []).find((x) => x.id === 'jobBoard');
  return b ? b.btn.labelText.text : '(absent — no drawer on the home world)';
};

try {
  // 1) The real menu flow: NEW GAME.
  const menu = await waitFor(() => { const m = game.scene.getScene('MenuScene'); return m?.newGameBtn ? m : null; });
  if (!menu) throw new Error('menu never booted');
  menu.startNewGame();
  const gs = await waitFor(() => { const g = game.scene.getScene('GameScene'); return g?.ship ? g : null; }, 200);
  if (!gs) throw new Error('GameScene never booted');
  await sleep(600);

  // 2) Land on the home world the game's own way (the target is built
  //    WHILE the home flag still reads true — the HUD's "Home World"
  //    label comes from it).
  const target = gs.commsTargetFor(gs.planet);
  if (STAGE !== 'drawer') gs.isHomeSystem = false; // PROBE STAGING — the slot's visual on this world
  gs.startLanding(target);
  const ss = await waitFor(() => { const c = game.scene.getScene('SurfaceScene'); return c?.jobBoardWindow ? c : null; }, 200);
  if (!ss) throw new Error('surface never booted');
  await sleep(700);
  ss.startSurface(); // force the loop stage (don't wait the landing clip out)
  const forcePlay = (v) => { if (v?.video) { v.video.muted = true; v.video.play().catch(() => {}); } };
  forcePlay(ss.surfaceVideo);
  await sleep(900);

  const win = ss.jobBoardWindow;

  if (STAGE === 'drawer') {
    // The HOME world's EXPLORE — the slot is a no-op (no drawer: the
    // Job Board's `isHomeSystem: false` clause leaves the item list
    // empty, and a world with no items gets no drawer).
    ss.toggleExplore();
    await sleep(400); // the console note in + hold
    window.__JB = {
      stage: 'drawer',
      home: ss.planetName,
      isHomeSystem: gs.isHomeSystem === true,
      drawerPresent: !!ss.exploreSubBar,
      drawerItems: (ss.exploreSubBar?.buttons ?? []).map((b) => b.id),
      noteG: ss.noteG ? ss.noteG.map((g) => g?.text) : null,
      deck: deckReport(ss),
      errors,
    };
    setReport(JSON.stringify(window.__JB, null, 1));
  } else {
    // The slot's player path: the drawer's JOB BOARD press → the toggle
    // (the drawer's onAction seam — the same call the button's press
    // makes on every non-home world).
    ss.toggleExplore();
    await sleep(1100); // the drawer's unfold
    ss.exploreAction('jobBoard');
    await sleep(1900); // the board’s reveal + the title’s decode
    // Headless autoplay policy: force the feed visible (muted).
    if (win.video?.video) { win.video.video.muted = true; win.video.video.play().catch(() => {}); }
    await sleep(700); // let a frame land
    window.__JB = {
      stage: 'board',
      world: ss.planetName,
      staged: 'isHomeSystem flipped for the slot’s visual (a real non-home world has it naturally)',
      jobBoardMode: ss.jobBoardMode,
      openState: win?.openState,
      title: win?.rightTitle?.text,
      titlePos: win?.rightTitle ? [Math.round(win.rightTitle.x), Math.round(win.rightTitle.y)] : null,
      jobs: win?.jobsSection ? { a: +win.jobsSection.bg.alpha.toFixed(2), y: Math.round(win.jobsSection.bg.y), head: win.jobsSection.headTxt.text, ha: +win.jobsSection.headTxt.alpha.toFixed(2) } : null,
      detail: win?.detailSection ? { a: +win.detailSection.bg.alpha.toFixed(2), y: Math.round(win.detailSection.bg.y), head: win.detailSection.headTxt.text, ha: +win.detailSection.headTxt.alpha.toFixed(2) } : null,
      geo: win?.geo ? { bodyY: win.geo.bodyY, bodyBottom: win.geo.bodyBottom, rightX: win.geo.rightX, rightW: win.geo.rightW, availTop: win.geo.availTop, availH: win.geo.availH, detailPanelY: win.geo.detailPanelY, detailH: win.geo.detailH } : null,
      video: win?.video ? { muted: win.video.video.muted, loop: win.video.loop, volume: win.video.volume } : null,
      slotLabel: slotLabel(ss),
      drawerItems: (ss.exploreSubBar?.buttons ?? []).map((b) => b.id),
      deck: deckReport(ss),
      errors,
    };
    setReport(JSON.stringify(window.__JB, null, 1));

    if (STAGE === 'left') {
      // LEAVE — the slot's press again (the player's exact way out).
      ss.exploreAction('jobBoard');
      await sleep(900); // the close + the relabel back
      window.__JB = {
        stage: 'left',
        world: ss.planetName,
        jobBoardMode: ss.jobBoardMode,
        openState: win?.openState,
        slotLabel: slotLabel(ss),
        deck: deckReport(ss),
        errors,
      };
      setReport(JSON.stringify(window.__JB, null, 1));
    }
  }
} catch (err) {
  window.__JB = { stage: 'FAILED', error: String(err?.message ?? err), errors };
  setReport(JSON.stringify(window.__JB, null, 1));
}