import { createHash } from 'node:crypto'
import { access, readFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { loadGoldenManifest } from './freecad-golden-contract.mjs'

const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const readJson = async (relative) => JSON.parse(await readFile(resolve(root, relative), 'utf8'))
const fail = (message) => { throw new Error(message) }

const baseline = await readJson('config/freecad-baseline.json')
const toolchain = await readJson('config/freecad-toolchain.json')
const nativeBuild = await readJson('config/freecad-native-build.json')
const runtime = await readJson('config/runtime-baseline.json')
const packageJson = await readJson('package.json')
const nodeRuntime = await readFile(resolve(root, 'config/node-runtime.env'), 'utf8')

if (baseline.baselineId !== toolchain.baselineId || baseline.freecadVersion !== toolchain.source.tag) fail('FreeCAD baseline and toolchain tag disagree.')
if (!baseline.sourceRef.endsWith(`@${toolchain.source.commit}`) || !/^[0-9a-f]{40}$/.test(toolchain.source.commit)) fail('FreeCAD source commit is not an exact 40-character revision.')
if (nativeBuild.baselineId !== baseline.baselineId || nativeBuild.source.commit !== toolchain.source.commit) fail('Native oracle build manifest does not match the locked FreeCAD source.')
if (!nodeRuntime.includes(`NODE_VERSION=${packageJson.engines.node}`) || runtime.projectRuntime.node !== packageJson.engines.node) fail('Project Node runtime declarations disagree.')

for (const [packageName, expectedVersion] of [['@bitbybit-dev/occt', runtime.geometry.version], ['@bitbybit-dev/occt-worker', runtime.geometry.version], ['three', runtime.viewport.version], ['@sqlite.org/sqlite-wasm', '3.53.0-build1']]) {
  const declared = packageJson.dependencies[packageName]
  const installed = await readJson(`node_modules/${packageName}/package.json`)
  if (declared !== expectedVersion || installed.version !== expectedVersion) fail(`${packageName} must be declared and installed at ${expectedVersion}.`)
}

const wasmFile = resolve(root, 'node_modules/@bitbybit-dev/occt/bitbybit-dev-occt/bitbybit-dev-occt.a4a6ec2a.wasm')
const wasmHash = createHash('sha256').update(await readFile(wasmFile)).digest('hex')
if (wasmHash !== runtime.geometry.wasmSha256) fail(`OCCT WASM checksum mismatch: ${wasmHash}.`)

const manifest = await loadGoldenManifest(resolve(root, toolchain.goldenContract.manifest))
if (manifest.baselineId !== baseline.baselineId || manifest.driver !== toolchain.goldenContract.driver) fail('Golden manifest does not match the locked baseline contract.')
if (nativeBuild.verification.goldenManifest !== toolchain.goldenContract.manifest || nativeBuild.verification.scenarioCount !== manifest.scenarios.length) fail('Native oracle verification does not match the golden manifest.')
const nativeOracle = resolve(root, nativeBuild.artifact.path)
try {
  await access(nativeOracle)
  const nativeHash = createHash('sha256').update(await readFile(nativeOracle)).digest('hex')
  if (nativeHash !== nativeBuild.artifact.sha256) fail(`Native FreeCADCmd checksum mismatch: ${nativeHash}.`)
} catch (error) {
  if (error?.code !== 'ENOENT') throw error
}
console.log(`Baseline contract OK: FreeCAD ${baseline.freecadVersion} @ ${toolchain.source.commit.slice(0, 12)}, ${manifest.scenarios.length} golden scenarios, OCCT WASM ${wasmHash.slice(0, 12)}.`)
