import { expect } from "@esm-bundle/chai";
import { VoxelGrid } from "../../src/grid/VoxelGrid.js";
import { RuinGenerator } from "../../src/generation/RuinGenerator.js";

describe("System: Procedural Generation (Scatter)", () => {
  let grid;

  beforeEach(() => {
    grid = new VoxelGrid(20, 5, 20);
  });

  it("CoA 1: scatterCover should place objects on valid floors", () => {
    const gen = new RuinGenerator(grid, 12345);

    // 1. Generate empty rooms first
    // Note: RuinGenerator runs applyTextures() automatically at the end of generate(),
    // so floor IDs will be 200+, not 1.
    gen.generate(1, 10, 10);

    // 2. Count empty floor tiles (Air above Solid)
    let floorCount = 0;
    for (let x = 0; x < 20; x++) {
      for (let z = 0; z < 20; z++) {
        // Check for Air at y=1
        const isAirAbove = grid.getCell(x, 1, z) === 0;
        // Check for ANY solid block at y=0 (Floor ID is likely 200+)
        const isSolidBelow = grid.getCell(x, 0, z) !== 0;

        if (isAirAbove && isSolidBelow) {
          floorCount++;
        }
      }
    }

    // 3. Scatter Cover (ID 10) at 50% density
    gen.scatterCover(10, 0.5);

    // 4. Count Cover
    let coverCount = 0;
    for (let x = 0; x < 20; x++) {
      for (let z = 0; z < 20; z++) {
        if (grid.getCell(x, 1, z) === 10) {
          coverCount++;
        }
      }
    }

    // Expect roughly 50% of the floor to be covered
    // Allow a wider margin (30-70%) for small sample sizes where RNG variance is higher
    const expectedMin = Math.floor(floorCount * 0.3);
    const expectedMax = Math.ceil(floorCount * 0.7);

    expect(floorCount).to.be.greaterThan(0, "No floors were generated!");
    expect(coverCount).to.be.within(
      expectedMin,
      expectedMax,
      `Cover count ${coverCount} not within 30-70% of floor count ${floorCount}`
    );
  });

  it("CoA 2: scatterCover should NOT place objects in mid-air", () => {
    const gen = new RuinGenerator(grid, 12345);
    gen.generate();
    gen.scatterCover(10, 1.0); // 100% density to force errors if logic is wrong

    // Scan for floating cover
    for (let x = 0; x < 20; x++) {
      for (let z = 0; z < 20; z++) {
        for (let y = 1; y < 4; y++) {
          if (grid.getCell(x, y, z) === 10) {
            const below = grid.getCell(x, y - 1, z);
            // Cover must have something solid below it
            expect(below).to.not.equal(
              0,
              `Found floating cover at ${x},${y},${z}`
            );
          }
        }
      }
    }
  });
});
