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

describe("Generation: BaseGenerator", () => {
  let grid;
  let generator;

  beforeEach(() => {
    grid = new VoxelGrid(10, 5, 10);
    generator = new BaseGenerator(grid, 12345);
  });

  it("CoA 1: Should initialize with grid and RNG", () => {
    expect(generator.grid).to.equal(grid);
    expect(generator.rng).to.exist;
    expect(generator.width).to.equal(10);
    expect(generator.height).to.equal(5);
    expect(generator.depth).to.equal(10);
  });

  it("CoA 2: getSolidNeighbors should count solid neighbors correctly", () => {
    // Set up a pattern: center is air, surrounded by solids
    grid.setCell(5, 2, 5, 0); // Center (air)
    grid.setCell(4, 2, 5, 1); // Left
    grid.setCell(6, 2, 5, 1); // Right
    grid.setCell(5, 2, 4, 1); // Front
    grid.setCell(5, 2, 6, 1); // Back
    grid.setCell(5, 1, 5, 1); // Below
    grid.setCell(5, 3, 5, 1); // Above

    const count = generator.getSolidNeighbors(5, 2, 5);

    // Should count at least 6 neighbors (excluding center)
    expect(count).to.be.greaterThanOrEqual(6);
  });

  it("CoA 3: getSolidNeighbors should handle out-of-bounds as solid", () => {
    // Test edge case - corner position
    grid.setCell(0, 0, 0, 0); // Air at corner

    const count = generator.getSolidNeighbors(0, 0, 0);

    // Out-of-bounds neighbors should count as solid
    expect(count).to.be.greaterThan(0);
  });

  it("CoA 4: scatterCover should place objects on valid floor tiles", () => {
    // Create a floor: solid at y=0, air at y=1
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        grid.setCell(x, 0, z, 1); // Floor
        grid.setCell(x, 1, z, 0); // Air above
      }
    }

    generator.scatterCover(10, 0.5); // 50% density

    // Check that some objects were placed
    let objectCount = 0;
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        if (grid.getCell(x, 1, z) === 10) {
          objectCount++;
        }
      }
    }

    // With 50% density on ~64 tiles, we should get some objects
    expect(objectCount).to.be.greaterThan(0);
  });

  it("CoA 5: scatterCover should not place objects on invalid tiles", () => {
    // Create invalid floor: air at y=0 (no solid below)
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        grid.setCell(x, 0, z, 0); // No floor
        grid.setCell(x, 1, z, 0); // Air
      }
    }

    generator.scatterCover(10, 1.0); // 100% density

    // No objects should be placed
    let objectCount = 0;
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        if (grid.getCell(x, 1, z) === 10) {
          objectCount++;
        }
      }
    }

    expect(objectCount).to.equal(0);
  });

  it("CoA 6: scatterCover should respect density parameter", () => {
    // Create valid floor
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        grid.setCell(x, 0, z, 1);
        grid.setCell(x, 1, z, 0);
      }
    }

    // Test with different densities
    generator.scatterCover(10, 0.1); // 10% density
    let lowCount = 0;
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        if (grid.getCell(x, 1, z) === 10) lowCount++;
      }
    }

    // Reset and test higher density
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        grid.setCell(x, 1, z, 0);
      }
    }

    generator.scatterCover(10, 0.9); // 90% density
    let highCount = 0;
    for (let x = 1; x < 9; x++) {
      for (let z = 1; z < 9; z++) {
        if (grid.getCell(x, 1, z) === 10) highCount++;
      }
    }

    // Higher density should generally produce more objects
    // (allowing for randomness, but trend should be clear)
    expect(highCount).to.be.greaterThan(lowCount);
  });
});

