// Unit-Tests für die Wand-/Decken-Resolver (wallVerticalExtent /
// ceilingVerticalExtent): reine Datenschicht, kein React/Store.

import { describe, it, expect } from "vitest";
import { ceilingVerticalExtent } from "./wall";
import type { Ceiling, Project } from "./types";

/** Minimalprojekt mit einem Geschoss (baseElevation 0, floorHeight 2.6) und
 *  einem einschichtigen Wandtyp (0.2 m), den die Decke als Aufbau nutzt. */
function makeProject(overrides?: Partial<Project>): Project {
  return {
    id: "t",
    name: "T",
    lineStyles: [],
    hatches: [],
    components: [{ id: "c", name: "C", color: "#ccc", hatchId: "none", joinPriority: 10 }],
    wallTypes: [
      { id: "dt", name: "Decke", layers: [{ componentId: "c", thickness: 0.2 }] },
    ],
    drawingLevels: [
      {
        id: "eg",
        name: "EG",
        kind: "floor",
        visible: true,
        locked: false,
        floorHeight: 2.6,
        cutHeight: 1.0,
        baseElevation: 0,
      },
      {
        id: "og",
        name: "OG",
        kind: "floor",
        visible: true,
        locked: false,
        floorHeight: 2.6,
        cutHeight: 1.0,
        baseElevation: 2.8,
      },
    ],
    layers: [{ code: "30", name: "Decken", color: "#0a0a0a", lw: 0.5, visible: true, locked: false }],
    walls: [],
    doors: [],
    openings: [],
    ceilings: [],
    stairs: [],
    rooms: [],
    drawings2d: [],
    context: [],
    ...overrides,
  };
}

function makeCeiling(overrides?: Partial<Ceiling>): Ceiling {
  return {
    id: "cl1",
    type: "ceiling",
    floorId: "eg",
    categoryCode: "30",
    outline: [
      { x: 0, y: 0 },
      { x: 4, y: 0 },
      { x: 4, y: 4 },
      { x: 0, y: 4 },
    ],
    wallTypeId: "dt",
    ...overrides,
  };
}

describe("ceilingVerticalExtent", () => {
  it("ohne top/bottom: OK = Geschoss-Oberkante, UK = OK − Dicke (heutiges Verhalten)", () => {
    const project = makeProject();
    const ceiling = makeCeiling();
    const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
    expect(zTop).toBeCloseTo(2.6); // baseElevation(0) + floorHeight(2.6)
    expect(zBottom).toBeCloseTo(2.4); // zTop − thickness(0.2)
  });

  it("mit top: custom übersteuert die Oberkante; UK bleibt OK − Dicke", () => {
    const project = makeProject();
    const ceiling = makeCeiling({ top: { mode: "custom", z: 3.0 } });
    const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
    expect(zTop).toBeCloseTo(3.0);
    expect(zBottom).toBeCloseTo(2.8);
  });

  it("mit bottom: custom übersteuert die Unterkante — gewinnt über OK − Dicke", () => {
    const project = makeProject();
    const ceiling = makeCeiling({ bottom: { mode: "custom", z: 2.2 } });
    const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
    expect(zTop).toBeCloseTo(2.6); // OK unverändert (Geschoss-Default)
    expect(zBottom).toBeCloseTo(2.2); // UK-Override statt OK − Dicke (2.4)
  });

  it("mit top UND bottom: beide Overrides wirken unabhängig (Dicke wird ignoriert)", () => {
    const project = makeProject();
    const ceiling = makeCeiling({
      top: { mode: "custom", z: 5.0 },
      bottom: { mode: "custom", z: 4.5 },
    });
    const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
    expect(zTop).toBeCloseTo(5.0);
    expect(zBottom).toBeCloseTo(4.5);
  });

  it("bottom: floor bindet die Unterkante an ein Geschoss (+ optionalem offset)", () => {
    const project = makeProject();
    const ceiling = makeCeiling({ bottom: { mode: "floor", floorId: "og", offset: 0.1 } });
    const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
    expect(zTop).toBeCloseTo(2.6);
    expect(zBottom).toBeCloseTo(2.9); // baseElevation(og)=2.8 + offset(0.1)
  });
});
