import { expect, test } from "bun:test"
import type { Texture } from "../engine/render/Texture"
import { buildLevel } from "../game/level"
import type { Textures } from "../game/textures"

const texture: Texture = { width: 1, height: 1, data: new Uint32Array([0xFFFFFFFF]) }
const textures: Textures = {
  floor: texture,
  grass: texture,
  bark: texture,
  birch: texture,
  leaf: texture,
  needle: texture,
  rock: texture,
  flower: texture,
  wall: texture,
  crate: texture,
  npc: texture,
  frog: texture,
  bee: texture,
  robin: texture,
  skybox: texture,
}

test("game data compiles into a clone-safe engine render scene", () => {
  const level = buildLevel(textures)
  expect(level.actors).toHaveLength(60)
  expect(Object.isFrozen(level.actors)).toBe(true)
  expect(Object.isFrozen(level.render)).toBe(true)
  expect(Object.isFrozen(level.render.prototypes)).toBe(true)
  expect(level.render.prototypes).toHaveLength(3)
  expect(level.render.maxInstances).toBe(level.actors.length)
  expect(() => structuredClone(level.render)).not.toThrow()
})

test("actor prototype bounds cover local geometry", () => {
  const level = buildLevel(textures)
  for (const prototype of level.render.prototypes) {
    let covered = true
    for (const group of prototype.groups) {
      const vertices = group.mesh.verts
      for (let i = 0; i < vertices.length; i += 5) {
        covered &&=
          Math.abs(vertices[i]) <= prototype.radius + 1e-6 &&
          vertices[i + 1] >= prototype.minY - 1e-6 &&
          vertices[i + 1] <= prototype.maxY + 1e-6 &&
          Math.abs(vertices[i + 2]) <= prototype.radius + 1e-6
      }
    }
    expect(covered).toBe(true)
  }
})

test("chunk bounds cover geometry in every LOD", () => {
  const level = buildLevel(textures)
  for (const chunk of level.render.chunks) {
    let covered = true
    for (const group of [...chunk.near, ...chunk.far]) {
      const vertices = group.mesh.verts
      for (let i = 0; i < vertices.length; i += 5) {
        covered &&=
          vertices[i] >= chunk.minX &&
          vertices[i] <= chunk.maxX &&
          vertices[i + 1] >= chunk.minY &&
          vertices[i + 1] <= chunk.maxY &&
          vertices[i + 2] >= chunk.minZ &&
          vertices[i + 2] <= chunk.maxZ
      }
    }
    expect(covered).toBe(true)
  }
})
