/**
 * Rules 规则引擎插件
 * 控制工具调用权限、内容过滤、触发动作
 */

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

/**
 * 内置规则类型
 */
const RuleType = {
  ALLOW: 'allow',      // 允许
  DENY: 'deny',        // 拒绝
  TRANSFORM: 'transform',  // 转换
  RATE_LIMIT: 'rate_limit' // 限流
}

/**
 * 规则评估结果
 */
class RuleResult {
  constructor(allowed, rule = null, transform = null) {
    this.allowed = allowed
    this.rule = rule
    this.transform = transform
  }
}

class RulesPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'rules'
    this.version = '1.0.0'
    this.description = '规则引擎插件，用于控制工具调用权限、内容过滤、触发动作'
    this.priority = 25
    this.system = true 
    
    this.config = {
      rulesDir: config.rulesDir || '.agent/rules',
      autoLoad: config.autoLoad !== false
    }

    this._framework = null
    this._rules = []
    this._ruleStats = {
      total: 0,
      allowed: 0,
      denied: 0,
      transformed: 0
    }
  }

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

  start(framework) {
    // 自动加载规则文件
    if (this.config.autoLoad && this.config.rulesDir) {
      this.loadFromDirectory(this.config.rulesDir)
    }

    // 注册规则管理工具
    framework.registerTool({
      name: 'rules_list',
      description: '列出所有规则',
      inputSchema: z.object({}),
      execute: async () => {
        return {
          success: true,
          rules: this._rules.map(r => ({
            name: r.name,
            type: r.type,
            target: r.target,
            description: r.description,
            enabled: r.enabled
          })),
          total: this._rules.length
        }
      }
    })

    framework.registerTool({
      name: 'rules_add',
      description: '添加规则',
      inputSchema: z.object({
        name: z.string().describe('规则名称'),
        type: z.enum(['allow', 'deny', 'transform']).describe('规则类型'),
        target: z.string().describe('目标 (工具名, *, @event-type)'),
        pattern: z.string().optional().describe('匹配模式 (正则表达式)'),
        description: z.string().optional().describe('规则描述'),
        action: z.object({}).optional().describe('规则动作 (transform 时使用)')
      }),
      execute: async (args) => {
        const rule = {
          name: args.name,
          type: args.type,
          target: args.target,
          pattern: args.pattern ? new RegExp(args.pattern) : null,
          description: args.description || '',
          action: args.action || {},
          enabled: true
        }
        this._rules.push(rule)
        return { success: true, rule: rule.name }
      }
    })

    framework.registerTool({
      name: 'rules_remove',
      description: '移除规则',
      inputSchema: z.object({
        name: z.string().describe('规则名称')
      }),
      execute: async (args) => {
        const index = this._rules.findIndex(r => r.name === args.name)
        if (index === -1) {
          return { success: false, error: 'Rule not found' }
        }
        this._rules.splice(index, 1)
        return { success: true, removed: args.name }
      }
    })

    framework.registerTool({
      name: 'rules_stats',
      description: '获取规则统计',
      inputSchema: z.object({}),
      execute: async () => {
        return {
          success: true,
          stats: { ...this._ruleStats }
        }
      }
    })

    framework.registerTool({
      name: 'rules_test',
      description: '测试规则匹配',
      inputSchema: z.object({
        target: z.string().describe('目标 (工具名或事件类型)'),
        input: z.object({}).optional().describe('输入参数')
      }),
      execute: async (args) => {
        const result = this.evaluate(args.target, args.input || {})
        return {
          success: true,
          target: args.target,
          result: {
            allowed: result.allowed,
            ruleName: result.rule?.name || null,
            ruleType: result.rule?.type || null
          }
        }
      }
    })

    return this
  }

  /**
   * 从目录加载规则文件
   */
  loadFromDirectory(rulesDir) {
    const resolvedDir = path.resolve(process.cwd(), rulesDir)

    if (!fs.existsSync(resolvedDir)) {
      log.info(` Rules directory not found: ${resolvedDir}`)
      return
    }

    try {
      const files = fs.readdirSync(resolvedDir).filter(f => f.endsWith('.json'))

      for (const file of files) {
        const filePath = path.join(resolvedDir, file)
        const content = fs.readFileSync(filePath, 'utf-8')
        const rules = JSON.parse(content)

        for (const rule of rules) {
          if (rule.pattern) {
            rule.pattern = new RegExp(rule.pattern)
          }
          rule.enabled = rule.enabled !== false
          this._rules.push(rule)
        }

        log.info(` Loaded ${rules.length} rules from ${file}`)
      }
    } catch (err) {
      log.error(` Failed to load rules: ${err.message}`)
    }
  }

  /**
   * 评估目标是否符合规则
   * @param {string} target - 目标 (工具名, *, @event-type)
   * @param {Object} input - 输入参数
   * @returns {RuleResult}
   */
  evaluate(target, input = {}) {
    this._ruleStats.total++

    // 按优先级排序规则 (先加载的在前)
    for (const rule of this._rules) {
      if (!rule.enabled) continue

      // 匹配目标
      if (rule.target !== '*' && rule.target !== target) continue

      // 匹配模式 (如果有)
      if (rule.pattern) {
        const targetStr = typeof input === 'string' ? input : JSON.stringify(input)
        if (!rule.pattern.test(targetStr)) continue
      }

      // 评估规则
      if (rule.type === RuleType.DENY) {
        this._ruleStats.denied++
        return new RuleResult(false, rule)
      }

      if (rule.type === RuleType.ALLOW) {
        this._ruleStats.allowed++
        return new RuleResult(true, rule)
      }

      if (rule.type === RuleType.TRANSFORM) {
        this._ruleStats.transformed++
        return new RuleResult(true, rule, rule.action)
      }
    }

    // 没有匹配规则，默认允许
    this._ruleStats.allowed++
    return new RuleResult(true)
  }

  /**
   * 检查工具调用是否允许
   */
  checkToolCall(toolName, args) {
    return this.evaluate(toolName, args)
  }

  /**
   * 检查消息是否允许
   */
  checkMessage(message, context) {
    return this.evaluate('@message', { message, context })
  }

  /**
   * 添加规则
   */
  addRule(rule) {
    this._rules.push(rule)
  }

  /**
   * 移除规则
   */
  removeRule(name) {
    const index = this._rules.findIndex(r => r.name === name)
    if (index !== -1) {
      this._rules.splice(index, 1)
      return true
    }
    return false
  }

  reload(framework) {
    this._framework = framework
    this._rules = []
    this._ruleStats = { total: 0, allowed: 0, denied: 0, transformed: 0 }

    if (this.config.autoLoad && this.config.rulesDir) {
      this.loadFromDirectory(this.config.rulesDir)
    }
  }

  uninstall(framework) {
    this._rules = []
    this._ruleStats = { total: 0, allowed: 0, denied: 0, transformed: 0 }
    this._framework = null
  }
}

module.exports = RulesPlugin