/**
 * ExplorerLoop - 主自主循环，决定并执行操作
 */

const { Plugin } = require('../../src/core/plugin-base')
const { logger } = require('../../src/utils/logger')
const { Agent } = require('../../src/core/agent')
const { StepExecutor } = require('../../src/capabilities/workflow-engine')
const { SystemPrompts, ThinkModePrompts, FreeThinkPrompts } = require('./constants')

const log = logger.child('Ambient:ExplorerLoop')

class ExplorerLoop {
  constructor(goalManager, reflector, framework, config) {
    this._goalManager = goalManager
    this._reflector = reflector
    this._framework = framework
    this._config = config
    this._running = false
    this._timer = null
    this._lastActionTime = 0
    this._tickCount = 0
    this._recentActivities = []
    this._stepExecutor = new StepExecutor(framework)
    this._ambientAgent = null
    this._initAmbientAgent()
  }

  // ============================================================================
  // 生命周期
  // ============================================================================

  /**
   * 初始化 Ambient 专用子 Agent
   */
  _initAmbientAgent() {
    const aiPlugin = this._framework.pluginManager?.get('ai')
    const llmConfig = aiPlugin ? aiPlugin.getConfig() : {}

    this._ambientAgent = new Agent(this._framework, {
      name: 'ambient-worker',
      systemPrompt: SystemPrompts.ambientWorker,
      model: llmConfig.model,
      provider: llmConfig.provider,
      apiKey: llmConfig.apiKey,
      baseURL: llmConfig.baseURL
    })

    // 注册到主 agent（如果主 agent 已存在）
    if (this._framework._mainAgent) {
      this._registerAmbientWorker(this._framework._mainAgent)
    } else {
      // 等待主 agent 创建
      this._framework.once('agent:created', (agent) => {
        if (this._framework._mainAgent && agent === this._framework._mainAgent) {
          this._registerAmbientWorker(agent)
        }
      })
    }
  }

  /**
   * 注册 ambient-worker 到主 agent
   */
  _registerAmbientWorker(agent) {
    if (!this._ambientAgent) return
    agent.registerSubAgent(
      'ambient-worker',
      this._ambientAgent,
      '后台任务执行器',
      '执行需要 AI 能力的后台任务'
    )
    log.info('ambient-worker subagent registered')
  }

  /**
   * 启动探索循环
   */
  start() {
    if (this._running) return
    this._running = true
    this._scheduleNext()
  }

  /**
   * 停止探索循环
   */
  stop() {
    this._running = false
    if (this._timer) {
      clearTimeout(this._timer)
      this._timer = null
    }
  }

  /**
   * 暂停探索循环
   */
  pause() {
    this._running = false
    if (this._timer) {
      clearTimeout(this._timer)
      this._timer = null
    }
  }

  /**
   * 恢复探索循环
   */
  resume() {
    if (!this._running) {
      this._running = true
      this._scheduleNext()
    }
  }

  /**
   * 检查是否运行中
   */
  isRunning() {
    return this._running
  }

  /**
   * 获取状态
   */
  getStatus() {
    return {
      running: this._running,
      tickCount: this._tickCount,
      lastTick: this._lastActionTime ? new Date(this._lastActionTime) : null,
      recentActivities: this._recentActivities.slice(-10),
      activeGoals: this._goalManager.getActiveGoals().length,
      pendingGoals: this._goalManager.getPendingGoals().length
    }
  }

  // ============================================================================
  // 主循环
  // ============================================================================

  _scheduleNext() {
    if (!this._running) return
    this._timer = setTimeout(() => this._tick(), this._config.tickInterval)
  }

  async _tick() {
    if (!this._running) return

    // 如果处于嵌套执行上下文中，跳过此tick
    try {
      if (this._framework.getExecutionContext) {
        const ctx = this._framework.getExecutionContext()
        if (ctx && ctx.id) {
          // 跳过此tick，重新调度
          this._scheduleNext()
          return
        }
      }
    } catch (e) {
      // getExecutionContext可能不存在，继续执行
    }

    this._tickCount++

    try {
      await this._processGoals()
    } catch (err) {
      log.error('Tick错误:', err.message)
      this._addActivity('error', { message: err.message })
    }
    this._lastActionTime = Date.now()
    // 调度下一次tick
    this._scheduleNext()
  }

  async _processGoals() {
    const activeGoals = this._goalManager.getActiveGoals()

    for (const goal of activeGoals) {
      // 检查冷却时间
      if (Date.now() - this._lastActionTime < this._config.cooldownPeriod) {
        continue
      }

      // 检查目标是否有未处理的事件
      const hasNewEvents = goal.eventsReceived && goal.eventsReceived.length > 0

      // 检查是否是事件驱动目标
      const isEventDriven = goal.conditions?.events && goal.conditions.events.length > 0

      // 事件驱动目标：只有在新事件时才执行 actions
      if (isEventDriven && !hasNewEvents) {
        continue
      }

      // 获取下一个操作
      if (goal.actions && goal.actions.length > 0) {
        // 如果有多个 action，按顺序执行所有 action
        if (goal.actions.length > 1) {
          const eventData = hasNewEvents ? goal.eventsReceived[0] : null
          const results = await this._executeAllActions(goal.actions, eventData)

          // 最后一个结果用于评估
          const lastResult = results.length > 0 ? results[results.length - 1].result : null

          // 评估结果
          const outcome = this._reflector.evaluateOutcome(goal, lastResult)

          if (outcome.goalComplete && !isEventDriven) {
            // 非事件驱动目标可以完成
            this._goalManager.completeGoal(goal.id)
            this._addActivity('goal_completed', { goalId: goal.id, attempts: goal.attempts })
            this._notifyUser('目标完成', `目标 "${goal.title}" 已完成（尝试次数：${goal.attempts}）`, 'success')
          } else if (!outcome.shouldContinue && !isEventDriven) {
            // 非事件驱动目标可以失败
            this._goalManager.failGoal(goal.id, '达到最大尝试次数')
            this._addActivity('goal_failed', { goalId: goal.id, reason: '达到最大尝试次数' })
            this._notifyUser('目标失败', `目标 "${goal.title}" 失败：达到最大尝试次数`, 'error')
          } else {
            // 事件驱动目标：不论结果如何，都重置并继续等待下一事件
            this._addActivity('actions_completed', { goalId: goal.id, actionCount: results.length })
          }

          // 执行操作后清除已处理的事件，并重置 actions 以处理下一事件
          if (hasNewEvents) {
            this._resetGoalForNextEvent(goal)
          }
          continue
        }

        // 单个 action，使用原有逻辑
        const action = goal.actions[0]

        // 循环检测（仅用于非事件驱动的操作）
        if (!hasNewEvents && this._reflector.checkLoopDetection(goal, action.id)) {
          this._addActivity('goal_failed', { goalId: goal.id, reason: '检测到循环' })
          // 通知用户目标失败
          this._notifyUser('目标失败', `目标 "${goal.title}" 失败：检测到循环（同一操作连续重复）`, 'error')
          continue
        }

        // 执行操作
        const result = await this._executeAction(action, hasNewEvents ? goal.eventsReceived[0] : null)

        // 评估结果
        const outcome = this._reflector.evaluateOutcome(goal, result)

        if (outcome.goalComplete) {
          this._goalManager.completeGoal(goal.id)
          this._addActivity('goal_completed', { goalId: goal.id, attempts: goal.attempts })
          // 通知用户目标完成
          this._notifyUser('目标完成', `目标 "${goal.title}" 已完成（尝试次数：${goal.attempts}）`, 'success')
        } else if (!outcome.shouldContinue) {
          this._goalManager.failGoal(goal.id, '达到最大尝试次数')
          this._addActivity('goal_failed', { goalId: goal.id, reason: '达到最大尝试次数' })
          // 通知用户目标失败
          this._notifyUser('目标失败', `目标 "${goal.title}" 失败：达到最大尝试次数`, 'error')
        } else if (outcome.actionTaken) {
          // 从队列中移除已完成的操作
          if (!hasNewEvents) {
            goal.actions.shift()
          }
          this._addActivity('action_executed', { goalId: goal.id, action: action.id, hasEvents: hasNewEvents })
        }

        // 执行操作后清除已处理的事件，并重置 actions 以处理下一事件
        if (hasNewEvents) {
          this._resetGoalForNextEvent(goal)
        }
      }
    }

    // 激活满足条件的待处理目标
    const pendingGoals = this._goalManager.getPendingGoals()
    for (const goal of pendingGoals) {
      // 自动激活没有条件的目标
      // 有条件的目标会在事件触发时被 EventWatcher 自动激活
      if (!goal.conditions || Object.keys(goal.conditions).length === 0) {
        this._goalManager.activateGoal(goal.id)
        this._addActivity('goal_activated', { goalId: goal.id })
      } else {
        // 有条件的目标，立即激活以便开始监听事件
        this._goalManager.activateGoal(goal.id)
        this._addActivity('goal_activated', { goalId: goal.id, reason: '事件监听目标已激活' })
      }
    }
  }

  /**
   * 重置目标以处理下一事件
   */
  _resetGoalForNextEvent(goal) {
    goal.eventsReceived = []
    // 重置 actions 为原始 actions，以便处理下一事件
    if (goal._originalActions) {
      goal.actions = goal._originalActions.slice()
    }
    this._goalManager.updateGoal(goal.id, { eventsReceived: [], actions: goal.actions })
  }

  // ============================================================================
  // Action 执行
  // ============================================================================

  /**
   * 执行单个 action
   * @param {Object} action - action 配置
   * @param {Object} eventData - 事件数据
   * @param {Object} context - 执行上下文（包含 stepOutputs 等）
   * @returns {Promise<Object>} 执行结果
   */
  async _executeAction(action, eventData = null, context = null) {
    if (!this._framework) {
      return { success: false, error: '框架不可用' }
    }

    try {
      // 如果没有提供 context，创建一个新的
      if (!context) {
        context = {
          input: {},
          variables: {
            _event: eventData?.data || eventData || null,
            _eventRaw: eventData || null,
            _action: action
          },
          lastResult: null
        }
      } else {
        // 更新 context 中的 _action
        context.variables._action = action
      }

      // 将 action 转换为 step 配置
      const step = this._actionToStep(action)

      // 解析 step.args 中的变量引用（支持 ${actionId.output} 格式）
      if (step.args) {
        step.args = this._resolveActionArgs(step.args, context)
      }
      if (step.input) {
        step.input = this._resolveActionArgs(step.input, context)
      }

      // message 和 think 类型使用专用子 agent 执行
      if (step.type === 'message' || step.type === 'think') {
        return await this._executeWithAmbientAgent(step, context)
      }

      // 其他类型使用 StepExecutor 直接执行
      const result = await this._stepExecutor.executeStep(step, context)
      return result
    } catch (err) {
      return { success: false, error: err.message }
    }
  }

  /**
   * 解析 action 参数中的变量引用
   * 支持 ${actionId.output}、${actionId.output.field} 和 ${event.xxx} 格式
   */
  _resolveActionArgs(args, context) {
    if (!args || typeof args !== 'object') return args

    const stepOutputs = context.variables._stepOutputs || {}
    const eventData = context.variables._event || {}

    const resolved = {}
    for (const [key, value] of Object.entries(args)) {
      resolved[key] = this._resolveActionValue(value, stepOutputs, eventData)
    }
    return resolved
  }

  /**
   * 解析单个值中的 ${actionId.output} 引用和 ${event.xxx} 引用
   */
  _resolveActionValue(value, stepOutputs, eventData) {
    if (typeof value === 'string') {
      // 处理 ${actionId.output} 和 ${actionId.output.field} 格式
      const result = value.replace(/\$\{([^}]+)\}/g, (match, path) => {
        if (path === 'output' || path === 'result') {
          // {{result}} 引用上一步结果
          return stepOutputs._lastResult ?? match
        }
        if (path.startsWith('event.')) {
          // ${event.xxx} 引用事件数据
          let eventPath = path.replace(/^event\./, '')
          // 优先在 eventData.data 中查找（因为事件数据通常存储在 data 字段）
          if (eventData?.data) {
            let val = this._getNestedValue(eventData.data, eventPath)
            if (val !== undefined) return val
          }
          // 再尝试直接在 eventData 中查找
          let val = this._getNestedValue(eventData, eventPath)
          if (val !== undefined) return val
          // 兼容：如果 path 是 event.data.xxx 但 eventData 没有 data，尝试跳过一层
          if (eventPath.startsWith('data.')) {
            eventPath = eventPath.replace(/^data\./, '')
            val = this._getNestedValue(eventData, eventPath)
            if (val !== undefined) return val
          }
          // 特殊回退：如果查找 body 但找不到，尝试 text（邮件数据中用 text）
          if (eventPath === 'body' || eventPath === 'text') {
            const textVal = this._getNestedValue(eventData?.data, 'text')
            if (textVal !== undefined) return textVal
          }
          return match
        }
        if (path === 'event') {
          // ${event} 引用整个事件数据对象
          return eventData ?? match
        }
        if (path.includes('.')) {
          // ${actionId.output.field} 格式
          const [actionId, ...fieldParts] = path.split('.')
          if (actionId === 'result' || actionId === 'output') {
            // {{result.field}} 格式
            const val = this._getNestedValue(stepOutputs._lastResult, fieldParts.join('.'))
            return val !== undefined ? val : match
          }
          const actionOutput = stepOutputs[actionId]
          if (actionOutput !== undefined) {
            const val = this._getNestedValue(actionOutput, fieldParts.join('.'))
            return val !== undefined ? val : match
          }
        } else {
          // ${actionId.output} 格式
          const actionOutput = stepOutputs[path]
          if (actionOutput !== undefined) return actionOutput
        }
        return match
      })
      return result
    } else if (Array.isArray(value)) {
      return value.map(v => this._resolveActionValue(v, stepOutputs, eventData))
    } else if (typeof value === 'object' && value !== null) {
      const resolved = {}
      for (const [k, v] of Object.entries(value)) {
        resolved[k] = this._resolveActionValue(v, stepOutputs, eventData)
      }
      return resolved
    }
    return value
  }

  _getNestedValue(obj, path) {
    if (!obj) return undefined
    const parts = path.split('.')
    let current = obj
    for (const part of parts) {
      if (current === null || current === undefined) return undefined
      current = current[part]
    }
    return current
  }

  /**
   * 按顺序执行所有 actions
   * @param {Array} actions - action 数组
   * @param {Object} eventData - 事件数据
   * @returns {Promise<Array>} 所有执行结果
   */
  async _executeAllActions(actions, eventData = null) {
    const results = []
    const stepOutputs = {}

    const context = {
      input: {},
      variables: {
        _event: eventData?.data || eventData || null,
        _eventRaw: eventData || null,
        _stepOutputs: stepOutputs
      },
      lastResult: null
    }

    for (const action of actions) {
      // 执行前更新 stepOutputs
      context.variables._stepOutputs = stepOutputs

      const result = await this._executeAction(action, eventData, context)

      // 保存结果：使用 action id 作为键
      if (action.id) {
        stepOutputs[action.id] = result
      }
      // 同时保存为 _lastResult 供 {{result}} 引用
      stepOutputs._lastResult = result
      context.lastResult = result

      results.push({ actionId: action.id, result })

      // 如果执行失败，停止执行
      if (result && result.success === false) {
        break
      }
    }

    return results
  }

  /**
   * 使用 ambient 子 agent 执行 AI 相关操作
   */
  async _executeWithAmbientAgent(step, context) {
    if (!this._ambientAgent) {
      return { success: false, error: 'Ambient agent 未初始化' }
    }

    if (step.type === 'message') {
      let content = step.content || ''
      content = this._stepExecutor._resolveValue(content, context)

      if (context.variables._event) {
        content = `${content}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
      }

      try {
        const result = await this._ambientAgent.pushMessage(content)
        return { success: true, result }
      } catch (err) {
        return { success: false, error: err.message }
      }
    }

    if (step.type === 'think') {
      const thinkPlugin = this._framework.pluginManager?.get('think')
      if (!thinkPlugin) {
        return { success: false, error: '思考插件不可用' }
      }

      let topic = step.topic || 'Ambient代理反思'
      topic = this._stepExecutor._resolveValue(topic, context)

      if (context.variables._event) {
        topic = `${topic}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
      }

      try {
        const result = await thinkPlugin._triggerThinking({
          topic,
          mode: step.mode || 'reflect',
          depth: step.depth || 2
        })
        return result
      } catch (err) {
        return { success: false, error: err.message }
      }
    }

    return { success: false, error: `未知 AI 操作类型: ${step.type}` }
  }

  /**
   * 将 action 转换为 step 配置
   */
  _actionToStep(action) {
    const step = {
      id: action.id || `action_${Date.now()}`,
      type: action.type,
      name: action.name || action.id
    }

    switch (action.type) {
      case 'tool':
        step.tool = action.name
        step.args = action.args || {}
        break
      case 'message':
        step.content = action.content || ''
        break
      case 'think':
        step.topic = action.topic || 'Ambient代理反思'
        step.mode = action.mode || 'reflect'
        step.depth = action.depth || 2
        break
    }

    return step
  }

  // ============================================================================
  // 辅助方法
  // ============================================================================

  _getActiveAgent() {
    if (this._framework._mainAgent) {
      return this._framework._mainAgent
    }
    const agents = this._framework._agents || []
    return agents.length > 0 ? agents[agents.length - 1] : null
  }

  _addActivity(type, data) {
    this._recentActivities.push({
      type,
      data,
      timestamp: new Date()
    })
    // 只保留最近50条活动记录
    if (this._recentActivities.length > 50) {
      this._recentActivities = this._recentActivities.slice(-50)
    }
  }

  /**
   * 通知用户（通过事件发送给消息插件）
   */
  _notifyUser(title, message, level = 'info') {
    if (!this._framework) return

    // 获取目标相关的sessionId（如果有）
    let sessionId = null
    const sessionPlugin = this._framework.pluginManager.get('session')
    if (sessionPlugin) {
      const sessions = sessionPlugin.listSessions()
      if (sessions.length > 0) {
        // 取最新的会话
        sessions.sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
        sessionId = sessions[0].id
      }
    }

    // 发送统一的通知事件
    this._framework.emit('notification', {
      title,
      message,
      source: 'ambient',
      level,  // 'info' | 'warning' | 'success' | 'error'
      sessionId,
      timestamp: new Date()
    })

    log.info(`${title}: ${message}`)
  }
}

module.exports = { ExplorerLoop }
