/**
 * InstallPlugin - npm 包安装工具
 * 自动安装缺少的 node 模块到 .agent 目录或指定目录
 */

const { execSync } = require('child_process')
const fs = require('fs')
const path = require('path')
const { Plugin } = require('../src/core/plugin-base')
const { logger } = require('../src/utils/logger')
const log = logger.child('InstallPlugin')
const { z } = require('zod')

class InstallPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'install'
    this.version = '1.0.0'
    this.description = '自动安装 npm 包到指定目录'

    this._agentDir = config.agentDir || '.agent'
    this._nodeModulesDir = null
    this.system = true 
  }

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

  start(framework) {
    // 确保 node_modules 目录存在
    this._nodeModulesDir = path.join(this._agentDir, 'node_modules')
    if (!fs.existsSync(this._nodeModulesDir)) {
      fs.mkdirSync(this._nodeModulesDir, { recursive: true })
    }

    // 注册 install 工具
    framework.registerTool({
      name: 'install',
      description: '安装 npm 包到指定目录',
      inputSchema: z.object({
        package: z.string().optional().describe('包名，如 lodash、lodash@4.17.21 或 @scope/package'),
        path: z.string().optional().describe('安装目标目录，如 .agent/plugins/my-plugin（默认为 .agent）'),
        file: z.string().optional().describe('本地 package.json 路径，从该文件安装所有依赖')
      }),
      execute: async (args) => {
        const { package: packageName, path: targetPath, file: packageJsonPath } = args

        // 优先处理 file 参数（从 package.json 安装）
        if (packageJsonPath) {
          const resolvedPath = path.resolve(process.cwd(), packageJsonPath)
          return this._installFromPackageJson(resolvedPath, targetPath)
        }

        // package 和 path 都提供
        if (packageName) {
          return this._installPackage(packageName, targetPath)
        }

        // 只有 path，安装该目录的 package.json
        if (targetPath) {
          const resolvedPath = path.resolve(process.cwd(), targetPath)
          const pkgJson = path.join(resolvedPath, 'package.json')
          if (fs.existsSync(pkgJson)) {
            return this._installFromPackageJson(pkgJson, targetPath)
          }
          return { success: false, error: `package.json not found at ${pkgJson}` }
        }

        // 什么都不提供，报错
        return { success: false, error: 'Must provide package name or package.json path' }
      }
    })

    return this
  }

  /**
   * 安装单个包到指定目录
   * @param {string} packageName - 包名
   * @param {string|null} targetPath - 目标目录，默认为 .agent
   */
  _installPackage(packageName, targetPath = null) {
    try {
      const installPath = targetPath
        ? path.resolve(process.cwd(), targetPath)
        : this._agentDir

      log.info(` Installing ${packageName} to ${installPath}...`)

      // 确保目标目录存在
      if (!fs.existsSync(installPath)) {
        fs.mkdirSync(installPath, { recursive: true })
      }

      // 使用 npm install 安装到指定目录
      execSync(`npm install ${packageName} --prefix "${installPath}"`, {
        stdio: 'inherit',
        cwd: installPath
      })

      log.info(` Successfully installed ${packageName}`)

      return {
        success: true,
        message: `Successfully installed ${packageName} to ${installPath}`
      }
    } catch (err) {
      return {
        success: false,
        error: `Failed to install ${packageName}: ${err.message}`
      }
    }
  }

  /**
   * 从 package.json 安装所有依赖
   * @param {string} packageJsonPath - package.json 路径
   * @param {string|null} targetPath - 目标目录，默认为 package.json 所在目录
   */
  _installFromPackageJson(packageJsonPath, targetPath = null) {
    try {
      const resolvedPkgPath = path.resolve(process.cwd(), packageJsonPath)
      const pkgDir = path.dirname(resolvedPkgPath)
      const installPath = targetPath
        ? path.resolve(process.cwd(), targetPath)
        : pkgDir

      log.info(` Installing dependencies from ${resolvedPkgPath} to ${installPath}...`)

      // 读取 package.json 获取要安装的包
      const pkg = JSON.parse(fs.readFileSync(resolvedPkgPath, 'utf-8'))
      const packages = []

      if (pkg.dependencies) {
        packages.push(...Object.keys(pkg.dependencies))
      }
      if (pkg.devDependencies) {
        packages.push(...Object.keys(pkg.devDependencies))
      }

      if (packages.length === 0) {
        return { success: true, message: 'No dependencies to install' }
      }

      // 确保目标目录存在
      if (!fs.existsSync(installPath)) {
        fs.mkdirSync(installPath, { recursive: true })
      }

      // 使用 npm install 安装
      execSync(`npm install --prefix "${installPath}" --no-save`, {
        stdio: 'inherit',
        cwd: pkgDir
      })

      log.info(` Successfully installed ${packages.length} packages`)

      return {
        success: true,
        message: `Successfully installed ${packages.length} dependencies to ${installPath}`
      }
    } catch (err) {
      return {
        success: false,
        error: `Failed to install from package.json: ${err.message}`
      }
    }
  }

  /**
   * 获取 node_modules 路径，供其他插件使用
   */
  getNodeModulesDir() {
    return this._nodeModulesDir
  }

  /**
   * 添加到 module.paths（让 require 能找到）
   */
  addToModulePaths() {
    if (this._nodeModulesDir && !module.paths.includes(this._nodeModulesDir)) {
      module.paths.unshift(this._nodeModulesDir)
    }
  }

  /**
   * 添加自定义路径到 module.paths
   * @param {string} dir - 目录路径
   */
  addCustomModulePath(dir) {
    if (dir && fs.existsSync(dir) && !module.paths.includes(dir)) {
      module.paths.unshift(dir)
    }
  }
}

module.exports = InstallPlugin
