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

const root = resolve(new URL('..', import.meta.url).pathname)
const report = JSON.parse(await readFile(resolve(root, 'config/freecad-property-file-failure.json'), 'utf8'))
const fail = (message) => { throw new Error(`FreeCAD PropertyFile failure check failed: ${message}`) }
const same = (left, right) => JSON.stringify(left) === JSON.stringify(right)
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-file-failure' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail('baseline is invalid')
if (report.object?.typeId !== 'Mesh::Import' || report.property?.name !== 'FileName' || report.property?.typeId !== 'App::PropertyFile' || report.initial?.value !== '' || report.failures?.length !== 2) fail('failure fixture identity or cases changed')
const failures = new Map(report.failures.map((entry) => [entry.id, entry]))
for (const id of ['missing-path', 'wrong-type']) if (!failures.has(id)) fail(`missing failure case ${id}`)
const missing = failures.get('missing-path')
if (missing.assignmentException !== null || missing.recomputeException !== null || missing.after?.value !== '/definitely/missing/bitbybit-file.stl' || missing.after?.statusString !== 'File does not exist' || !same(missing.after?.objectState, ['Touched', 'Invalid']) || missing.objectsPreserved !== true || !same(missing.beforeObjects, missing.afterObjects)) fail('missing path did not enter the native invalid state without pollution')
const wrong = failures.get('wrong-type')
if (wrong.assignmentException?.type !== 'TypeError' || wrong.objectsPreserved !== true || !same(wrong.beforeObjects, wrong.afterObjects)) fail('wrong type did not reject without document pollution')
const disabled = report.disabled
if (disabled?.classification !== 'editor-read-only-and-python-immutable' || !disabled.status?.includes('Immutable') || disabled.exception?.type !== 'AttributeError' || disabled.exception.message !== "Object attribute 'FileName' is read-only" || !same(disabled.beforeObjects, disabled.afterObjects) || !same(disabled.restoredStatus, []) || !same(disabled.restoredEditorMode, [])) fail('disabled property state did not reject and restore cleanly')
const transaction = report.transaction
if (transaction?.undoMode !== 1 || transaction.pendingAfterEdit !== true || transaction.pendingAfterAbort !== false || transaction.activeAfterEdit?.name !== 'property-file-cancel' || !(transaction.activeAfterEdit.id > 0) || transaction.activeAfterAbort?.name !== '' || transaction.activeAfterAbort?.id !== 0 || transaction.before?.value !== '' || transaction.edited?.value !== '/tmp/transaction-file.stl' || transaction.afterAbort?.value !== '' || transaction.restored !== true || transaction.objectsRestored !== true) fail('transaction abort did not restore PropertyFile')
if (report.cancellationBoundary?.supported !== false || report.cancellationBoundary.classification !== 'synchronous-property-setter' || report.cancellationBoundary.reason !== 'no-native-cancel-hook' || report.cancellationBoundary.replacement !== 'abort-active-document-transaction') fail('cancellation boundary is not explicit')
if (report.documentIntegrity?.objectsPreserved !== true || report.documentIntegrity.objectCount !== 1 || !same(report.documentIntegrity.initialObjects, report.documentIntegrity.finalObjects)) fail('failure, disabled or cancellation cases polluted the document')
console.log(JSON.stringify({ status: 'freecad-property-file-failure-pass', failures: report.failures.map(({ id, after }) => ({ id, state: after.objectState, diagnostic: after.statusString })), disabled: { status: disabled.status, editorMode: disabled.editorMode, exception: disabled.exception }, transactionRestored: transaction.restored, documentObjectsPreserved: report.documentIntegrity.objectsPreserved, cancellationBoundary: report.cancellationBoundary }, null, 2))
