import { spawnSync } from 'node:child_process'
import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { mkdir, writeFile } from 'node:fs/promises'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
const executable = resolve(root, '.cache/freecad/install-desktop/bin/FreeCAD')
const probe = resolve(root, 'scripts/freecad-gui-workflow-oracle.py')
const sysroot = resolve(root, '.cache/freecad/sysroot')
const outputDirectory = resolve(root, '.cache/freecad/gui-workflow-oracle')
const reportPath = resolve(root, 'config/freecad-gui-workflow-oracle.json')
const marker = 'FREECAD_GUI_WORKFLOW_RESULT='
const timeoutMs = Number(process.env.FREECAD_GUI_WORKFLOW_TIMEOUT_MS || 120_000)
const fail = (message) => { throw new Error(`FreeCAD GUI workflow oracle: ${message}`) }

await mkdir(outputDirectory, { recursive: true })
const emptyConfig = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n<FCParameters><FCParamGroup Name="Root"/></FCParameters>\n'

const runProbe = (state) => {
  const resultFile = resolve(outputDirectory, `partdesign-pad-${state}-result.json`)
  const recoveryFile = resolve(outputDirectory, 'partdesign-pad-recovery.FCStd')
  const configDirectory = resolve(outputDirectory, `config-${state}`)
  const userConfig = resolve(configDirectory, 'user.cfg')
  const systemConfig = resolve(configDirectory, 'system.cfg')
  mkdirSync(configDirectory, { recursive: true })
  writeFileSync(userConfig, emptyConfig)
  writeFileSync(systemConfig, emptyConfig)
  rmSync(resultFile, { force: true })
  if (state === 'recovery') rmSync(recoveryFile, { force: true })
  const runtimeEnv = {
    ...process.env,
    PYTHONPATH: `${resolve(sysroot, 'usr/lib/python3/dist-packages')}${process.env.PYTHONPATH ? `:${process.env.PYTHONPATH}` : ''}`,
    LD_LIBRARY_PATH: `${resolve(sysroot, 'usr/lib/x86_64-linux-gnu')}${process.env.LD_LIBRARY_PATH ? `:${process.env.LD_LIBRARY_PATH}` : ''}`,
    MATPLOTLIBRC: resolve(sysroot, 'usr/share/matplotlib/mpl-data/matplotlibrc'),
    MPLBACKEND: 'Agg',
    FREECAD_GUI_WORKFLOW_STATE: state,
    FREECAD_GUI_WORKFLOW_RESULT_FILE: resultFile,
    FREECAD_GUI_WORKFLOW_RECOVERY_FILE: recoveryFile,
  }
  const execution = spawnSync('xvfb-run', ['-a', executable, '--user-cfg', userConfig, '--system-cfg', systemConfig, '--python-path', resolve(sysroot, 'usr/lib/python3/dist-packages'), probe], {
    cwd: root,
    encoding: 'utf8',
    maxBuffer: 32 * 1024 * 1024,
    timeout: timeoutMs,
    env: runtimeEnv,
  })
  const output = `${execution.stdout ?? ''}\n${execution.stderr ?? ''}`
  const markerLine = output.split(/\r?\n/).find((line) => line.startsWith(marker))
  const resultBytes = (() => { try { return readFileSync(resultFile, 'utf8') } catch { return '' } })()
  if (execution.error || (execution.status !== 0 && !resultBytes && !markerLine)) fail(`${state} native probe exited with ${execution.status}: ${[execution.error?.message, output.trim()].filter(Boolean).join('\n')}`)
  const result = JSON.parse(resultBytes || markerLine.slice(marker.length))
  if (result.freecadVersion !== '1.1.1' || result.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail(`${state} native baseline mismatch: ${JSON.stringify(result)}`)
  if (result.workflowId !== 'partdesign-pad-task' || result.commandId !== 'PartDesign_Pad' || result.state !== state || result.success !== true) fail(`Pad ${state} workflow failed: ${JSON.stringify(result)}`)
  return result
}

const success = runProbe('success')
const disabled = runProbe('disabled')
const failure = runProbe('failure')
const cancel = runProbe('cancel')
const recovery = runProbe('recovery')

const report = {
  schemaVersion: 1,
  baseline: {
    freecadVersion: success.freecadVersion,
    commit: success.gitCommit,
    profile: 'desktop-xvfb-isolated-config',
  },
  generatedBy: './npmw run probe:freecad-gui-workflow',
  checkedBy: './npmw run check:freecad-gui-workflow',
  family: {
    id: success.workflowId,
    primaryCommand: success.commandId,
    exactTask: 'EX-UI-03',
    source: '.cache/freecad/FreeCAD/src/Mod/PartDesign/Gui/Command.cpp',
  },
  workflows: {
    success,
    disabled,
    failure,
    cancel,
    recovery,
  },
  remainingStates: [],
  exactPromotionReady: false,
}
await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`)
console.log(JSON.stringify({
  status: 'freecad-gui-workflow-generated',
  family: report.family.id,
  command: report.family.primaryCommand,
  capturedStates: Object.keys(report.workflows),
  bodyTip: success.after.bodyTip,
  volume: success.after.pad.volume,
  taskOpened: success.taskPanel.opened.activeDialog,
  taskClosed: !success.taskPanel.closed.activeDialog,
  disabledWithoutDocument: disabled.after.sideEffects.documentCount === 0,
  disabledWithoutTask: !disabled.after.sideEffects.taskPanel.activeDialog,
  disabledWithoutTransaction: !disabled.after.sideEffects.transaction.active,
  failureDiagnostic: failure.diagnostic.warnings[0].text,
  failureRolledBack: !failure.after.padExists && !failure.after.transaction.active,
  cancelPreviewVolume: cancel.taskPanel.preview.volume,
  cancelRolledBack: !cancel.after.padExists && !cancel.after.transaction.active,
  recoveryVolume: recovery.persistence.resavedReopened.padVolume,
  recoveryResaved: recovery.persistence.resavedReopened.padExists,
  report: 'config/freecad-gui-workflow-oracle.json',
}, null, 2))
