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-property-status-oracle.json'), 'utf8'))
const fail = (message) => { throw new Error(`FreeCAD Property status oracle: ${message}`) }
const byId = new Map((oracle.cases ?? []).map((entry) => [entry.id, entry]))
const changed = (id) => byId.get(id)?.changed

if (oracle.schemaVersion !== 2 || oracle.baselineId !== 'freecad-1.1.1-property-status-oracle' || oracle.freecadVersion !== '1.1.1' || oracle.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || oracle.status !== 'pass') fail('baseline is invalid.')
if (byId.size !== 5 || ['ordinary', 'runtime-output', 'type-output', 'runtime-no-recompute', 'type-no-recompute'].some((id) => !byId.has(id))) fail('change matrix is incomplete.')
if (changed('ordinary')?.documentTouched !== true || byId.get('ordinary')?.recomputeCount !== 1) fail('ordinary input change did not touch and recompute its owner.')
if (changed('runtime-output')?.mustExecute !== false || changed('runtime-output')?.documentTouched !== false) fail('runtime Output changed its owner recompute state.')
if (changed('type-output')?.mustExecute !== false || changed('type-output')?.documentTouched !== false) fail('Prop_Output changed its owner recompute state.')
if (changed('runtime-no-recompute')?.documentTouched !== true || byId.get('runtime-no-recompute')?.recomputeCount !== 1) fail('runtime NoRecompute no longer matches the locked implementation behavior.')
if (changed('type-no-recompute')?.documentTouched !== true || byId.get('type-no-recompute')?.recomputeCount !== 0) fail('Prop_NoRecompute did not touch without recomputing its owner.')
if (oracle.lockDynamic?.propertyStillPresent !== true || oracle.lockDynamic.renamedPropertyPresent !== false || oracle.lockDynamic.failures?.remove !== null || !oracle.lockDynamic.failures?.rename) fail('LockDynamic did not preserve FreeCAD remove-false/rename-error behavior.')
if (oracle.lockDynamic.mutableRenameAndRemove !== true || oracle.lockDynamic.undoAvailable !== true) fail('Dynamic property mutation is not transactionally undoable.')
const dynamicEvents = (oracle.lockDynamic.observerEvents ?? []).map((event) => `${event.type}:${event.property ?? event.name ?? ''}`)
if (dynamicEvents.join(',') !== 'property.added:MutableValue,transaction.opened:dynamic-property-mutation,property.before-change:MutableValue,property.changed:MutableValue,property.removed:RenamedValue,transaction.committed:') fail('Dynamic property observer/transaction order drifted.')
const partialTrigger = oracle.partialTrigger
if (partialTrigger?.reportedStatus?.join(',') !== 'PartialTrigger' || partialTrigger.value !== true || partialTrigger.recomputeCount !== 1 || partialTrigger.undoAvailable !== true || partialTrigger.state?.documentTouched !== false) fail('PartialTrigger native mutation behavior drifted.')
const partialEvents = (partialTrigger.observerEvents ?? []).map((event) => `${event.type}:${event.property ?? event.name ?? ''}`)
if (partialEvents.join(',') !== 'property.before-change:PartialLoad,transaction.opened:partial-trigger-mutation,property.changed:PartialLoad,property.changed:Shape,transaction.committed:') fail('PartialTrigger observer/transaction order drifted.')
const xml = oracle.fcstd?.xml
const reopened = oracle.fcstd?.reopened
if (xml?.persistedProperty !== true || xml.runtimeTransientProperty !== true || xml.typeTransientProperty !== true || xml.noPersistProperty !== false || xml.runtimeTransientHasValue !== false || xml.typeTransientHasValue !== false) fail('FCStd Property persistence partition drifted.')
if (JSON.stringify(reopened?.properties) !== JSON.stringify(['Persisted', 'RuntimeTransient', 'TypeTransient']) || reopened.values?.Persisted !== 11 || reopened.values.RuntimeTransient !== 0 || reopened.values.TypeTransient !== 0) fail('FCStd reopen did not restore persisted/transient defaults exactly.')
if (xml.floatConstraintNative !== true || xml.quantityConstraintNative !== true || xml.precisionNative !== true || xml.hiddenLinkNative !== true) fail('Native high-frequency App Property XML codecs drifted.')
if (reopened.codecValues?.FloatConstraint !== 0.25 || reopened.codecValues.QuantityConstraint !== 12.5 || reopened.codecValues.Precision !== 0.001 || reopened.codecValues.HiddenLink !== 'Target') fail('Native high-frequency App Property codecs did not reopen losslessly.')
console.log(JSON.stringify({ status: 'freecad-property-status-oracle-pass', cases: byId.size, outputSuppressesTouch: true, noRecomputePartition: true, lockDynamic: true, partialTrigger: true, observerTransactions: true, nativeCodecTypes: 4, fcstdRoundtrip: true }, null, 2))
