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

const root = resolve(new URL('..', import.meta.url).pathname)
const load = (path) => readFile(resolve(root, path), 'utf8').then(JSON.parse)
const fail = (message) => { throw new Error(`FreeCAD TSN stage evidence: ${message}`) }

const requiredOperations = ['fuse', 'cut', 'common', 'rotate', 'pad', 'pocket', 'loft', 'pipe', 'revolution', 'groove', 'fillet', 'chamfer', 'hole', 'draft', 'thickness', 'linear-pattern', 'polar-pattern', 'mirrored', 'multi-transform']
const reportSpecs = {
  'chrome-native-history-verification.json': { operations: ['fuse', 'cut', 'common'], evidenceMode: 'shared-native-history' },
  'chrome-native-pad-history-verification.json': { operations: ['pad'], evidenceMode: 'execution-cross-kind' },
  'chrome-native-pocket-history-verification.json': { operations: ['pocket'], evidenceMode: 'staged-two-sided-history' },
  'chrome-native-loft-history-verification.json': { operations: ['loft'], marker: ['loft'], evidenceMode: 'native-history-report' },
  'chrome-native-pipe-history-verification.json': { operations: ['pipe'], marker: ['pipe'], evidenceMode: 'native-history-report' },
  'chrome-native-revolution-history-verification.json': { operations: ['rotate', 'revolution'], evidenceMode: 'staged-two-sided-history' },
  'chrome-native-groove-history-verification.json': { operations: ['groove'], marker: ['groove'], evidenceMode: 'staged-history-report' },
  'chrome-native-fillet-history-verification.json': { operations: ['fillet'], marker: ['fillet'], evidenceMode: 'native-history-report' },
  'chrome-native-chamfer-history-verification.json': { operations: ['chamfer'], marker: ['chamfer'], evidenceMode: 'native-history-report' },
  'chrome-native-hole-history-verification.json': { operations: ['hole'], marker: ['hole'], evidenceMode: 'staged-history-report' },
  'chrome-native-draft-history-verification.json': { operations: ['draft'], marker: ['draft'], evidenceMode: 'native-history-report' },
  'chrome-native-thickness-history-verification.json': { operations: ['thickness'], marker: ['thickness'], evidenceMode: 'native-history-report' },
  'chrome-native-linear-pattern-history-verification.json': { operations: ['linear-pattern'], marker: ['linear-pattern'], evidenceMode: 'native-history-report' },
  'chrome-native-polar-pattern-history-verification.json': { operations: ['polar-pattern'], marker: ['polar-pattern'], evidenceMode: 'native-history-report' },
  'chrome-native-mirrored-history-verification.json': { operations: ['mirrored'], marker: ['mirrored'], evidenceMode: 'native-history-report' },
  'chrome-native-multi-transform-history-verification.json': { operations: ['multi-transform'], marker: ['multi-transform'], evidenceMode: 'staged-history-report' },
}

const reports = Object.fromEntries(await Promise.all(Object.entries(reportSpecs).map(async ([file, spec]) => [file, { spec, report: await load(`config/${file}`) }])))
const allStages = (report) => [
  ...(report.history?.stages ?? []),
  ...(report.twoSidedHistory?.stages ?? []),
  ...(report.twoAngleHistory?.stages ?? []),
]
const markerOperations = (report) => {
  const opfs = report.opfs ?? {}
  const payload = opfs.markerPayload?.operation
  return [opfs.markerOperation, opfs.markerSuite, payload].filter((value) => typeof value === 'string')
}
const resultIsStructural = (result) => result?.structuralValid === true || result?.nativeStructuralValid === true || result?.bitbybitStructuralValid === true
const resultSolids = (result) => result?.solids ?? result?.nativeSolids ?? result?.bitbybitSolids
const stageEvidence = []
const capturedOperations = new Set()
const operationEvidence = {}

for (const [file, { spec, report }] of Object.entries(reports)) {
  if (report.schemaVersion !== 1 || report.status !== 'pass') fail(`${file} is not a passing schema-v1 report.`)
  if (report.nativeCapabilities?.availability !== 'available' || report.nativeCapabilities.providerId !== 'occt-native.history-step' || report.nativeCapabilities.transport !== 'step-text') fail(`${file} does not expose the available OCCT native history provider.`)
  if (report.capabilities && (report.capabilities.status !== 'ready' || report.capabilities.worker !== true || report.capabilities.wasm !== true)) fail(`${file} does not expose a ready browser worker/WASM capability.`)
  if (report.afterRelease && (report.afterRelease.shapeCount !== 0 || report.afterRelease.kernelReferenceCount !== 0)) fail(`${file} leaked native resources.`)
  if (!report.afterRelease && report.workerDisposed !== true) fail(`${file} has no native resource release proof.`)
  const history = report.history ?? {}
  const recordCount = report.execution?.recordCount ?? history.recordCount
  if (!Number.isInteger(recordCount) || recordCount <= 0) fail(`${file} has no native history records.`)
  const relationCount = Object.values(history.relations ?? {}).reduce((sum, value) => sum + (Number.isInteger(value) ? value : 0), 0) + Object.values(report.execution?.relations ?? {}).reduce((sum, value) => sum + (Number.isInteger(value) ? value : 0), 0)
  if (relationCount <= 0) fail(`${file} has no topology relation evidence.`)
  if (report.result && resultSolids(report.result) !== undefined && resultSolids(report.result) <= 0) fail(`${file} did not produce a solid result.`)
  if (report.result && report.result.structuralErrors !== undefined && report.result.structuralErrors !== 0) fail(`${file} reported structural errors.`)
  if (spec.marker) {
    if (report.opfs?.markerRemoved !== true || !spec.marker.some((marker) => markerOperations(report).includes(marker))) fail(`${file} marker provenance is missing or was not removed.`)
  }
  if (file === 'chrome-native-pad-history-verification.json') {
    if (report.execution.crossKindRecords <= 0 || report.execution.profileKinds?.slice().sort().join(',') !== 'edge,face,vertex' || report.execution.summary?.isValid !== true || report.execution.summary?.solids !== 1 || report.workerDisposed !== true) fail('Pad cross-kind execution/topology evidence is incomplete.')
  }
  for (const operation of spec.operations) {
    if (!report.nativeCapabilities.operations?.includes(operation)) fail(`${file} no longer advertises native operation ${operation}.`)
    capturedOperations.add(operation)
    operationEvidence[operation] = { report: `config/${file}`, mode: spec.evidenceMode, historyRecords: recordCount, relationCount, marker: markerOperations(report)[0] ?? null }
  }
  for (const stage of allStages(report)) {
    if (!stage.stageId || typeof stage.operation !== 'string' || !stage.resultObjectId || stage.topologyEntries <= 0 || !Array.isArray(stage.inputObjectIds) || !Number.isInteger(stage.recordCount) || stage.recordCount < 0 || (stage.operation !== 'hole' && stage.inputObjectIds.length === 0) || (stage.operation !== 'hole' && stage.recordCount <= 0)) fail(`${file} contains an incomplete native stage capture.`)
    stageEvidence.push({ report: `config/${file}`, stageId: stage.stageId, operation: stage.operation, inputObjectCount: stage.inputObjectIds.length, resultObjectId: stage.resultObjectId, topologyEntries: stage.topologyEntries, recordCount: stage.recordCount })
    capturedOperations.add(stage.operation)
    operationEvidence[stage.operation] ??= { report: `config/${file}`, mode: 'native-stage', historyRecords: stage.recordCount, relationCount: 0, marker: null }
  }
}

const missingOperations = requiredOperations.filter((operation) => !capturedOperations.has(operation))
if (missingOperations.length > 0) fail(`missing native evidence for: ${missingOperations.join(', ')}`)
const history = reports['chrome-native-history-verification.json'].report
if (JSON.stringify(history.nativeCapabilities.operations) !== JSON.stringify(requiredOperations)) fail('the native history operation registry drifted from the locked 19-operation contract.')

console.log(JSON.stringify({
  status: 'freecad-tsn-stage-evidence-pass',
  exactPromotionReady: false,
  provider: history.nativeCapabilities.providerId,
  requiredBuilderOperations: requiredOperations.length,
  capturedStageOperations: [...capturedOperations].sort(),
  capturedBuilderOperationCount: capturedOperations.size,
  missingBuilderOperations: missingOperations,
  reports: Object.fromEntries(Object.entries(operationEvidence).sort(([a], [b]) => a.localeCompare(b))),
  nativeStages: stageEvidence,
  blockers: ['Production private naming is linked and non-unique isomorphic provenance is fail-closed; exhaustive cross-feature mutation, FCStd round-trip closure and complete native document/property semantics remain open'],
}, null, 2))
