/**
 * CMakeConfigurator - CMake build configuration
 * DD §15. CMake+Ninja preferred, Make fallback. Generates compile_commands.json.
 *
 * @module packages/toolchain-cpp/src/build/CMakeConfigurator
 */

import { execFileSync } from 'child_process'
import { existsSync, mkdirSync } from 'fs'
import { join } from 'path'

export interface CMakeConfig {
  project_root: string
  build_dir?: string
  generator?: 'Ninja' | 'Unix Makefiles'
  cmake_args?: string[]
  build_type?: 'Debug' | 'Release' | 'RelWithDebInfo'
}

export interface CMakeConfigureOutput {
  ok: boolean
  build_dir: string
  compile_commands_path?: string
  error?: string
}

export class CMakeConfigurator {
  configure(config: CMakeConfig): CMakeConfigureOutput {
    const build_dir = config.build_dir || join(config.project_root, 'build')
    const generator = config.generator || 'Ninja'
    const build_type = config.build_type || 'Debug'
    const extra_args: string[] = config.cmake_args || []

    if (!existsSync(build_dir)) {
      mkdirSync(build_dir, { recursive: true })
    }

    const cmake_args = [
      '-G', generator,
      `-DCMAKE_BUILD_TYPE=${build_type}`,
      '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
      ...extra_args,
      config.project_root,
    ]

    try {
      execFileSync('cmake', cmake_args, {
        cwd: build_dir,
        encoding: 'utf-8',
        stdio: 'pipe',
      })

      const cc_path = join(build_dir, 'compile_commands.json')
      return {
        ok: true,
        build_dir,
        compile_commands_path: existsSync(cc_path) ? cc_path : undefined
      }
    } catch (error) {
      return {
        ok: false,
        build_dir,
        error: error instanceof Error ? error.message : String(error)
      }
    }
  }
}
