import test from "node:test";
import assert from "node:assert/strict";
import { validateModel } from "../src/validate.js";

test("validate normalizes dense symbol pin spacing and body size deterministically", () => {
  const model = {
    meta: { title: "Dense symbol test" },
    symbols: {
      dense: {
        symbol_id: "dense",
        category: "generic",
        body: { width: 80, height: 40 },
        pins: [
          { name: "A", number: "1", side: "left", offset: 4, type: "input" },
          { name: "B", number: "2", side: "left", offset: 6, type: "input" },
          { name: "Y", number: "3", side: "right", offset: 5, type: "output" },
          { name: "Z", number: "4", side: "right", offset: 7, type: "output" }
        ]
      }
    },
    instances: [{ ref: "U1", symbol: "dense", placement: { x: 100, y: 100, rotation: 0, locked: false } }],
    nets: [
      {
        name: "N1",
        class: "signal",
        nodes: [
          { ref: "U1", pin: "A" },
          { ref: "U1", pin: "Y" }
        ]
      },
      {
        name: "N2",
        class: "signal",
        nodes: [
          { ref: "U1", pin: "B" },
          { ref: "U1", pin: "Z" }
        ]
      }
    ]
  };

  const first = validateModel(model);
  assert.ok(first.model);
  const dense = first.model.symbols.dense;
  assert.ok(dense.body.width >= 96);
  assert.ok(dense.body.height >= 64);

  const leftPins = dense.pins.filter((pin) => pin.side === "left");
  const rightPins = dense.pins.filter((pin) => pin.side === "right");
  assert.ok(leftPins[1].offset - leftPins[0].offset >= 18);
  assert.ok(rightPins[1].offset - rightPins[0].offset >= 18);

  assert.ok(first.issues.some((issue) => issue.code === "symbol_geometry_adjusted"));

  const second = validateModel(first.model);
  assert.ok(second.model);
  assert.deepEqual(second.model.symbols.dense, first.model.symbols.dense);
});

test("validate applies adaptive pin pitch for crowded symbol sides", () => {
  const model = {
    meta: { title: "Crowded side symbol" },
    symbols: {
      crowded: {
        symbol_id: "crowded",
        category: "generic",
        body: { width: 100, height: 80 },
        pins: [
          { name: "A0", number: "1", side: "left", offset: 8, type: "input" },
          { name: "A1", number: "2", side: "left", offset: 10, type: "input" },
          { name: "A2", number: "3", side: "left", offset: 12, type: "input" },
          { name: "A3", number: "4", side: "left", offset: 14, type: "input" },
          { name: "A4", number: "5", side: "left", offset: 16, type: "input" },
          { name: "A5", number: "6", side: "left", offset: 18, type: "input" },
          { name: "Y", number: "7", side: "right", offset: 12, type: "output" }
        ]
      }
    },
    instances: [{ ref: "U1", symbol: "crowded", placement: { x: 40, y: 40, rotation: 0, locked: false } }],
    nets: [],
    constraints: {},
    annotations: []
  };

  const result = validateModel(model);
  const sym = result.model?.symbols?.crowded;
  assert.ok(sym);
  const left = sym.pins.filter((pin) => pin.side === "left");
  assert.ok(left[1].offset - left[0].offset >= 22);
  assert.ok(sym.body.width >= 96);
  assert.ok(sym.body.height >= 180);
  assert.ok(result.issues.some((issue) => issue.code === "symbol_geometry_adjusted"));
});
