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

const root = resolve(new URL('..', import.meta.url).pathname)
const load = async (path) => JSON.parse(await readFile(resolve(root, path), 'utf8'))
const oracle = await load('config/freecad-partdesign-base-oracle.json')
if (oracle.schemaVersion !== 1 || oracle.baselineId !== 'freecad-1.1.1-partdesign-base-oracle' || oracle.freecadVersion !== '1.1.1' || oracle.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || oracle.status !== 'pass' || oracle.tolerance !== 1e-7) throw new Error('FreeCAD PartDesign base oracle baseline is invalid.')
if (oracle.summary?.cases !== 5 || oracle.summary?.passed !== 5) throw new Error('FreeCAD PartDesign base oracle summary is incomplete.')

const expectedVolumes = new Map([
  ['pad-tapered', 98.77344374611019],
  ['pocket-tapered', 810.4374375507407],
  ['pocket-through-all', 960],
  ['pocket-up-to-face', 960],
  ['pad-midplane', 96],
])
for (const [id, volume] of expectedVolumes) {
  const fixture = oracle.cases?.find((entry) => entry.id === id)
  if (!fixture || fixture.passed !== true || fixture.status !== 'Valid' || fixture.solids !== 1 || !Number.isFinite(fixture.volume) || Math.abs(fixture.volume - volume) > oracle.tolerance) throw new Error(`FreeCAD PartDesign base fixture ${id} is invalid.`)
}
const upToFace = oracle.cases.find((entry) => entry.id === 'pocket-up-to-face')
const midplane = oracle.cases.find((entry) => entry.id === 'pad-midplane')
if (!Number.isSafeInteger(upToFace.targetFace) || Math.abs(midplane.bounds.min[2] + 3) > oracle.tolerance || Math.abs(midplane.bounds.max[2] - 3) > oracle.tolerance) throw new Error('FreeCAD PartDesign termination bounds are invalid.')

const chrome = await load('config/chrome-geometry-features-verification.json')
if (chrome.status !== 'pass' || chrome.afterRelease?.shapeCount !== 0 || chrome.afterRelease?.kernelReferenceCount !== 0) throw new Error('Chrome PartDesign base geometry report is invalid.')
for (const [id] of expectedVolumes) {
  const nativeFixture = oracle.cases.find((entry) => entry.id === id)
  const browserFixture = chrome.operations?.find((entry) => entry.name === id)
  if (!browserFixture || Math.abs(browserFixture.volume - nativeFixture.volume) > oracle.tolerance) throw new Error(`Chrome ${id} geometry does not match the FreeCAD oracle.`)
}

const lifecycle = await load('config/chrome-partdesign-lifecycle-verification.json')
if (lifecycle.status !== 'pass' || lifecycle.initial?.length !== 42 || lifecycle.edited?.length !== 31 || lifecycle.edited?.recompute !== 'completed' || lifecycle.undone?.length !== 42 || lifecycle.undone?.recompute !== 'completed' || lifecycle.released?.shapeCount !== 0 || lifecycle.released?.kernelReferenceCount !== 0) throw new Error('Chrome PartDesign parameter-edit lifecycle evidence is invalid.')

const nativeHistoryPaths = new Map([
  ['pad', 'config/chrome-native-pad-history-verification.json'],
  ['pocket', 'config/chrome-native-pocket-history-verification.json'],
  ['revolution', 'config/chrome-native-revolution-history-verification.json'],
  ['groove', 'config/chrome-native-groove-history-verification.json'],
])
const nativeHistory = {}
for (const [operation, path] of nativeHistoryPaths) {
  const report = await load(path)
  const recordCount = report.execution?.recordCount ?? report.history?.recordCount
  const released = operation === 'pad' ? report.workerDisposed === true : report.afterRelease?.shapeCount === 0 && report.afterRelease?.kernelReferenceCount === 0
  if (report.status !== 'pass' || report.nativeCapabilities?.availability !== 'available' || !report.nativeCapabilities?.operations?.includes(operation) || !Number.isSafeInteger(recordCount) || recordCount < 1 || !released) throw new Error(`Chrome native ${operation} history evidence is invalid.`)
  nativeHistory[operation] = recordCount
}

console.log(JSON.stringify({ status: 'freecad-partdesign-base-oracle-pass', baselineId: oracle.baselineId, freecadVersion: oracle.freecadVersion, summary: oracle.summary, lifecycle: { initialLength: lifecycle.initial.length, editedLength: lifecycle.edited.length, undoneLength: lifecycle.undone.length }, nativeHistory }, null, 2))
