import assert from 'node:assert/strict'
import test from 'node:test'
import { createDraftDocument } from '../src/facade/draft'

test('Draft working plane, grid and parametric geometry are deterministic', () => {
  const draft = createDraftDocument()
  draft.setWorkingPlane({ origin: { x: 10, y: 20, z: 30 }, xAxis: { x: 0, y: 1, z: 0 }, yAxis: { x: 0, y: 0, z: 1 } })
  draft.setGrid(0.5)
  assert.deepEqual(draft.snap({ x: 1.24, y: 2.26 }), { x: 1, y: 2.5 })
  assert.deepEqual(draft.mapToWorld({ x: 2, y: 3 }), { x: 10, y: 22, z: 33 })
  draft.createLine('line', { x: 0, y: 0 }, { x: 4, y: 0 })
  draft.createWire('wire', [{ x: 0, y: 0 }, { x: 2, y: 0 }, { x: 2, y: 2 }])
  draft.createCircle('circle', { x: 1, y: 1 }, 2)
  assert.equal(draft.snapshot().objects.length, 3)
})

test('Draft operations preserve clone and array source dependencies', () => {
  const draft = createDraftDocument()
  draft.addLayer({ id: 'construction', label: 'Construction', visible: true, color: '#007f86' })
  draft.createLine('line', { x: 0, y: 0 }, { x: 4, y: 0 })
  draft.move('line', { x: 1, y: 2 })
  draft.rotate('line', 90, { x: 1, y: 2 })
  draft.scale('line', 2, { x: 1, y: 2 })
  const offset = draft.offsetLine('line', 1, 'offset')
  assert.equal(Math.round(Math.hypot(offset.start.x - 1, offset.start.y - 2)), 1)
  const trimmed = draft.trimLine('line', 0.25, 0.75)
  assert.equal(Math.hypot(trimmed.end.x - trimmed.start.x, trimmed.end.y - trimmed.start.y), 4)
  const clone = draft.clone('line', 'clone', { x: 10, y: 0 })
  const array = draft.array('line', { columns: 2, rows: 2, columnSpacing: 5, rowSpacing: 7, idPrefix: 'array' })
  assert.equal(clone.sourceId, 'line')
  assert.equal(array.length, 4)
  assert.equal(array.every((entry) => entry.sourceId === 'line'), true)
  assert.equal(draft.assignLayer('clone', 'construction').layerId, 'construction')
})

test('Draft rejects invalid planes, geometry, layers and arrays', () => {
  const draft = createDraftDocument()
  assert.throws(() => draft.setWorkingPlane({ origin: { x: 0, y: 0, z: 0 }, xAxis: { x: 2, y: 0, z: 0 }, yAxis: { x: 0, y: 1, z: 0 } }), /normalized/)
  assert.throws(() => draft.createLine('line', { x: 0, y: 0 }, { x: 0, y: 0 }), /non-zero/)
  draft.createCircle('circle', { x: 0, y: 0 }, 1)
  assert.throws(() => draft.offsetLine('circle', 1, 'offset'), /line objects only/)
  assert.throws(() => draft.trimLine('circle', 0.25, 0.75), /line objects only/)
  draft.createLine('line', { x: 0, y: 0 }, { x: 4, y: 0 })
  assert.throws(() => draft.trimLine('line', 0.75, 0.25), /0 <= start < end <= 1/)
  assert.throws(() => draft.array('circle', { columns: 1001, rows: 1, columnSpacing: 1, rowSpacing: 1, idPrefix: 'many' }), /between 1 and 1000/)
})
