import { isDeepStrictEqual } from 'node:util'
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-fileincluded-roundtrip.json'), 'utf8'))
const fail = (message) => { throw new Error(`FreeCAD PropertyFileIncluded roundtrip check failed: ${message}`) }
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-fileincluded-roundtrip' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.propertyType !== 'App::PropertyFileIncluded') fail('baseline is invalid')
const objectSet = [{ name: 'IncludedProbe', typeId: 'App::DocumentObjectFileIncluded' }]
for (const [phase, snapshot] of [['nativeInitial', report.nativeInitial], ['nativeReopened', report.nativeAfter?.reopened], ['nativeResaved', report.nativeAfter?.resaved]]) {
  const object = snapshot?.object
  if (object?.name !== 'IncludedProbe' || object.typeId !== 'App::DocumentObjectFileIncluded' || object.propertyTypeId !== 'App::PropertyFileIncluded' || object.baseName !== 'payload.bin' || object.exists !== true || !Number.isSafeInteger(object.bytes) || object.bytes <= 0 || !/^[0-9a-f]{64}$/.test(object.sha256) || object.writeBits !== 0 || object.underTransientDir !== true || !isDeepStrictEqual(object.propertyStatus, []) || !isDeepStrictEqual(object.editorMode, []) || !isDeepStrictEqual(object.state, ['Up-to-date']) || object.statusString !== 'Valid' || object.hasShapeProperty !== false || !isDeepStrictEqual(snapshot.objectSet, objectSet)) fail(`${phase} native object semantics are incomplete`)
}
if (report.nativeInitial.object.sha256 !== report.assets?.initial?.sha256 || report.nativeAfter.reopened.object.sha256 !== report.assets?.target?.sha256 || report.nativeAfter.resaved.object.sha256 !== report.assets?.target?.sha256) fail('native transient bytes do not match the locked assets')
const before = report.web?.before
const after = report.web?.after
if (before?.typeId !== 'App::PropertyFileIncluded' || before.element !== 'FileIncluded' || before.resourcePath !== 'payload.bin' || before.includedFileResource?.byteLength !== report.assets.initial.bytes || after?.typeId !== 'App::PropertyFileIncluded' || after.element !== 'FileIncluded' || after.resourcePath !== 'payload.bin' || after.includedFileResource?.byteLength !== report.assets.target.bytes) fail('Web property summaries are incomplete')
const resource = report.web.resource
if (resource?.path !== 'payload.bin' || resource.pathPreserved !== true || resource.beforeBytes !== report.assets.initial.bytes || resource.afterBytes !== report.assets.target.bytes || resource.beforeSha256 !== report.assets.initial.sha256 || resource.afterSha256 !== report.assets.target.sha256 || resource.changed !== true || report.web.targetMarkedTouched !== true || report.web.webOutputMatches !== true || report.web.semanticObjectsPreserved !== true || report.web.opaqueEntriesPreserved !== true || report.web.opaquePathsPreserved !== 0) fail('Web edit did not preserve native archive semantics')
if (report.nativeResavedResource?.path !== 'payload.bin' || report.nativeResavedResource.byteLength !== report.assets.target.bytes) fail('native resave did not retain the embedded resource')
const classification = report.classification
if (classification?.archiveName !== 'payload.bin' || classification.initialSha256 !== report.assets.initial.sha256 || classification.targetSha256 !== report.assets.target.sha256 || classification.reopenedSha256 !== report.assets.target.sha256 || classification.resavedSha256 !== report.assets.target.sha256 || classification.nativeOutputMatches !== true || classification.objectSetPreserved !== true || classification.resavedResourceMatches !== true || classification.externalResourceBoundary !== 'embedded FCStd ZIP entry restored to a read-only document transient file' || classification.unknownSemanticDrift !== false || classification.zeroUnknownDrift !== true) fail('round-trip classification is not exact for PropertyFileIncluded')
for (const artifact of [...Object.values(report.assets ?? {}), ...Object.values(report.archives ?? {})]) if (!artifact?.path || !Number.isSafeInteger(artifact.bytes) || artifact.bytes <= 0 || !/^[0-9a-f]{64}$/.test(artifact.sha256)) fail('asset or archive evidence is incomplete')
console.log(JSON.stringify({ status: 'freecad-property-fileincluded-roundtrip-pass', hashes: { initial: classification.initialSha256, reopened: classification.reopenedSha256, resaved: classification.resavedSha256 }, resource, opaquePathsPreserved: report.web.opaquePathsPreserved, zeroUnknownDrift: classification.zeroUnknownDrift }, null, 2))
