/**
 * What an Arena office-nav snapshot may legally contain, now that a walker can
 * change storeys.
 *
 * `src/interiors/walker.ts`'s `restore()` used to refuse any snapshot whose
 * `levelId` differed from the spawn level, and `OfficeNavEnvironment` restores
 * an episode straight through it. That rule has been relaxed to "a level the
 * plan resolves, at a position valid on it" — which is a change to this
 * environment's contract and not an internal detail, so it is asserted here
 * explicitly rather than left implied by the controller's own unit tests.
 *
 * Frontier Valley is the pack this environment runs, and it has a mezzanine at
 * 4.4 m whose footprint is a *subset* of the ground floor's. That is what makes
 * the second assertion below meaningful: `(20, 18)` is a place a walker can
 * stand on level 1 and is off the edge of the mezzanine, so "valid on the level
 * you are on" and "valid somewhere in this building" are different answers.
 */

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { arenaChecksum } from "../../arena/checksum.ts";
import { OfficeNavEnvironment } from "../../arena/officeNav.ts";

/** Re-checksum a hand-edited snapshot so the episode bookkeeping still validates. */
function resign<T extends { checksum: string }>(snapshot: T): T {
  const { checksum: _drop, ...core } = snapshot;
  return { ...core, checksum: arenaChecksum(core) } as T;
}

describe("arena office-nav snapshots across storeys", () => {
  it("restores an episode whose walker is on the mezzanine", () => {
    const environment = new OfficeNavEnvironment();
    environment.reset(11, "train-hangar-crossing");
    const snapshot = environment.snapshot();
    assert.equal(snapshot.simulation.walker.levelId, "level-1");

    const upstairs = resign({
      ...snapshot,
      simulation: {
        ...snapshot.simulation,
        walker: {
          ...snapshot.simulation.walker,
          levelId: "level-mezz",
          position: { x: 45, z: 25 },
        },
      },
    });

    const restored = environment.restore(upstairs);
    assert.equal(restored.observation.levelId, "level-mezz");
    assert.equal(restored.observation.x, 45);
    assert.equal(restored.observation.z, 25);
  });

  it("still refuses a position that is not valid on the level it names", () => {
    const environment = new OfficeNavEnvironment();
    environment.reset(11, "train-hangar-crossing");
    const snapshot = environment.snapshot();

    // Inside the hangar, well off the west edge of the mezzanine.
    const offTheEdge = resign({
      ...snapshot,
      simulation: {
        ...snapshot.simulation,
        walker: {
          ...snapshot.simulation.walker,
          levelId: "level-mezz",
          position: { x: 20, z: 18 },
        },
      },
    });
    assert.throws(() => environment.restore(offTheEdge), RangeError);

    const unknownLevel = resign({
      ...snapshot,
      simulation: {
        ...snapshot.simulation,
        walker: { ...snapshot.simulation.walker, levelId: "level-9" },
      },
    });
    assert.throws(() => environment.restore(unknownLevel), RangeError);
  });
});
