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

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

  beforeEach(() => {
    grid = new VoxelGrid(20, 10, 20);
    generator = new CaveGenerator(grid, 12345);
  });

  it("CoA 1: Should initialize with texture generators", () => {
    expect(generator.floorGen).to.exist;
    expect(generator.wallGen).to.exist;
    expect(generator.generatedAssets).to.have.property("palette");
  });

  it("CoA 2: preloadTextures should generate texture palette", () => {
    generator.preloadTextures();

    // Should have wall variations (100-109)
    expect(generator.generatedAssets.palette[100]).to.exist;
    expect(generator.generatedAssets.palette[109]).to.exist;

    // Should have floor variations (200-209)
    expect(generator.generatedAssets.palette[200]).to.exist;
    expect(generator.generatedAssets.palette[209]).to.exist;
  });

  it("CoA 3: generate should create foundation layer", () => {
    generator.generate(0.5, 2);

    // Foundation (y=0) should be solid
    for (let x = 0; x < grid.size.x; x++) {
      for (let z = 0; z < grid.size.z; z++) {
        expect(grid.getCell(x, 0, z)).to.not.equal(0);
      }
    }
  });

  it("CoA 4: generate should keep sky clear", () => {
    generator.generate(0.5, 2);

    // Top layer (y=height-1) should be air
    const topY = grid.size.y - 1;
    for (let x = 0; x < grid.size.x; x++) {
      for (let z = 0; z < grid.size.z; z++) {
        expect(grid.getCell(x, topY, z)).to.equal(0);
      }
    }
  });

  it("CoA 5: smooth should apply cellular automata rules", () => {
    // Set up initial pattern
    for (let x = 0; x < grid.size.x; x++) {
      for (let z = 0; z < grid.size.z; z++) {
        for (let y = 1; y < grid.size.y - 1; y++) {
          grid.setCell(x, y, z, Math.random() > 0.5 ? 1 : 0);
        }
      }
    }

    const beforeState = grid.cells.slice();
    generator.smooth();
    const afterState = grid.cells.slice();

    // Smoothing should change the grid
    expect(afterState).to.not.deep.equal(beforeState);
  });

  it("CoA 6: applyTextures should assign floor and wall IDs", () => {
    // Create a simple structure: floor at y=1, wall above
    // Floor surface: solid at y=1 with air above (y=2)
    // Wall: solid at y=2 with solid above (y=3)
    for (let x = 1; x < 10; x++) {
      for (let z = 1; z < 10; z++) {
        grid.setCell(x, 0, z, 1); // Foundation
        grid.setCell(x, 1, z, 1); // Floor surface (will be textured as floor if air above)
        grid.setCell(x, 2, z, 0); // Air above floor (makes y=1 a floor surface)
        grid.setCell(x, 3, z, 1); // Wall (solid with solid above)
        grid.setCell(x, 4, z, 1); // Solid above wall
      }
    }

    generator.applyTextures();

    // Floor surfaces (y=1 with air above) should have IDs 200-209
    const floorId = grid.getCell(5, 1, 5);
    expect(floorId).to.be.greaterThanOrEqual(200);
    expect(floorId).to.be.lessThanOrEqual(209);

    // Walls (y=3 with solid above) should have IDs 100-109
    const wallId = grid.getCell(5, 3, 5);
    expect(wallId).to.be.greaterThanOrEqual(100);
    expect(wallId).to.be.lessThanOrEqual(109);
  });

  it("CoA 7: generate should scatter cover objects", () => {
    generator.generate(0.5, 2);

    // Check for cover objects (ID 10)
    let coverCount = 0;
    for (let x = 0; x < grid.size.x; x++) {
      for (let z = 0; z < grid.size.z; z++) {
        for (let y = 0; y < grid.size.y; y++) {
          if (grid.getCell(x, y, z) === 10) {
            coverCount++;
          }
        }
      }
    }

    // Should have some cover objects
    expect(coverCount).to.be.greaterThan(0);
  });

  it("CoA 8: generate with same seed should produce consistent results", () => {
    const grid1 = new VoxelGrid(20, 10, 20);
    const gen1 = new CaveGenerator(grid1, 12345);
    gen1.generate(0.5, 2);

    const grid2 = new VoxelGrid(20, 10, 20);
    const gen2 = new CaveGenerator(grid2, 12345);
    gen2.generate(0.5, 2);

    // Same seed should produce same results
    expect(grid1.cells).to.deep.equal(grid2.cells);
  });
});

