// bot/src/context.ts — Manages SDD_BOT_CONTEXT environment variable
// NOTE: execa v8 is ESM-only; we load it via dynamic import() to stay compatible
// with the CommonJS compilation target configured in tsconfig.json.

import fs from 'node:fs'

// Lazy-loaded execa to work around the ESM-only constraint of execa v8.
async function getExeca() {
  // Dynamic import is supported at runtime even in CJS output.
  const mod = await import('execa')
  return mod.execa
}

export class BotContext {
  static isBotContext(): boolean {
    return process.env.SDD_BOT_CONTEXT === 'true'
  }

  // Runs sdd CLI with SDD_BOT_CONTEXT=true injected
  // Returns stdout as string
  static async runSdd(args: string[], cwd: string): Promise<string> {
    const execa = await getExeca()
    try {
      const result = await execa('sdd', args, {
        cwd,
        env: { ...process.env, SDD_BOT_CONTEXT: 'true' },
        timeout: 120_000,
        stderr: 'inherit',
      })
      return result.stdout
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : String(err)
      throw new Error(`sdd ${args.join(' ')} failed (bot context): ${msg}`)
    }
  }

  // Normaliza o output do sdd para o CONTEÚDO do artefato.
  // Comandos de stage (idea, prd, techspec, ...) ESCREVEM o artefato em
  // docs/<slug>/NN-stage.md e imprimem apenas o CAMINHO no stdout; já o `risk`
  // imprime o conteúdo direto. Se o output apontar para um arquivo .md existente,
  // lê e retorna o conteúdo do arquivo; caso contrário devolve o próprio output.
  static resolveArtifactContent(sddOutput: string): string {
    const lines = sddOutput
      .split(/\r?\n/)
      .map((l) => l.trim())
      .filter((l) => l.length > 0)
    for (let i = lines.length - 1; i >= 0; i--) {
      const candidate = lines[i]
      if (candidate.toLowerCase().endsWith('.md') && fs.existsSync(candidate)) {
        return fs.readFileSync(candidate, 'utf8').trim()
      }
    }
    return sddOutput.trim()
  }

  // Roda o sdd em contexto de bot e retorna o CONTEÚDO do artefato gerado,
  // resolvendo o caso em que o sdd imprime apenas o caminho do arquivo.
  static async runSddArtifact(args: string[], cwd: string): Promise<string> {
    const output = await BotContext.runSdd(args, cwd)
    return BotContext.resolveArtifactContent(output)
  }

  // Runs sdd CLI WITHOUT bot context (normal mode)
  static async runSddNormal(args: string[], cwd: string): Promise<string> {
    const execa = await getExeca()
    try {
      const result = await execa('sdd', args, {
        cwd,
        timeout: 120_000,
        stderr: 'inherit',
      })
      return result.stdout
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : String(err)
      throw new Error(`sdd ${args.join(' ')} failed (normal context): ${msg}`)
    }
  }
}
