/**
 * Telegram 插件
 * 支持绑定主Agent进行持续对话
 *
 * 配置：
 * - botToken: Telegram Bot Token (必需)
 * - allowedChats: 允许的聊天ID数组
 * - groupMode: 是否启用群组模式
 * - prefix: 命令前缀
 */

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

// 转义 MarkdownV2 特殊字符
function escapeMarkdown(text) {
  if (!text) return ''
  return text.replace(/([\_*\[\]()~`>#+\-=|{}.!])/g, '\\$1')
}

class TelegramPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'telegram'
    this.version = '2.1.0'
    this.description = 'Telegram 对话插件，绑定主Agent进行持续对话'
    this.priority = 80
    this.enabled = false
    this.systemPrompt = `你是一个有帮助的AI助手。回复内容不要使用markdown格式文本。
    
**重要:** 子Agent 匹配规则必须遵守：
- 根据【子 Agent 匹配表】，将任务委托给最匹配的子Agent处理
- 使用 subagent_call 工具并指定 agentName 来委托任务
- 只有当没有匹配的子Agent时，才直接调用工具

**命令执行规范：**
- 执行 npx skills add / npx skills remove / npx skills list 命令时，必须自动添加参数：-a openclaw -y
- 禁止添加 -g 参数
- 例如：npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`

    this.config = {
      botToken: config.botToken || process.env.TELEGRAM_BOT_TOKEN,
      allowedChats: config.allowedChats || [],
      groupMode: config.groupMode || false,
      prefix: config.prefix || '/'
    }

    this._framework = null
    this._bot = null
    this._sessionPlugin = null
    this._sessionDeleteHandler = null
    this._sessionAgents = new Map()
  }

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

  start(framework) {
    if (!this.config.botToken) {
      log.warn(' No bot token. Set TELEGRAM_BOT_TOKEN env var.')
      return this
    }

    this._framework = framework
    this._sessionPlugin = framework.pluginManager.get('session')

    if (this._sessionPlugin) {
      this._sessionDeleteHandler = (sessionId) => {
        if (sessionId.startsWith('telegram_')) {
          log.info(` Session deleted: ${sessionId}`)
        }
      }
      this._sessionPlugin.on('session:deleted', this._sessionDeleteHandler)
    }

    this._initBot()
    return this
  }

  _initBot() {
    try {
      const TelegramBot = require('node-telegram-bot-api')
      this._bot = new TelegramBot(this.config.botToken, { polling: true })

      log.info(' Bot started successfully')

      this._bot.setMyCommands([
        { command: 'start', description: '显示帮助信息' },
        { command: 'clear', description: '清除对话历史' },
        { command: 'history', description: '查看对话状态' }
      ]).catch((err) => {
        log.error(' Failed to register commands:', err.message)
      })

      this._bot.on('message', (msg) => this._handleMessage(msg))
      this._bot.on('edit_message', (msg) => this._handleEdit(msg))
      this._bot.on('callback_query', (query) => this._handleCallback(query))
      this._bot.on('polling_error', (err) => log.error(' Polling error:', err.message))
      this._bot.on('error', (err) => log.error(' Bot error:', err.message))

      if (this._framework) {
        this._framework.on('agent:created', (agent) => {
          log.info(' New agent created:', agent.name)
        })

        // 监听统一通知事件
        this._framework.on('notification', async (data) => {
          await this._handleNotification(data)
        })

        // 监听 webhook 事件
        this._framework.on('webhook:received', async (data) => {
          await this._handleWebhookNotification(data)
        })
      }
    } catch (err) {
      log.error(' Failed to initialize bot:', err.message)
    }
  }

  /**
   * 处理统一通知
   */
  async _handleNotification(data) {
    const { title, message, source, level } = data

    if (!this._bot) {
      log.warn(' Bot not ready, cannot send notification')
      return
    }

    // 确定 chatId
    let chatId = null
    let effectiveSessionId = data.sessionId

    // 如果没有 sessionId，尝试从执行上下文获取
    if (!effectiveSessionId) {
      const ctx = this._framework.getExecutionContext()
      if (ctx?.sessionId) {
        effectiveSessionId = ctx.sessionId
      }
    }

    if (effectiveSessionId && effectiveSessionId.startsWith('telegram_')) {
      chatId = effectiveSessionId.replace('telegram_', '')
    } else if (this._sessionPlugin) {
      // 获取最近的 telegram 会话
      const sessions = this._sessionPlugin.listSessions()
        .filter(s => s.id.startsWith('telegram_'))
        .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
      if (sessions.length > 0) {
        chatId = sessions[0].id.replace('telegram_', '')
      }
    }

    if (!chatId) {
      log.warn(' No telegram session found for notification')
      return
    }

    // 格式化通知消息
    const levelEmoji = {
      info: 'ℹ️',
      warning: '⚠️',
      success: '✅',
      error: '❌'
    }
    const emoji = levelEmoji[level] || 'ℹ️'
    const notificationText = `${emoji} [${source}] ${title}\n\n${message}`

    try {
      await this._bot.sendMessage(chatId, notificationText)
      log.info(` Notification sent to chat ${chatId}`)
    } catch (err) {
      log.error(` Failed to send notification:`, err.message)
    }
  }

  /**
   * 处理 webhook 通知
   */
  async _handleWebhookNotification(data) {
    const { data: webhookData, response, sessionId } = data

    if (!sessionId || !sessionId.startsWith('telegram_')) {
      return
    }

    const chatId = sessionId.replace('telegram_', '')
    const notificationText = `📥 [Webhook 接收]\n\n路径: ${webhookData.path}\n方法: ${webhookData.method}\n\n处理结果: ${response || '处理中...'}`

    try {
      await this._bot.sendMessage(chatId, notificationText)
      log.info(` Webhook notification sent to chat ${chatId}`)
    } catch (err) {
      log.error(` Failed to send webhook notification:`, err.message)
    }
  }

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

  _getSessionAgent(chatId) {
    if (this._sessionAgents.has(chatId)) {
      return { agent: this._sessionAgents.get(chatId), sessionId: `telegram_${chatId}` }
    }

    const agent = this._framework.createSessionAgent(`telegram_${chatId}`, {
      systemPrompt: this.systemPrompt,
      sharedPrompt: `工作目录: {{WORK_DIR}}`,
      metadata: { WORK_DIR: process.cwd() }
    })
    this._sessionAgents.set(chatId, agent)

    if (this._sessionPlugin) {
      this._sessionPlugin.getOrCreateSession(`telegram_${chatId}`, {
        metadata: { platform: 'telegram', chatId }
      })
    }

    return { agent, sessionId: `telegram_${chatId}` }
  }

  async _handleMessage(msg) {
    if (!msg || !msg.chat) return
    const chatId = msg.chat.id.toString()

    if (msg.photo) { await this._handlePhoto(msg); return }
    if (msg.document) { await this._handleDocument(msg); return }
    if (!msg.text) return

    const text = msg.text.trim()
    if (text.startsWith(this.config.prefix)) {
      await this._handleCommand(msg)
      return
    }

    if (msg.chat.type === 'group' || msg.chat.type === 'supergroup') {
      if (!this.config.groupMode) return
    }

    if (!this._checkPermission(chatId)) {
      await this._sendMessage(chatId, '抱歉，您没有权限使用此 Bot。', msg.message_id)
      return
    }

    await this._processChat(chatId, text, msg.message_id)
  }

  async _handleCommand(msg) {
    const chatId = msg.chat.id.toString()
    const text = msg.text.trim()
    const parts = text.split(' ')
    const command = parts[0].substring(1)
    const args = parts.slice(1).join(' ')

    switch (command.toLowerCase()) {
      case 'start':
        await this._sendMessage(chatId,
          '👋 欢迎使用 AI 助手！\n\n直接发送消息即可与我对话。\n\n可用命令：\n/start - 显示帮助\n/clear - 清除对话历史\n/history - 查看历史消息数',
          msg.message_id)
        break
      case 'clear':
        this._clearSession(chatId)
        await this._sendMessage(chatId, '✅ 对话历史已清除', msg.message_id)
        break
      case 'history':
        if (this._sessionPlugin) {
          const session = this._sessionPlugin.getSession(`telegram_${chatId}`)
          const sessions = this._sessionPlugin.listSessions().filter(s => s.id.startsWith('telegram_'))
          await this._sendMessage(chatId,
            `📊 当前状态\n\n会话数：${sessions.length}\n历史消息：${session?.messages?.length || 0}\n最后活跃：${session?.lastActive?.toLocaleString() || '无'}`,
            msg.message_id)
        } else {
          await this._sendMessage(chatId, '❌ 会话服务不可用', msg.message_id)
        }
        break
      default:
        await this._processChat(chatId, text, msg.message_id)
    }
  }

  async _processChat(chatId, text, replyToMessageId) {
    const sessionInfo = this._getSessionAgent(chatId)
    if (!sessionInfo) {
      await this._sendMessage(chatId, '❌ AI 服务未初始化', replyToMessageId)
      return
    }

    const { agent, sessionId } = sessionInfo

    // if (this._sessionPlugin) {
    //   this._sessionPlugin.addMessage(sessionId, { role: 'user', content: text })
    // }

    let thinkingMsg
    try {
      thinkingMsg = await this._bot.sendMessage(chatId, '🤔 思考中...', {
        reply_to_message_id: replyToMessageId
      })
    } catch (err) {
      log.error(' Send thinking error:', err.message)
      return
    }

    try {
      let fullResponse = ''
      for await (const chunk of agent.chatStream(text, { sessionId })) {
        if (chunk.type === 'text' && chunk.text) {
          fullResponse += chunk.text
          if (fullResponse.length % 100 === 0) {
            try {
              await this._bot.editMessageText(`📝 ${escapeMarkdown(fullResponse)}▌`, {
                chat_id: chatId,
                message_id: thinkingMsg.message_id
              })
            } catch (e) { /* ignore */ }
          }
        }
      }

      // if (this._sessionPlugin) {
      //   this._sessionPlugin.addMessage(sessionId, { role: 'assistant', content: fullResponse })
      // }

      const safeResponse = escapeMarkdown(fullResponse) || '抱歉，我没有收到有效的回复。'
      await this._bot.editMessageText(safeResponse, {
        chat_id: chatId,
        message_id: thinkingMsg.message_id,
        parse_mode: 'MarkdownV2'
      })
    } catch (err) {
      log.error(' Chat error:', err)
      await this._bot.editMessageText(escapeMarkdown(`❌ 发生错误：${err.message}`), {
        chat_id: chatId,
        message_id: thinkingMsg.message_id
      })
    }
  }

  async _handleEdit(msg) { /* 支持编辑后重新处理 */ }

  async _handleCallback(query) {
    await this._bot.answerCallbackQuery(query.id, { text: '处理中...' })
  }

  _checkPermission(chatId) {
    return this.config.allowedChats.length === 0 || this.config.allowedChats.includes(chatId)
  }

  async _handlePhoto(msg) {
    const chatId = msg.chat.id.toString()
    if (!this._checkPermission(chatId)) {
      await this._sendMessage(chatId, '抱歉，您没有权限使用此 Bot。', msg.message_id)
      return
    }

    const caption = msg.caption?.trim() || ''
    const photo = msg.photo[msg.photo.length - 1]

    try {
      const filePath = await this._downloadFile(photo.file_id, '.jpg', 'telegram_images')
      await this._sendMessage(chatId, `收到图片${caption ? ': ' + caption : ''}\n已保存至: ${filePath}`, msg.message_id)
      if (caption) {
        await this._processChat(chatId, `图片：${filePath}, ${caption}`, msg.message_id)
      }
    } catch (err) {
      log.error(' Failed to save photo:', err.message)
      await this._sendMessage(chatId, '图片保存失败: ' + err.message, msg.message_id)
    }
  }

  async _handleDocument(msg) {
    const chatId = msg.chat.id.toString()
    if (!this._checkPermission(chatId)) {
      await this._sendMessage(chatId, '抱歉，您没有权限使用此 Bot。', msg.message_id)
      return
    }

    const fileName = msg.document.file_name || '未命名文件'
    const caption = msg.caption?.trim() || ''
    const ext = fileName.includes('.') ? fileName.split('.').pop() : 'bin'

    try {
      const filePath = await this._downloadFile(msg.document.file_id, ext, 'telegram_documents')
      await this._sendMessage(chatId, `收到文件: ${fileName}\n已保存至: ${filePath}${caption ? '\n\n说明: ' + caption : ''}`, msg.message_id)
      if (caption) {
        await this._processChat(chatId, `文件：${filePath}, ${caption}`, msg.message_id)
      }
    } catch (err) {
      log.error(' Failed to save document:', err.message)
      await this._sendMessage(chatId, '文件保存失败: ' + err.message, msg.message_id)
    }
  }

  async _downloadFile(fileId, ext, subDir) {
    const path = require('path')
    const fs = require('fs')
    const saveDir = path.join(process.cwd(), '.agent', 'data', subDir)
    if (!fs.existsSync(saveDir)) fs.mkdirSync(saveDir, { recursive: true })

    const fileName = `${Date.now()}_${Math.random().toString(36).substring(7)}.${ext}`
    const filePath = path.join(saveDir, fileName)

    const savedPath = await this._bot.downloadFile(fileId, saveDir)
    if (savedPath !== filePath) fs.renameSync(savedPath, filePath)
    return filePath
  }

  _clearSession(chatId) {
    if (this._sessionPlugin) {
      this._sessionPlugin.deleteSession(`telegram_${chatId}`)
    }
  }

  async _sendMessage(chatId, text, replyToMessageId = null) {
    if (!this._bot) return
    return this._bot.sendMessage(chatId, text, { reply_to_message_id: replyToMessageId })
  }

  getStatus() {
    let sessions = []
    if (this._sessionPlugin) {
      sessions = this._sessionPlugin.listSessions()
        .filter(s => s.id.startsWith('telegram_'))
        .map(s => ({
          chatId: s.id.replace('telegram_', ''),
          historyLength: s.messageCount,
          lastActive: s.lastActive
        }))
    }
    return {
      connected: !!this._bot,
      sessionCount: sessions.length,
      sessions,
      config: {
        groupMode: this.config.groupMode,
        prefix: this.config.prefix,
        allowedChatsCount: this.config.allowedChats.length
      }
    }
  }

  stopBot() {
    if (this._bot) {
      this._bot.stopPolling()
      this._bot = null
      log.info(' Bot stopped')
    }
  }

  reload(framework) {
    this._framework = framework
    if (this.config.botToken) {
      this.stopBot()
      this._initBot()
    }
  }

  uninstall() {
    for (const agent of this._sessionAgents.values()) {
      agent.destroy()
    }
    this._sessionAgents.clear()
    this.stopBot()
    if (this._sessionPlugin && this._sessionDeleteHandler) {
      this._sessionPlugin.off('session:deleted', this._sessionDeleteHandler)
      this._sessionDeleteHandler = null
    }
    this._sessionPlugin = null
    this._framework = null
  }
}

module.exports = TelegramPlugin
