/**
 * Scheduler 定时任务调度插件
 * 支持 Cron 表达式、绝对时间、相对时间调度
 * 任务触发时自动唤醒 Agent 发送消息
 */

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

// 尝试加载 node-cron
let cron = null
try {
  cron = require('node-cron')
} catch (e) {
  log.warn(' node-cron not installed, cron tasks will not work')
}

// ============================================================================
// TaskStore - 持久化任务到 .agent/data/scheduler/tasks.json
// ============================================================================
class TaskStore {
  constructor(persistencePath) {
    this._persistencePath = persistencePath
    this._ensureDir()
  }

  _ensureDir() {
    if (!fs.existsSync(this._persistencePath)) {
      fs.mkdirSync(this._persistencePath, { recursive: true })
    }
  }

  _getTasksPath() {
    return path.join(this._persistencePath, 'tasks.json')
  }

  saveTasks(tasks) {
    try {
      // 序列化时移除不可保存的字段（timer, cronTask）
      const serializable = tasks.map(t => ({
        id: t.id,
        name: t.name,
        type: t.type,
        message: t.message,
        enabled: t.enabled,
        createdAt: t.createdAt,
        lastRun: t.lastRun,
        runCount: t.runCount,
        runAt: t.runAt,
        cronExpression: t.cronExpression,
        sessionId: t.sessionId,
        llm: t.llm,
        persistDelay: t.persistDelay,  // 相对时间的延迟毫秒数
        persistNextRun: t.persistNextRun  // 下次执行时间
      }))
      fs.writeFileSync(this._getTasksPath(), JSON.stringify(serializable, null, 2))
    } catch (err) {
      log.error(' 保存任务失败:', err.message)
    }
  }

  loadTasks() {
    try {
      const filePath = this._getTasksPath()
      if (fs.existsSync(filePath)) {
        const data = fs.readFileSync(filePath, 'utf-8')
        return JSON.parse(data)
      }
    } catch (err) {
      log.error(' 加载任务失败:', err.message)
    }
    return []
  }
}

// 时间解析辅助函数
function parseDelay(delayStr) {
  const match = delayStr.match(/^(\d+)\s*(second|minute|hour|day|week)s?$/i)
  if (!match) return null
  const value = parseInt(match[1])
  const unit = match[2].toLowerCase()
  const multipliers = {
    second: 1000,
    minute: 60 * 1000,
    hour: 60 * 60 * 1000,
    day: 24 * 60 * 60 * 1000,
    week: 7 * 24 * 60 * 60 * 1000
  }
  return value * (multipliers[unit] || 1000)
}

function parseAtTime(timeStr) {
  const now = new Date()
  // 简单时间格式 "12:00"
  const timeMatch = timeStr.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/)
  if (timeMatch) {
    const date = new Date(now)
    date.setHours(parseInt(timeMatch[1]), parseInt(timeMatch[2]), parseInt(timeMatch[3] || 0), 0)
    if (date <= now) {
      date.setDate(date.getDate() + 1)
    }
    return date
  }
  return new Date(timeStr)
}

/**
 * 生成唯一 ID
 */
function generateId() {
  if (require('crypto').randomUUID) {
    return require('crypto').randomUUID()
  }
  return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
}

class SchedulerPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'scheduler'
    this.version = '1.0.0'
    this.description = '定时任务调度插件，支持 Cron 表达式、绝对时间、相对时间'
    this.priority = 15
    this.system = true
    this.config = {
      checkInterval: config.checkInterval || 1000,  // 每秒检查一次
      persistencePath: config.persistencePath || '.agent/data/scheduler'
    }

    this._framework = null
    this._agent = null
    this._tasks = new Map()
    this._timer = null
    this._taskStore = null
    this._taskStats = {
      total: 0,
      running: 0,
      completed: 0,
      failed: 0
    }
  }

  install(framework) {
    this._framework = framework
    // 初始化任务存储
    this._taskStore = new TaskStore(this.config.persistencePath)
    return this
  }

  /**
   * 获取 Agent 实例
   */
  _getAgent() {
    if (this._agent) return this._agent
    if (this._framework._mainAgent) {
      this._agent = this._framework._mainAgent
    } else {
      const agents = this._framework._agents || []
      this._agent = agents.length > 0 ? agents[agents.length - 1] : null
    }
    return this._agent
  }

  start(framework) {
    // 获取 Agent 实例
    this._agent = this._getAgent()

    // 注册调度工具
    framework.registerTool({
      name: 'schedule_task',
      description: '设置定时提醒任务。支持多种时间格式：相对时间(1 minute, 2 hours)、具体时间(12:00)、Cron表达式(* * * * *)。系统会自动判断任务是否需要 LLM 处理。',
      inputSchema: z.object({
        name: z.string().optional().describe('任务名称'),
        scheduleTime: z.string().describe('执行时间。支持格式：\n- 相对时间: "1 minute", "2 hours", "1 day"\n- 具体时间: "12:00", "14:30"\n- Cron表达式: "*/5 * * * *" (每5分钟)'),
        message: z.string().describe('提醒消息内容。系统会自动判断：\n- 简单提醒（喝水、吃饭）直接显示\n- 需要查询/分析的任务（查看列表、分析数据）自动启用 LLM'),
        repeat: z.boolean().optional().describe('是否重复执行 (默认 false)'),
        cronExpression: z.string().optional().describe('Cron 表达式 (当 repeat 为 true 时使用)'),
        sessionId: z.string().optional().describe('会话 ID（提醒将发送到该会话，不填则使用默认会话）'),
        llm: z.boolean().optional().describe('是否需要 LLM 处理（自动检测，可手动覆盖）')
      }),
      execute: async (args) => {
        try {
          const { scheduleTime, message, repeat, cronExpression, sessionId } = args
          const agent = this._getAgent()
          if (!agent) {
            return { success: false, error: 'Agent not available' }
          }

          // 如果没有指定 sessionId，优先从执行上下文获取（来自 WeChat 等消息源）
          let targetSessionId = sessionId
          if (!targetSessionId) {
            const ctx = this._framework.getExecutionContext()
            if (ctx?.sessionId) {
              targetSessionId = ctx.sessionId
            }
          }
          // 如果执行上下文也没有，从 sessionPlugin 获取最近活跃会话
          if (!targetSessionId) {
            const sessionPlugin = this._framework.pluginManager.get('session')
            if (sessionPlugin) {
              const sessions = sessionPlugin.listSessions()
              // 获取最近的活跃会话
              if (sessions.length > 0) {
                // 按 lastActive 排序，取最新的
                sessions.sort((a, b) => {
                  const aTime = a.lastActive ? new Date(a.lastActive).getTime() : 0
                  const bTime = b.lastActive ? new Date(b.lastActive).getTime() : 0
                  return bTime - aTime
                })
                targetSessionId = sessions[0].id
                //log.info(` Auto-detected active session: ${targetSessionId}`)
              }
            }
          }

          const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
          let task

          // 自动检测是否需要 LLM 处理
          const LLM_KEYWORDS = [
            '分析', '查询', '查看', '检查', '总结', '搜索', '获取',
            'list', 'get', 'check', 'search', 'find', 'fetch',
            '什么', '如何', '为什么', '什么时候', '多少', '谁',
            '今天', '明天', '昨天', '这周', '这月', '今年'
          ]
          const messageLower = message.toLowerCase()
          const needsLLM = args.llm === true || LLM_KEYWORDS.some(kw =>
            message.includes(kw) || messageLower.includes(kw.toLowerCase())
          )
          const llmMode = needsLLM

          // 检测是否像 Cron 表达式
          const isCron = /^[\d*,\/-\s]+$/.test(scheduleTime) && scheduleTime.split(' ').length >= 5

          if (isCron || repeat) {
            // Cron 任务
            if (!cron) {
              return { success: false, error: 'node-cron not installed' }
            }
            task = {
              id: taskId,
              name: args.name || 'CronTask',
              type: 'cron',
              cronExpression: cronExpression || scheduleTime,
              message,
              enabled: true,
              createdAt: new Date(),
              lastRun: null,
              runCount: 0,
              timer: null,
              cronTask: null,
              sessionId: targetSessionId || null,
              llm: llmMode
            }

            // 使用 node-cron 调度
            task.cronTask = cron.schedule(task.cronExpression, async () => {
              await this._executeTask(task)
            })
          } else if (scheduleTime.includes(':')) {
            // 具体时间
            const runAt = parseAtTime(scheduleTime)
            task = {
              id: taskId,
              name: args.name || 'Reminder',
              type: 'once',
              runAt,
              message,
              enabled: true,
              createdAt: new Date(),
              lastRun: null,
              runCount: 0,
              timer: null,
              sessionId: targetSessionId || null,
              llm: llmMode
            }
            task.timer = setTimeout(async () => {
              await this._executeTask(task)
            }, runAt.getTime() - Date.now())
          } else {
            // 相对时间
            const delayMs = parseDelay(scheduleTime)
            if (!delayMs) {
              return { success: false, error: '无效的时间格式' }
            }
            const runAt = new Date(Date.now() + delayMs)
            task = {
              id: taskId,
              name: args.name || 'Reminder',
              type: 'once',
              runAt,
              message,
              enabled: true,
              createdAt: new Date(),
              lastRun: null,
              runCount: 0,
              timer: null,
              sessionId: targetSessionId || null,
              llm: llmMode,
              persistDelay: delayMs  // 保存延迟毫秒数用于持久化
            }
            task.timer = setTimeout(async () => {
              await this._executeTask(task)
            }, delayMs)
          }

          this._tasks.set(task.id, task)
          this._taskStats.total++
          this._saveTasks()  // 持久化

          // 发送任务创建事件
          this._framework.emit('scheduler:task_created', {
            taskId: task.id,
            taskName: task.name,
            type: task.type,
            scheduleTime,
            cronExpression: task.cronExpression
          })

          return {
            success: true,
            taskId: task.id,
            name: task.name,
            scheduleTime,
            executeAt: task.runAt ? task.runAt.toISOString() : null,
            cronExpression: task.cronExpression,
            message: repeat ? '定时任务已创建 (重复执行)' : '提醒已设置',
            sessionId: sessionId || 'default',
            llm: llmMode
          }
        } catch (err) {
          return { success: false, error: err.message }
        }
      }
    })

    framework.registerTool({
      name: 'schedule_list',
      description: '列出所有定时任务',
      inputSchema: z.object({}),
      execute: async () => {
        const tasks = Array.from(this._tasks.values()).map(t => ({
          id: t.id,
          name: t.name,
          type: t.type,
          message: t.message,
          enabled: t.enabled,
          nextRun: t.nextRun || t.runAt,
          runCount: t.runCount,
          lastRun: t.lastRun,
          cronExpression: t.cronExpression,
          llm: t.llm,
          sessionId: t.sessionId
        }))

        return {
          success: true,
          tasks,
          total: tasks.length,
          stats: { ...this._taskStats }
        }
      }
    })

    framework.registerTool({
      name: 'schedule_cancel',
      description: '取消定时任务',
      inputSchema: z.object({
        taskId: z.string().describe('任务 ID')
      }),
      execute: async (args) => {
        const task = this._tasks.get(args.taskId)
        if (!task) {
          return { success: false, error: 'Task not found' }
        }

        const taskName = task.name
        this._cancelTask(task)
        this._saveTasks()  // 持久化

        // 发送任务取消通知
        this._framework.emit('notification', {
          title: '任务已取消',
          message: `定时任务 "${taskName}" 已取消`,
          source: 'scheduler',
          level: 'info',
          sessionId: task.sessionId,
          timestamp: new Date()
        })

        return { success: true, cancelled: args.taskId }
      }
    })

    framework.registerTool({
      name: 'cron_examples',
      description: '获取常用 Cron 表达式示例',
      inputSchema: z.object({}),
      execute: async () => {
        return {
          examples: [
            { expression: '* * * * *', description: '每分钟' },
            { expression: '*/5 * * * *', description: '每5分钟' },
            { expression: '*/15 * * * *', description: '每15分钟' },
            { expression: '0 * * * *', description: '每小时' },
            { expression: '0 9 * * *', description: '每天早上9点' },
            { expression: '0 12 * * *', description: '每天中午12点' },
            { expression: '0 18 * * *', description: '每天下午6点' },
            { expression: '0 9 * * 1-5', description: '工作日上午9点' },
            { expression: '0 9 * * 0,6', description: '周末上午9点' },
            { expression: '0 9 * * 1', description: '每周一上午9点' },
            { expression: '0 */2 * * *', description: '每2小时' }
          ]
        }
      }
    })

    // 启动调度循环（用于检查一次性任务）
    this._startScheduler()

    // 加载持久化的任务
    this._loadPersistedTasks()

    return this
  }

  /**
   * 启动调度循环
   */
  _startScheduler() {
    if (this._timer) {
      clearInterval(this._timer)
    }

    this._timer = setInterval(() => {
      this._checkTasks()
    }, this.config.checkInterval)
  }

  /**
   * 检查任务状态（主要用于更新 stats）
   */
  _checkTasks() {
    for (const [id, task] of this._tasks) {
      if (!task.enabled) continue
      // 统计信息更新
    }
  }

  /**
   * 保存任务到持久化存储
   */
  _saveTasks() {
    if (this._taskStore) {
      this._taskStore.saveTasks(Array.from(this._tasks.values()))
    }
  }

  /**
   * 加载持久化的任务并重新调度
   */
  _loadPersistedTasks() {
    if (!this._taskStore) return

    const savedTasks = this._taskStore.loadTasks()
    if (!savedTasks || savedTasks.length === 0) return

    log.info(` 加载 ${savedTasks.length} 个持久化任务...`)

    for (const saved of savedTasks) {
      // 跳过已过期的任务或已清理的任务
      if (saved.type === 'once' && saved.runCount > 0) {
        log.info(` 跳过已完成的一次性任务: ${saved.name}`)
        continue
      }

      let task = { ...saved }

      // 重新调度 Cron 任务
      if (task.type === 'cron' && task.enabled && cron) {
        try {
          task.cronTask = cron.schedule(task.cronExpression, async () => {
            await this._executeTask(task)
          })
          this._tasks.set(task.id, task)
          this._taskStats.total++
          log.info(` 已恢复 Cron 任务: ${task.name}`)
        } catch (err) {
          log.error(` 恢复 Cron 任务失败: ${task.name}`, err.message)
        }
      }
      // 重新调度相对时间任务（计算新的执行时间）
      else if (task.type === 'once' && task.enabled && task.persistDelay) {
        const newDelay = task.persistDelay
        if (newDelay > 0) {
          task.runAt = new Date(Date.now() + newDelay)
          task.timer = setTimeout(async () => {
            await this._executeTask(task)
          }, newDelay)
          this._tasks.set(task.id, task)
          this._taskStats.total++
          log.info(` 已恢复一次性任务: ${task.name}，将在 ${newDelay}ms 后执行`)
        }
      }
      // 重新调度绝对时间任务
      else if (task.type === 'once' && task.enabled && task.runAt) {
        const runAt = new Date(task.runAt)
        if (runAt > new Date()) {
          const delay = runAt.getTime() - Date.now()
          task.timer = setTimeout(async () => {
            await this._executeTask(task)
          }, delay)
          this._tasks.set(task.id, task)
          this._taskStats.total++
          log.info(` 已恢复一次性任务: ${task.name}，将在 ${runAt} 执行`)
        } else {
          log.info(` 跳过已过期的任务: ${task.name}`)
        }
      }
    }
  }

  /**
   * 取消任务
   */
  _cancelTask(task) {
    if (task.timer) {
      clearTimeout(task.timer)
      task.timer = null
    }
    if (task.cronTask) {
      task.cronTask.stop()
      task.cronTask = null
    }
    task.enabled = false
  }

  /**
   * 执行任务
   */
  async _executeTask(task) {
    // log.info(` Executing task: ${task.name} (${task.id})`)
    // log.info(` Message: ${task.message}`)
    // if (task.sessionId) {
    //   log.info(` Target session: ${task.sessionId}`)
    // }
    // log.info(` LLM mode: ${task.llm ? 'enabled' : 'disabled'}`)

    task.lastRun = new Date()
    task.runCount++
    this._taskStats.running++

    try {
      if (task.llm) {
        // LLM 模式：使用子Agent处理
        const schedulerAgent = this._framework.createSubAgent({
          name: 'scheduler_task',
          role: '定时任务执行助手，专注于处理定时提醒和任务执行'
        })

        const result = await schedulerAgent.chat(task.message)

        this._taskStats.completed++

        // 获取 LLM 返回的消息
        let responseText = ''
        if (result && result.message) {
          responseText = result.message
        } else if (result && result.text) {
          responseText = result.text
        }

        // if (responseText) {
        //   console.log(`\n🔔 [定时提醒] ${responseText}\n`)
        // }

        // 发送统一的通知事件
        this._framework.emit('notification', {
          title: task.name,
          message: responseText || task.message,
          source: 'scheduler',
          level: 'info',
          sessionId: task.sessionId,
          timestamp: new Date()
        })
      } else {
        // 直接显示模式：只显示提醒，不发 LLM
        //console.log(`\n🔔 [定时提醒] ${task.message}\n`)

        // 发送统一的通知事件
        this._framework.emit('notification', {
          title: task.name,
          message: task.message,
          source: 'scheduler',
          level: 'info',
          sessionId: task.sessionId,
          timestamp: new Date()
        })

        this._taskStats.completed++
      }

      // 一次性任务执行后清理
      if (task.type === 'once' && !task.cronTask) {
        this._cleanupTask(task.id)
      }

      return { success: true }
    } catch (err) {
      this._taskStats.failed++
      log.error(` Task ${task.name} failed: ${err.message}`)

      // 发送统一的通知事件
      this._framework.emit('notification', {
        title: `任务失败: ${task.name}`,
        message: err.message,
        source: 'scheduler',
        level: 'error',
        sessionId: task.sessionId,
        timestamp: new Date()
      })

      // 一次性任务失败后也清理
      if (task.type === 'once' && !task.cronTask) {
        this._cleanupTask(task.id)
      }

      return { error: err.message }
    } finally {
      this._taskStats.running--
    }
  }

  /**
   * 清理任务
   */
  _cleanupTask(taskId) {
    const task = this._tasks.get(taskId)
    if (task) {
      if (task.timer) {
        clearTimeout(task.timer)
        task.timer = null
      }
      if (task.cronTask) {
        task.cronTask.stop()
        task.cronTask = null
      }
      this._tasks.delete(taskId)
      this._saveTasks()  // 持久化
    }
  }

  /**
   * 停止所有任务
   */
  stopAll() {
    for (const task of this._tasks.values()) {
      this._cancelTask(task)
    }

    if (this._timer) {
      clearInterval(this._timer)
      this._timer = null
    }

    // 保存状态
    this._saveTasks()
  }

  reload(framework) {
    this._framework = framework
    this._agent = this._getAgent()
    this._startScheduler()
    // 重新加载持久化任务
    this._loadPersistedTasks()
  }

  uninstall(framework) {
    this.stopAll()
    this._tasks.clear()
    this._taskStats = { total: 0, running: 0, completed: 0, failed: 0 }
    this._framework = null
    this._agent = null
  }
}

module.exports = SchedulerPlugin
