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 lifecycle = await load('config/chrome-partdesign-lifecycle-verification.json')
const referenceLifecycle = await load('config/chrome-partdesign-reference-lifecycle-verification.json')
const loft = await load('config/chrome-partdesign-loft-verification.json')
const transform = await load('config/chrome-partdesign-transform-verification.json')
const base = await load('config/chrome-geometry-features-verification.json')

if ([lifecycle, referenceLifecycle, loft, transform, base].some((report) => report.status !== 'pass')) throw new Error('PartDesign closure requires passing lifecycle, external reference, base, loft and transform browser reports.')
const lifecycleStages = [lifecycle.initial, lifecycle.edited, lifecycle.undone, lifecycle.reopened]
if (new Set(lifecycleStages.map((stage) => stage?.shapeId)).size !== lifecycleStages.length || lifecycleStages.some((stage) => !stage?.shapeId || !(stage.volume > 0) || stage.solids !== 1 || stage.tip !== 'pad' || stage.support !== 'XY_Plane') || lifecycle.edited.length !== 31 || lifecycle.undone.length !== 42 || lifecycle.reopened.length !== 42 || Math.abs(lifecycle.initial.volume - 504) > 1e-7 || Math.abs(lifecycle.edited.volume - 372) > 1e-7 || Math.abs(lifecycle.undone.volume - 504) > 1e-7 || Math.abs(lifecycle.reopened.volume - 504) > 1e-7) throw new Error('PartDesign edit/Undo/load lifecycle contains stale Shape, Tip or Support evidence.')
if (lifecycle.structural?.reorderRejected !== true || lifecycle.structural?.dependencyRemovalRejected !== true || lifecycle.structural?.deleted?.tip !== 'pocket' || lifecycle.structural?.deletionUndone?.tip !== 'fillet' || lifecycle.structural?.deletionRedone?.tip !== 'pocket' || lifecycle.structural?.restoredTip !== 'fillet') throw new Error('PartDesign structural Undo/Redo and Tip evidence is invalid.')
if (referenceLifecycle.initial?.properties?.XLinkList?.length !== 2 || referenceLifecycle.initial?.properties?.XLinkSubList?.length !== 2 || referenceLifecycle.closed?.binder?.cacheState !== 'cached' || referenceLifecycle.missing?.source?.status !== 'missing' || referenceLifecycle.relinkedAfterMissing?.binder?.cacheState !== 'linked' || referenceLifecycle.edited?.binder?.area !== 54 || referenceLifecycle.undone?.binder?.area !== 30 || referenceLifecycle.redone?.binder?.area !== 54 || referenceLifecycle.reopenedUndo?.binder?.area !== 30 || referenceLifecycle.reopenedRedo?.binder?.area !== 54) throw new Error('PartDesign external reference close, relink, edit, Undo/Redo or OPFS evidence is invalid.')

const expectedLoft = ['additive-loft', 'additive-pipe', 'subtractive-loft', 'subtractive-pipe']
if (JSON.stringify(loft.operations?.map((entry) => entry.command)) !== JSON.stringify(expectedLoft) || loft.operations.some((entry) => entry.tip !== entry.objectId || !entry.base || !entry.shapeId || !(entry.volume > 0)) || new Set(loft.operations.map((entry) => entry.shapeId)).size !== loft.operations.length) throw new Error('PartDesign Loft/Pipe create and Tip/Base evidence is invalid.')
for (const recovery of [loft.failureRecovery?.loft, loft.failureRecovery?.pipe]) {
  if (recovery?.status !== 'failed' || recovery.retainedShapeId !== recovery.previousShapeId || recovery.restoredStatus !== 'completed' || !recovery.restoredShapeId || recovery.restoredShapeId === recovery.previousShapeId) throw new Error('PartDesign Loft/Pipe failure recovery retained stale or missing Shape evidence.')
}

const expectedTransform = ['hole', 'fillet', 'chamfer', 'draft', 'thickness', 'hole', 'hole', 'linear-pattern', 'mirrored', 'mirrored', 'linear-pattern', 'polar-pattern', 'multi-transform', 'hole']
if (JSON.stringify(transform.operations?.map((entry) => entry.command)) !== JSON.stringify(expectedTransform) || transform.operations.some((entry) => entry.tip !== entry.objectId || !entry.base || !entry.shapeId || !(entry.volume > 0) || entry.solids !== 1) || new Set(transform.operations.map((entry) => entry.shapeId)).size !== transform.operations.length) throw new Error('PartDesign dress-up/transform/Hole create and Tip/Base evidence is invalid.')
const ambiguity = transform.ambiguityRecovery
if (ambiguity?.status !== 'failed' || ambiguity.retainedShapeId !== ambiguity.previousShapeId || ambiguity.restoredStatus !== 'completed' || !ambiguity.restoredShapeId || ambiguity.restoredShapeId === ambiguity.previousShapeId || transform.topologyMigration?.wrongBindings !== 0) throw new Error('PartDesign topology failure recovery retained stale or incorrectly rebound Shape evidence.')

const baseModes = ['pad-tapered', 'pocket-tapered', 'pocket-through-all', 'pocket-up-to-face', 'pad-midplane']
if (baseModes.some((name) => !base.operations?.some((entry) => entry.name === name && entry.shapeId && entry.volume > 0))) throw new Error('PartDesign base mode creation evidence is incomplete.')
if (loft.persistence?.mode !== 'sqlite-opfs' || transform.persistence?.mode !== 'sqlite-opfs' || lifecycle.reopened?.persistenceMode !== 'sqlite-opfs' || loft.persistence.reopenedTip !== 'subtractive-pipe' || transform.persistence.reopenedTip !== transform.operations.at(-1).objectId || lifecycle.reopened.tip !== 'pad') throw new Error('PartDesign save/load Tip evidence is invalid.')
if (loft.afterRelease?.shapeCount !== 0 || loft.afterRelease?.kernelReferenceCount !== 0 || transform.afterRelease?.shapeCount !== 0 || transform.afterRelease?.kernelReferenceCount !== 0 || lifecycle.released?.shapeCount !== 0 || lifecycle.released?.kernelReferenceCount !== 0 || referenceLifecycle.released?.shapeCount !== 0 || referenceLifecycle.released?.kernelReferenceCount !== 0 || base.afterRelease?.shapeCount !== 0 || base.afterRelease?.kernelReferenceCount !== 0) throw new Error('PartDesign closure reports leaked Shape ownership.')

const historyPaths = new Map([
  ['pad', 'config/chrome-native-pad-history-verification.json'],
  ['pocket', 'config/chrome-native-pocket-history-verification.json'],
  ['loft', 'config/chrome-native-loft-history-verification.json'],
  ['pipe', 'config/chrome-native-pipe-history-verification.json'],
  ['revolution', 'config/chrome-native-revolution-history-verification.json'],
  ['groove', 'config/chrome-native-groove-history-verification.json'],
  ['fillet', 'config/chrome-native-fillet-history-verification.json'],
  ['chamfer', 'config/chrome-native-chamfer-history-verification.json'],
  ['hole', 'config/chrome-native-hole-history-verification.json'],
  ['draft', 'config/chrome-native-draft-history-verification.json'],
  ['thickness', 'config/chrome-native-thickness-history-verification.json'],
  ['linear-pattern', 'config/chrome-native-linear-pattern-history-verification.json'],
  ['polar-pattern', 'config/chrome-native-polar-pattern-history-verification.json'],
  ['mirrored', 'config/chrome-native-mirrored-history-verification.json'],
  ['multi-transform', 'config/chrome-native-multi-transform-history-verification.json'],
])
const nativeHistory = {}
for (const [operation, path] of historyPaths) {
  const report = await load(path)
  const count = 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?.operations?.includes(operation) !== true || !Number.isSafeInteger(count) || count < 1 || !released) throw new Error(`PartDesign native ${operation} history evidence is invalid.`)
  nativeHistory[operation] = count
}

console.log(JSON.stringify({ status: 'partdesign-closure-pass', lifecycle: lifecycleStages.map((stage) => ({ length: stage.length, shapeId: stage.shapeId, volume: stage.volume, tip: stage.tip, support: stage.support })), externalReferences: { propertyKinds: Object.keys(referenceLifecycle.initial.properties), sourceCloseRelink: true, missingSourceRelink: true, opfsUndoRedo: true }, createdFeatures: { loft: expectedLoft, transform: expectedTransform, baseModes }, failureRecovery: { loft: loft.failureRecovery, transform: transform.ambiguityRecovery }, persistence: { lifecycle: lifecycle.reopened, references: referenceLifecycle.reopened, loft: loft.persistence, transform: transform.persistence }, nativeHistory }, null, 2))
