/**
 * Shell 执行器插件
 * 使用 child_process 执行终端命令
 */

const { Plugin } = require('../src/core/plugin-base')
const { spawn } = require('child_process')
const { z } = require('zod')

class ShellExecutorPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'shell-executor'
    this.version = '1.0.0'
    this.description = 'Shell 执行器，用于运行终端命令和脚本'
    this.priority = 15

    this.system = true 

    this.config = {
      timeout: config.timeout || 60000,
      workingDir: config.workingDir || process.cwd()
    }

    this._framework = null
  }

  install(framework) {
    this._framework = framework
    return this
  }

  start(framework) {
    // 注册 shell 工具
    framework.registerTool({
      name: 'shell',
      description: '执行 Shell 命令',
      inputSchema: z.object({
        command: z.string().describe('要执行的命令'),
        cwd: z.string().optional().describe('工作目录，默认为当前目录'),
        timeout: z.number().optional().describe('超时时间（毫秒），默认 60000')
      }),
      execute: async (args) => {
        const cwd = args.cwd || this.config.workingDir
        const timeout = args.timeout || this.config.timeout

        return new Promise((resolve) => {
          const startTime = Date.now()
          let output = ''
          let errorOutput = ''

          // 检测命令类型
          const isWindows = process.platform === 'win32'
          const shell = isWindows ? 'cmd.exe' : '/bin/sh'
          const shellArg = isWindows ? '/c' : '-c'

          const proc = spawn(shell, [shellArg, args.command], {
            cwd,
            timeout,
            env: { ...process.env }
          })

          proc.stdout.on('data', (data) => {
            output += data.toString()
          })

          proc.stderr.on('data', (data) => {
            errorOutput += data.toString()
          })

          proc.on('close', (code) => {
            const elapsed = Date.now() - startTime
            resolve({
              success: code === 0,
              exitCode: code,
              stdout: output,
              stderr: errorOutput,
              elapsed,
              command: args.command,
              cwd
            })
          })

          proc.on('error', (err) => {
            resolve({
              success: false,
              error: err.message,
              command: args.command,
              cwd
            })
          })

          // 超时处理
          setTimeout(() => {
            if (!proc.killed) {
              proc.kill('SIGTERM')
              resolve({
                success: false,
                error: `Command timed out after ${timeout}ms`,
                stdout: output,
                stderr: errorOutput,
                command: args.command,
                cwd,
                timedOut: true
              })
            }
          }, timeout)
        })
      }
    })

    // 注册 PowerShell 工具 (Windows)
    if (process.platform === 'win32') {
      framework.registerTool({
        name: 'powershell',
        description: '执行 PowerShell 命令 (仅 Windows)',
        inputSchema: z.object({
          command: z.string().describe('要执行的 PowerShell 命令'),
          cwd: z.string().optional().describe('工作目录'),
          timeout: z.number().optional().describe('超时时间（毫秒）')
        }),
        execute: async (args) => {
          const cwd = args.cwd || this.config.workingDir
          const timeout = args.timeout || this.config.timeout

          return new Promise((resolve) => {
            const startTime = Date.now()
            let output = ''
            let errorOutput = ''

            const proc = spawn('powershell.exe', ['-NoProfile', '-Command', args.command], {
              cwd,
              timeout,
              env: { ...process.env }
            })

            proc.stdout.on('data', (data) => {
              output += data.toString()
            })

            proc.stderr.on('data', (data) => {
              errorOutput += data.toString()
            })

            proc.on('close', (code) => {
              const elapsed = Date.now() - startTime
              resolve({
                success: code === 0,
                exitCode: code,
                stdout: output,
                stderr: errorOutput,
                elapsed,
                command: args.command,
                cwd
              })
            })

            proc.on('error', (err) => {
              resolve({
                success: false,
                error: err.message,
                command: args.command,
                cwd
              })
            })

            setTimeout(() => {
              if (!proc.killed) {
                proc.kill('SIGTERM')
                resolve({
                  success: false,
                  error: `Command timed out after ${timeout}ms`,
                  stdout: output,
                  stderr: errorOutput,
                  command: args.command,
                  cwd,
                  timedOut: true
                })
              }
            }, timeout)
          })
        }
      })
    }

    return this
  }

  reload(framework) {
    this._framework = framework
  }

  uninstall(framework) {
    this._framework = null
  }
}

module.exports = ShellExecutorPlugin