import { createCamJob } from './facade/cam'
import { createLinuxcncIframeAdapter, prepareCamPipeline, submitCamPipelineToLinuxcnc } from './facade/camPipeline'

type MachineReport = {
  schemaVersion: 1
  status: 'pass' | 'failed'
  stages: string[]
  openCamLib?: { backend: string; sourceRevision: string; artifactSha256: string; triangleCount: number; inputPoints: number; outputPoints: number; sampling: number }
  gcode?: { bytes: number; hasM428: boolean; hasM429: boolean; hasG93: boolean; hasG94: boolean; hasB: boolean; hasC359: boolean; hasC361: boolean }
  machine?: { backend: string; status: string; dryRunStatus?: string; parserAuthority?: string; machineCase?: string; dryRunMachineCase?: string; lines?: number; blocks?: number; trajectorySegments?: number; message?: string }
  error?: string
}

declare global { interface Window { __bitbybitCamLinuxcncMachineReport?: MachineReport } }

const run = async (): Promise<MachineReport> => {
  const report: MachineReport = { schemaVersion: 1, status: 'failed', stages: ['CAD', 'OCL', 'CAMotics', 'GCODE', 'LinuxCNC WASM'] }
  try {
    // Keep the test stock inside the selected LinuxCNC machine's Z workspace
    // (AXIS_Z is [-475, 0]); positive-Z work coordinates require a G54 offset.
    const cam = createCamJob('machine-cert', 'LinuxCNC WASM machine acceptance', { min: [0, 0, -10], max: [10, 10, -5] })
    cam.addTool({ id: 'T1', name: '2 mm end mill', diameter: 2, length: 20 })
    cam.addToolController({ id: 'TC1', label: 'T1 controller', toolId: 'T1', toolNumber: 1, spindleSpeed: 6000, spindleDirection: 'forward', horizontalFeed: 120, verticalFeed: 60, horizontalRapid: 600, verticalRapid: 300 })
    cam.addOperation({ id: 'profile', kind: 'profile', toolId: 'T1', controllerId: 'TC1', depth: 1, feed: 120 })
    cam.generatePath('profile')
    const prepared = await prepareCamPipeline(cam, 'profile', {
      postprocessor: 'linuxcnc',
      kinematics: { configuration: '5-axis', rotary: { axis: 'C', startDegrees: 359, endDegrees: 361 }, tilt: { axis: 'B', startDegrees: 5, endDegrees: 15 } },
    })
    report.openCamLib = prepared.openCamLib
    report.gcode = {
      bytes: new TextEncoder().encode(prepared.gcode).byteLength,
      hasM428: /(^|\n)M428(\n|$)/.test(prepared.gcode),
      hasM429: /(^|\n)M429(\n|$)/.test(prepared.gcode),
      hasG93: /(^|\n)G93(\n|$)/.test(prepared.gcode),
      hasG94: /(^|\n)G94(\n|$)/.test(prepared.gcode),
      hasB: /\bB15\.000\b/.test(prepared.gcode),
      hasC359: /\bC359\.000\b/.test(prepared.gcode),
      hasC361: /\bC361\.000\b/.test(prepared.gcode),
    }
    const dryRun = await submitCamPipelineToLinuxcnc(prepared, createLinuxcncIframeAdapter({
      url: '/linuxcnc-machine/?case=axis-vismach-5axis-table-rotary-tilting-xyzbc-trt',
      run: false,
      name: 'cad-ocl-camotics-xyzbc-dry-run.ngc',
      timeoutMs: 180_000,
    }))
    const result = await submitCamPipelineToLinuxcnc(prepared, createLinuxcncIframeAdapter({
      url: '/linuxcnc-machine/?case=axis-vismach-5axis-table-rotary-tilting-xyzbc-trt',
      run: true,
      name: 'cad-ocl-camotics-xyzbc.ngc',
      timeoutMs: 180_000,
    }))
    const trace = result.linuxcnc?.trace
    const dryRunTrace = dryRun.linuxcnc?.trace
    report.machine = { backend: result.linuxcnc?.backend || '', status: result.linuxcnc?.status || '', dryRunStatus: dryRun.linuxcnc?.status || '', parserAuthority: trace?.parserAuthority, machineCase: trace?.machineCase, dryRunMachineCase: dryRunTrace?.machineCase, lines: trace?.lines, blocks: trace?.blocks, trajectorySegments: trace?.trajectorySegments, message: result.linuxcnc?.message }
    report.status = report.openCamLib.backend === 'upstream-opencamlib-wasm' && report.openCamLib.triangleCount >= 2 && report.openCamLib.outputPoints >= report.openCamLib.inputPoints && Object.values(report.gcode).every(Boolean) && report.machine.backend === 'linuxcnc-wasm' && report.machine.status === 'accepted' && report.machine.dryRunStatus === 'dry-run' && report.machine.parserAuthority === 'linuxcnc-wasm' && report.machine.machineCase === 'axis-vismach-5axis-table-rotary-tilting-xyzbc-trt' && report.machine.dryRunMachineCase === report.machine.machineCase && Number(report.machine.lines) >= 10 && Number(report.machine.lines) < 1000 && Number(report.machine.blocks) >= 2 && Number(report.machine.blocks) < 1000 && Number(report.machine.trajectorySegments) >= 2 && Number(report.machine.trajectorySegments) < 1000 ? 'pass' : 'failed'
  } catch (error) {
    report.error = error instanceof Error ? error.stack || error.message : String(error)
  }
  return report
}

void run().then((report) => {
  window.__bitbybitCamLinuxcncMachineReport = report
  document.documentElement.dataset.status = report.status
  const output = document.querySelector('#result')
  if (output) output.textContent = JSON.stringify(report, null, 2)
})
