import { mkdir, writeFile } from 'node:fs/promises'
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
const run = promisify(execFile)
const sourceDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/source-occt8')
const buildDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/build-wasm')
const installDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/install-wasm')
const qtPrefix = resolve(root, '.cache/toolchains/qt6/install-wasm-freecad')
const yamlPrefix = resolve(root, '.cache/toolchains/yaml-cpp/install-wasm')
const icuPrefix = resolve(root, '.cache/toolchains/icu/install-wasm')
const pythonPrefix = resolve(root, '.cache/toolchains/python/install-wasm')
const xercesPrefix = resolve(root, '.cache/toolchains/xerces-c/install-wasm')
const occtBuild = resolve(root, '.cache/bitbybit/occt-history-build-offline')
const occtSource = resolve(root, '.cache/occt/occt')
const offlineSysroot = resolve(root, '.cache/offline-sysroot')
const boostPrefix = resolve(root, '.cache/toolchains/boost/install-wasm')
const reportPath = resolve(root, '.cache/toolchains/freecad-naming-sdk/configure-report.json')
const command = [
  'emcmake', 'cmake', '--fresh', '-S', sourceDir, '-B', buildDir, '-G', 'Ninja',
  '-DCMAKE_BUILD_TYPE=Release',
  `-DCMAKE_INSTALL_PREFIX=${installDir}`,
  `-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=${resolve(root, 'config/freecad-wasm-sdk-bootstrap.cmake')}`,
  '-DBUILD_GUI=OFF', '-DBUILD_PART=ON', '-DBUILD_MATERIAL=ON', '-DBUILD_BIM=OFF', '-DBUILD_FLAT_MESH=OFF',
  '-DBUILD_PART_DESIGN=OFF', '-DBUILD_SKETCHER=OFF',
  '-DBUILD_MESH=OFF', '-DBUILD_MESH_PART=OFF', '-DBUILD_FEM=OFF', '-DBUILD_CAM=OFF', '-DBUILD_ASSEMBLY=OFF',
  '-DBUILD_DRAFT=OFF', '-DBUILD_DRAWING=OFF', '-DBUILD_HELP=OFF', '-DBUILD_IDF=OFF', '-DBUILD_IMPORT=OFF',
  '-DBUILD_INSPECTION=OFF', '-DBUILD_OPENSCAD=OFF', '-DBUILD_PLOT=OFF', '-DBUILD_POINTS=OFF',
  '-DBUILD_REVERSEENGINEERING=OFF', '-DBUILD_ROBOT=OFF', '-DBUILD_SHOW=OFF', '-DBUILD_SPREADSHEET=OFF',
  '-DBUILD_START=OFF', '-DBUILD_SURFACE=OFF', '-DBUILD_TECHDRAW=OFF', '-DBUILD_TEST=OFF', '-DBUILD_TUX=OFF',
  '-DBUILD_WEB=OFF', '-DBUILD_ADDONMGR=OFF', '-DBUILD_MEASURE=OFF', '-DBUILD_CLOUD=OFF', '-DBUILD_JTREADER=OFF',
  '-DBUILD_VR=OFF', '-DBUILD_TEMPLATE=OFF', '-DBUILD_SANDBOX=OFF', '-DENABLE_DEVELOPER_TESTS=OFF',
  '-DFREECAD_USE_FREETYPE=OFF', '-DFREECAD_USE_EXTERNAL_FMT=ON', '-DFREECAD_CHECK_PIVY=OFF',
  '-DINSTALL_TO_SITEPACKAGES=OFF', '-DFREECAD_USE_CCACHE=OFF', '-DBUILD_DYNAMIC_LINK_PYTHON=OFF',
  `-DFREECAD_WASM_OFFLINE_SYSROOT=${offlineSysroot}`,
  `-DCMAKE_PREFIX_PATH=${qtPrefix};${yamlPrefix};${icuPrefix};${xercesPrefix}`,
  `-DQt6_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6')}`,
  `-DQt6Core_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Core')}`,
  `-DQt6Concurrent_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Concurrent')}`,
  `-DQt6Network_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Network')}`,
  `-DQt6Xml_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Xml')}`,
  `-DQt6ZlibPrivate_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6ZlibPrivate')}`,
  `-DQt6BundledZLIB_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6BundledZLIB')}`,
  `-DQt6BundledPcre2_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6BundledPcre2')}`,
  `-DZLIB_INCLUDE_DIR=${resolve(qtPrefix, 'include/QtZlib')}`,
  `-DZLIB_LIBRARY=${resolve(qtPrefix, 'lib/libQt6BundledZLIB.a')}`,
  `-Dyaml-cpp_DIR=${resolve(yamlPrefix, 'lib/cmake/yaml-cpp')}`,
  `-DICU_ROOT=${icuPrefix}`,
  `-DICU_INCLUDE_DIR=${resolve(icuPrefix, 'include')}`,
  `-DICU_UC_LIBRARY_RELEASE=${resolve(icuPrefix, 'lib/libicuuc.a')}`,
  `-DICU_I18N_LIBRARY_RELEASE=${resolve(icuPrefix, 'lib/libicui18n.a')}`,
  `-DXercesC_INCLUDE_DIR=${resolve(xercesPrefix, 'include')}`,
  `-DXercesC_LIBRARY=${resolve(xercesPrefix, 'lib/libxerces-c.a')}`,
  '-DPython3_EXECUTABLE=/usr/bin/python3.13',
  `-DPython3_INCLUDE_DIR=${resolve(pythonPrefix, 'include/python3.13')}`,
  `-DPython3_INCLUDE_DIRS=${resolve(pythonPrefix, 'include/python3.13')}`,
  `-DPython3_LIBRARY=${resolve(pythonPrefix, 'lib/libpython3.13.a')}`,
  '-DOCCT_CMAKE_FALLBACK=ON',
  `-DOCC_INCLUDE_DIR=${resolve(occtBuild, 'include/opencascade')}`,
  `-DOCC_LIBRARY=${resolve(occtBuild, 'lin32/clang/lib/libTKernel.a')}`,
  `-DFREECAD_WASM_OCCT_COMPAT_INCLUDE=${resolve(occtSource, 'src/Deprecated/NCollectionAliases')}`,
  `-DEIGEN3_INCLUDE_DIR=${resolve(offlineSysroot, 'include/eigen3')}`,
  `-DBOOST_WASM_ROOT=${boostPrefix}`,
  `-DBoost_DIR=${resolve(root, 'config/cmake/boost')}`,
  '-DBoost_USE_STATIC_LIBS=ON',
  '-DQT_HOST_PATH=/usr',
  '-DQT_HOST_PATH_CMAKE_DIR=/usr/lib/x86_64-linux-gnu/cmake',
  '-DFETCHCONTENT_FULLY_DISCONNECTED=ON',
  `-DCMAKE_TOOLCHAIN_FILE=${resolve(root, 'config/emscripten-freecad-candidate-toolchain.cmake')}`,
  '-DCMAKE_AR=emar', '-DCMAKE_RANLIB=emranlib',
  '-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER', '-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY', '-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY',
]
const startedAt = new Date().toISOString()
let status = 'configured'
let exitCode = 0
let output = ''
try {
  const result = await run(command[0], command.slice(1), { cwd: root, maxBuffer: 16 * 1024 * 1024 })
  output = `${result.stdout}${result.stderr}`
} catch (error) {
  status = 'blocked'
  exitCode = error.status ?? 1
  output = `${error.stdout ?? ''}${error.stderr ?? ''}`
}
const missing = []
if (status === 'blocked') {
  if (output.includes('Could not find a valid Qt installation') || output.includes('Could NOT find Qt6')) missing.push('Qt6 wasm package configuration')
  if (output.includes('Could NOT find Python3')) missing.push('Emscripten Python3 development target')
  if (output.includes('Could NOT find ICU') || output.includes('Failed to find all ICU components')) missing.push('ICU wasm static libraries')
  if (output.includes('Could NOT find XercesC') || output.includes('Failed to find XercesC')) missing.push('Xerces-C wasm static library')
  if (output.includes('Could NOT find ZLIB')) missing.push('ZLIB wasm static library')
  if (output.includes('Could NOT find OCC') || output.includes('OpenCASCADE not found')) missing.push('OpenCASCADE wasm SDK')
  if (output.includes('Could NOT find Eigen3') || output.includes('Eigen3 not found')) missing.push('Eigen3 headers')
  if (output.includes('Could NOT find Boost') || output.includes('provided by "Boost"')) missing.push('Boost wasm static libraries')
  if (output.includes('Could NOT find yaml-cpp') || output.includes('provided by "yaml-cpp"')) missing.push('yaml-cpp wasm package')
  if (output.includes('Unknown CMake command "qt_add_translation"')) missing.push('Qt translation cross-build adapter')
  if (output.includes('Qt6::Core') && output.includes('mkspecs/wasm-emscripten') && output.includes('non-existent path')) missing.push('Qt6 wasm mkspec installation')
  if (missing.length === 0) missing.push('unclassified CMake configure failure')
}
await mkdir(resolve(root, '.cache/toolchains/freecad-naming-sdk'), { recursive: true })
await writeFile(reportPath, `${JSON.stringify({ schemaVersion: 1, status, exitCode, startedAt, command, missing, buildDir, outputTail: output.slice(-12000), productionPublication: false, boundary: { freecadNamingBuildStatus: 'production-linked', exTsn02: 'completed', systemExact: false, workerLinked: true, callbacks: ['freecadNamingAbiVersion', 'freecadNamingCapabilitiesJson', 'freecadNamingEvidenceJson'] } }, null, 2)}\n`)
console.log(JSON.stringify({ status, exitCode, report: reportPath, missing, productionPublication: false }, null, 2))
if (status !== 'configured') process.exit(exitCode)
