#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SDK_ROOT="${FREECAD_WASM_SDK_OUTPUT_DIR:-${ROOT_DIR}/.cache/toolchains/freecad-naming-sdk}"
BUILD_DIR="${ROOT_DIR}/.cache/toolchains/freecad-naming-sdk/build-wasm"
REPORT_PATH="${SDK_ROOT}/candidate-build-report.json"
JOBS="${JOBS:-$(nproc)}"

cd "${ROOT_DIR}"
node scripts/check-freecad-wasm-sdk-build-plan.mjs >/dev/null
if [[ "${FREECAD_WASM_REUSE_OVERLAY:-0}" != "1" ]]; then
  bash scripts/prepare-freecad-occt8-overlay.sh
fi
if [[ "${FREECAD_WASM_REUSE_CONFIGURE:-0}" != "1" ]]; then
  node scripts/configure-freecad-naming-sdk-candidate.mjs
fi

cmake --build "${BUILD_DIR}" --target Part --parallel "${JOBS}"
mkdir -p "${SDK_ROOT}/lib"
cp -f "${BUILD_DIR}/lib/libFreeCADBase.so" "${SDK_ROOT}/lib/libFreeCADBase.a"
cp -f "${BUILD_DIR}/lib/libFreeCADApp.so" "${SDK_ROOT}/lib/libFreeCADApp.a"
cp -f "${BUILD_DIR}/Mod/Part/Part.so" "${SDK_ROOT}/lib/libPart.a"

node --input-type=module - "${SDK_ROOT}" "${REPORT_PATH}" <<'NODE'
import { writeFile } from 'node:fs/promises'
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
import { relative, resolve } from 'node:path'
import { inspectWasmStaticArchive, sha256File } from './scripts/freecad-naming-sdk-lib.mjs'

const run = promisify(execFile)
const root = process.cwd()
const sdkRoot = resolve(process.argv[2])
const reportPath = resolve(process.argv[3])
const specs = [
  { name: 'FreeCADBase', file: 'libFreeCADBase.a', requiredMembers: [] },
  {
    name: 'FreeCADApp',
    file: 'libFreeCADApp.a',
    requiredMembers: ['ElementMap.cpp.o', 'MappedElement.cpp.o', 'MappedName.cpp.o', 'ElementNamingUtils.cpp.o', 'StringHasher.cpp.o'],
  },
  { name: 'Part', file: 'libPart.a', requiredMembers: ['TopoShape.cpp.o', 'TopoShapeExpansion.cpp.o', 'TopoShapeMapper.cpp.o'] },
]
const archives = []
for (const spec of specs) {
  const path = resolve(sdkRoot, 'lib', spec.file)
  const inspected = await inspectWasmStaticArchive(path)
  const members = (await run('emar', ['t', path], { maxBuffer: 16 * 1024 * 1024 })).stdout.trim().split('\n').filter(Boolean)
  const missingMembers = spec.requiredMembers.filter((member) => !members.includes(member))
  if (missingMembers.length > 0) throw new Error(`${spec.name} archive is missing required members: ${missingMembers.join(', ')}`)
  archives.push({
    name: spec.name,
    path: relative(root, path),
    sha256: await sha256File(path),
    ...inspected,
    requiredMembers: spec.requiredMembers,
  })
}
const report = {
  schemaVersion: 1,
  status: 'candidate-archives-built',
  availability: 'candidate-archives-only',
  target: 'wasm32-emscripten',
  freecadVersion: '1.1.1',
  sourceCommit: '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d',
  emscriptenVersion: '3.1.69',
  archives,
  productionPublication: false,
  productionManifestGenerated: false,
  boundary: {
    freecadNamingBuildStatus: 'production-linked',
    exTsn02: 'completed',
    systemExact: false,
    workerLinked: true,
    availability: 'available',
    callbacks: ['freecadNamingAbiVersion', 'freecadNamingCapabilitiesJson', 'freecadNamingEvidenceJson'],
  },
}
await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`)
console.log(JSON.stringify({ ...report, report: relative(root, reportPath) }, null, 2))
NODE

git -C "${ROOT_DIR}/.cache/freecad/FreeCAD" diff --quiet
git -C "${ROOT_DIR}/.cache/freecad/FreeCAD" diff --cached --quiet
