/**
 * Session 会话管理插件
 * 管理多个用户会话，支持会话隔离和历史记录
 */

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

/**
 * 生成 UUID
 */
function generateId() {
  if (require('crypto').randomUUID) {
    return require('crypto').randomUUID()
  }
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = Math.random() * 16 | 0
    const v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

class SessionPlugin extends Plugin {
  constructor(config = {}) {
    super()
    this.name = 'session'
    this.version = '1.0.0'
    this.description = '会话管理插件，支持多会话隔离、历史记录、会话超时清理'
    this.priority = 5

    this.system = true

    this.config = {
      sessionTTL: config.sessionTTL || 30 * 60 * 1000,  // 30分钟
      maxSessions: config.maxSessions || 100,
      maxHistoryLength: config.maxHistoryLength || 150,  // 放宽到 150，Agent 已有智能压缩
      autoCleanup: config.autoCleanup||false,  // 默认不开启自动清理，避免误删会话
      cleanupInterval: config.cleanupInterval || 5 * 60 * 1000,  // 5分钟
      persistToStorage: config.persistToStorage !== false,  // 默认持久化到 storage
      // Session 钩子配置
      onSessionStart: config.onSessionStart || null,
      onSessionEnd: config.onSessionEnd || null,
      onSessionCreated: config.onSessionCreated || null
    }
    // console.log('SessionPlugin config:', this.config)
    this._framework = null
    this._sessions = new Map()
    this._cleanupTimer = null
    this._events = new EventEmitter()
    this._storageKeyPrefix = 'session:'
  }

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

  /**
   * 获取存储实例
   * @private
   */
  _getStorage() {
    if (!this._framework) return null;
    return this._framework.pluginManager.get('storage');
  }

  /**
   * 从 storage 加载会话数据
   * @private
   */
  _loadFromStorage(sessionId) {
    const storage = this._getStorage();
    if (!storage) return null;

    try {
      const store = storage.getStore();
      const data = store.get(this._storageKeyPrefix + sessionId);
      if (data && data.messages) {
        return data;
      }
    } catch (err) {
      // 忽略加载错误
    }
    return null;
  }

  /**
   * 保存会话数据到 storage
   * @private
   */
  _saveToStorage(session) {
    const storage = this._getStorage();
    if (!storage || !this.config.persistToStorage) return;

    try {
      storage.setDirect(this._storageKeyPrefix + session.id, {
        messages: session.messages,
        variables: session.variables,
        metadata: session.metadata,
        createdAt: session.createdAt,
        lastActive: session.lastActive
      });
    } catch (err) {
      // 忽略保存错误
    }
  }

  /**
   * 从 storage 删除会话数据
   * @private
   */
  _deleteFromStorage(sessionId) {
    const storage = this._getStorage();
    if (!storage) return;

    try {
      storage.deleteDirect(this._storageKeyPrefix + sessionId);
    } catch (err) {
      // 忽略删除错误
    }
  }

  /**
   * 从 storage 加载所有会话
   * @private
   */
  _loadAllFromStorage() {
    const storage = this._getStorage();
    if (!storage) return;

    try {
      const store = storage.getStore();
      // 遍历 storage 找出所有 session: 开头的键
      for (const [key, value] of store.entries()) {
        if (key.startsWith(this._storageKeyPrefix)) {
          const sessionId = key.substring(this._storageKeyPrefix.length);
          const sessionData = value;
          if (sessionId && sessionData && sessionData.messages) {
            // 恢复会话到内存
            this._sessions.set(sessionId, {
              id: sessionId,
              messages: sessionData.messages || [],
              variables: sessionData.variables || {},
              metadata: sessionData.metadata || {},
              createdAt: sessionData.createdAt ? new Date(sessionData.createdAt) : new Date(),
              lastActive: sessionData.lastActive ? new Date(sessionData.lastActive) : new Date()
            });
          }
        }
      }
      log.info(`Loaded ${this._sessions.size} sessions from storage`);
    } catch (err) {
      log.warn('Failed to load sessions from storage:', err.message);
    }
  }

  start(framework) {
    // 从 storage 加载所有会话
    this._loadAllFromStorage();
    // 注册会话管理工具
    framework.registerTool({
      name: 'session_create',
      description: '创建新会话',
      inputSchema: z.object({
        sessionId: z.string().optional().describe('可选：指定会话 ID'),
        metadata: z.object({}).optional().describe('会话元数据')
      }),
      execute: async (args) => {
        const sessionId = args.sessionId || `session_${generateId()}`
        const session = this.createSession(sessionId, { metadata: args.metadata })
        return {
          success: true,
          sessionId: session.id,
          createdAt: session.createdAt
        }
      }
    })

    framework.registerTool({
      name: 'session_get',
      description: '获取会话信息',
      inputSchema: z.object({
        sessionId: z.string().describe('会话 ID')
      }),
      execute: async (args) => {
        const session = this.getSession(args.sessionId)
        if (!session) {
          return { success: false, error: 'Session not found' }
        }
        return {
          success: true,
          sessionId: session.id,
          messageCount: session.messages.length,
          variables: Object.keys(session.variables),
          createdAt: session.createdAt,
          lastActive: session.lastActive
        }
      }
    })

    framework.registerTool({
      name: 'session_list',
      description: '列出所有会话',
      inputSchema: z.object({}),
      execute: async () => {
        const sessions = this.listSessions()
        return {
          success: true,
          sessions,
          total: sessions.length
        }
      }
    })

    framework.registerTool({
      name: 'session_delete',
      description: '删除会话',
      inputSchema: z.object({
        sessionId: z.string().describe('会话 ID')
      }),
      execute: async (args) => {
        const deleted = this.deleteSession(args.sessionId)
        return { success: deleted, deleted: args.sessionId }
      }
    })

    framework.registerTool({
      name: 'session_history',
      description: '获取会话历史消息',
      inputSchema: z.object({
        sessionId: z.string().describe('会话 ID'),
        limit: z.number().optional().describe('返回消息数量限制')
      }),
      execute: async (args) => {
        const history = this.getHistory(args.sessionId, args.limit)
        return {
          success: true,
          sessionId: args.sessionId,
          messages: history,
          count: history.length
        }
      }
    })

    framework.registerTool({
      name: 'session_stats',
      description: '获取会话统计信息',
      inputSchema: z.object({}),
      execute: async () => {
        return {
          success: true,
          stats: this.getMemoryStats()
        }
      }
    })

    // 启动自动清理
    if (this.config.autoCleanup) {
      this._startAutoCleanup()
    }

    return this
  }

  /**
   * 创建新会话
   */
  createSession(sessionId, options = {}) {
    const id = sessionId || `session_${generateId()}`

    if (this._sessions.has(id)) {
      return this._sessions.get(id)
    }

    // 如果会话数超过限制，清理最老的
    // if (this._sessions.size >= this.config.maxSessions) {
    //   this._cleanupLRU()
    // }

    const session = {
      id,
      messages: options.initialMessages || [],
      variables: options.variables || {},
      metadata: options.metadata || {},
      createdAt: new Date(),
      lastActive: new Date()
    }

    this._sessions.set(id, session)
    this._saveToStorage(session)

    // 触发 session:created 事件
    this._events.emit('session:created', session)

    // 调用 onSessionCreated 钩子
    if (this.config.onSessionCreated) {
      this._callHook(this.config.onSessionCreated, session)
    }

    return session
  }

  /**
   * 获取会话
   */
  getSession(sessionId) {
    let session = this._sessions.get(sessionId)
    if (session) {
      session.lastActive = new Date()
      return session
    }

    // 尝试从 storage 加载
    const storageData = this._loadFromStorage(sessionId)
    if (storageData) {
      session = {
        id: sessionId,
        messages: storageData.messages || [],
        variables: storageData.variables || {},
        metadata: storageData.metadata || {},
        createdAt: storageData.createdAt ? new Date(storageData.createdAt) : new Date(),
        lastActive: new Date()
      }
      this._sessions.set(sessionId, session)
      return session
    }

    return null
  }

  /**
   * 获取或创建会话
   */
  getOrCreateSession(sessionId, options = {}) {
    let session = this.getSession(sessionId)
    if (!session) {
      session = this.createSession(sessionId, options)
    }
    return session
  }

  /**
   * 添加消息到会话
   */
  addMessage(sessionId, message) {
    const session = this.getSession(sessionId)
    if (session) {
      // 基础消息验证
      if (!message || !message.role || !message.content) {
        log.warn('Invalid message format, skipping:', { sessionId, message });
        return session;
      }

      // 触发 session:started 事件（首次添加消息时）
      if (session.messages.length === 0) {
        this._events.emit('session:started', session)
        if (this.config.onSessionStart) {
          this._callHook(this.config.onSessionStart, session)
        }
      }

      session.messages.push(message)
      session.lastActive = new Date()

      // 限制历史长度
      if (session.messages.length > this.config.maxHistoryLength) {
        session.messages = session.messages.slice(-this.config.maxHistoryLength)
      }

      // 持久化到 storage
      this._saveToStorage(session)
    }
    return session
  }

  /**
   * 整体替换会话消息（用于压缩后同步）
   * @param {string} sessionId - 会话 ID
   * @param {Array} messages - 新的消息数组
   */
  replaceMessages(sessionId, messages) {
    const session = this.getSession(sessionId)
    if (session) {
      session.messages = messages || []
      session.lastActive = new Date()
      // 持久化到 storage
      this._saveToStorage(session)
    }
    return session
  }

  /**
   * 获取会话历史
   */
  getHistory(sessionId, limit = null) {
    const session = this.getSession(sessionId)
    if (!session) return []

    const messages = session.messages
    if (limit) {
      return messages.slice(-limit)
    }
    return messages
  }

  /**
   * 删除会话
   */
  deleteSession(sessionId) {
    const deleted = this._sessions.delete(sessionId)
    if (deleted) {
      this._deleteFromStorage(sessionId)
      this._events.emit('session:deleted', sessionId)
    }
    return deleted
  }

  /**
   * 列出所有会话
   */
  listSessions() {
    return Array.from(this._sessions.values()).map(s => ({
      id: s.id,
      messageCount: s.messages.length,
      createdAt: s.createdAt,
      lastActive: s.lastActive,
      metadata: s.metadata
    }))
  }

  /**
   * 清理过期会话
   */
  cleanup() {
    const now = Date.now()
    let cleanedCount = 0

    for (const [sessionId, session] of this._sessions) {
      if (now - session.lastActive.getTime() > this.config.sessionTTL) {
        this._sessions.delete(sessionId)
        cleanedCount++
      }
    }

    return cleanedCount
  }

  /**
   * LRU 清理 - 删除最老的 20% 会话
   */
  _cleanupLRU() {
    const sessions = Array.from(this._sessions.values())
    if (sessions.length === 0) return

    // 按最后活跃时间排序
    sessions.sort((a, b) => a.lastActive.getTime() - b.lastActive.getTime())

    // 删除最老的会话
    const toDelete = sessions.slice(0, Math.ceil(sessions.length * 0.2))
    for (const session of toDelete) {
      this._sessions.delete(session.id)
    }
  }

  /**
   * 获取内存统计
   */
  getMemoryStats() {
    const sessionCount = this._sessions.size
    const totalMessages = Array.from(this._sessions.values()).reduce(
      (sum, s) => sum + s.messages.length, 0
    )

    return {
      sessionCount,
      maxSessions: this.config.maxSessions,
      totalMessages,
      ttl: this.config.sessionTTL
    }
  }

  /**
   * 清理所有会话
   */
  clear() {
    const sessionIds = Array.from(this._sessions.keys())
    this._sessions.clear()
    sessionIds.forEach(id => this._events.emit('session:deleted', id))
  }

  /**
   * 监听会话事件
   */
  on(event, listener) {
    this._events.on(event, listener)
  }

  /**
   * 移除会话事件监听
   */
  off(event, listener) {
    this._events.off(event, listener)
  }

  /**
   * 调用会话钩子
   * @param {Function} hook - 钩子函数
   * @param {Object} session - 会话对象
   * @private
   */
  _callHook(hook, session) {
    if (typeof hook === 'function') {
      try {
        const result = hook(session)
        if (result && typeof result.catch === 'function') {
          result.catch(err => log.warn('Session hook error:', err.message))
        }
      } catch (err) {
        log.warn('Session hook error:', err.message)
      }
    }
  }

  /**
   * 结束会话（触发 session:ended 事件）
   * 当会话完成处理时调用
   * @param {string} sessionId - 会话 ID
   */
  endSession(sessionId) {
    const session = this.getSession(sessionId)
    if (session) {
      this._events.emit('session:ended', session)
      if (this.config.onSessionEnd) {
        this._callHook(this.config.onSessionEnd, session)
      }
    }
  }

  /**
   * 启动自动清理定时器
   */
  _startAutoCleanup() {
    if (this._cleanupTimer) {
      clearInterval(this._cleanupTimer)
    }
    this._cleanupTimer = setInterval(() => {
      const cleaned = this.cleanup()
      if (cleaned > 0) {
        log.info(` Cleaned up ${cleaned} expired sessions`)
      }
    }, this.config.cleanupInterval)
  }

  reload(framework) {
    this._framework = framework
  }

  uninstall(framework) {
    if (this._cleanupTimer) {
      clearInterval(this._cleanupTimer)
      this._cleanupTimer = null
    }
    this._events.removeAllListeners()
    this._sessions.clear()
    this._framework = null
  }
}

module.exports = SessionPlugin