import { readFile } from 'node:fs/promises'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
const oracle = JSON.parse(await readFile(resolve(root, 'config/freecad-attachment-combination-oracle.json'), 'utf8'))
const fail = (message) => { throw new Error(`FreeCAD attachment combination oracle: ${message}`) }
const same = (actual, expected) => JSON.stringify(actual) === JSON.stringify(expected)
const near = (actual, expected) => typeof actual === 'number' && Math.abs(actual - expected) <= oracle.tolerance
const valid = (state, mode) => state?.mapMode === mode && state.finitePlacement === true && same(state.state, ['Up-to-date']) && state.status === 'Valid' && state.positionBySupport === true && state.suggestionMessage === 'OK' && state.suggestedModes?.includes(mode)

if (oracle.schemaVersion !== 1 || oracle.baselineId !== 'freecad-1.1.1-attachment-combination-oracle' || oracle.freecadVersion !== '1.1.1' || oracle.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || oracle.status !== 'pass' || oracle.tolerance !== 1e-7) fail('baseline is invalid.')
const expectedEngineCounts = { plane: 85, line: 44, point: 22, sketch: 85 }
if (oracle.caseCount !== 236 || Object.entries(expectedEngineCounts).some(([engine, count]) => oracle.engineCaseCounts?.[engine] !== count) || Object.keys(oracle.engineCaseCounts ?? {}).length !== 4 || oracle.cases?.length !== oracle.caseCount) fail('the implemented engine/reference combination census is incomplete.')
if (!same(oracle.translation, [1.25, -0.75, 2])) fail('source mutation vector changed.')

const identities = new Set()
for (const entry of oracle.cases) {
  const identity = `${entry.engine}\0${entry.mode}\0${entry.combinationIndex}`
  if (identities.has(identity)) fail(`duplicate case ${entry.id}.`)
  identities.add(identity)
  if (!Array.isArray(entry.referenceCombination) || entry.referenceCombination.length === 0 || entry.referenceCombination.some((value) => typeof value !== 'string' || !value)) fail(`${entry.id} has no executable reference combination.`)
  if (!valid(entry.initial, entry.mode)) fail(`${entry.id} initial execution is invalid: ${entry.initial?.status}`)
  if (!valid(entry.mutated, entry.mode)) fail(`${entry.id} source mutation is invalid: ${entry.mutated?.status}`)
  if (!valid(entry.roundtrip, entry.mode)) fail(`${entry.id} FCStd round-trip is invalid: ${entry.roundtrip?.status}`)
  if (!same(entry.initial.support, entry.mutated.support) || !same(entry.mutated.support, entry.roundtrip.support)) fail(`${entry.id} support references drifted.`)
  for (let index = 0; index < 3; index += 1) {
    const initial = entry.initial.placement.position[index]
    const mutated = entry.mutated.placement.position[index]
    if (!near(mutated - initial, oracle.translation[index])) fail(`${entry.id} did not follow the source translation on axis ${index}.`)
    if (!near(entry.roundtrip.placement.position[index], mutated)) fail(`${entry.id} placement drifted after FCStd reopen on axis ${index}.`)
  }
  for (let index = 0; index < 3; index += 1) if (!near(entry.roundtrip.placement.axis[index], entry.mutated.placement.axis[index])) fail(`${entry.id} rotation axis drifted after FCStd reopen.`)
  if (!near(entry.roundtrip.placement.angleDegrees, entry.mutated.placement.angleDegrees)) fail(`${entry.id} rotation angle drifted after FCStd reopen.`)
}

console.log(JSON.stringify({ status: 'freecad-attachment-combination-oracle-pass', baselineId: oracle.baselineId, cases: oracle.caseCount, engines: oracle.engineCaseCounts, allImplementedModes: true, allReferenceCombinations: true, sourceMutation: oracle.translation, fcstdRoundtrip: true }, null, 2))
