const redis = require('../models/redis')
const logger = require('../utils/logger')
const { v4: uuidv4 } = require('uuid')

class WebhookConfigService {
  constructor() {
    this.KEY_PREFIX = 'webhook_config'
    this.DEFAULT_CONFIG_KEY = `${this.KEY_PREFIX}:default`
  }

  /**
   * 获取webhook配置
   */
  async getConfig() {
    try {
      const configStr = await redis.client.get(this.DEFAULT_CONFIG_KEY)
      if (!configStr) {
        // 返回默认配置
        return this.getDefaultConfig()
      }

      const storedConfig = JSON.parse(configStr)
      const defaultConfig = this.getDefaultConfig()

      // 合并默认通知类型，确保新增类型有默认值
      storedConfig.notificationTypes = {
        ...defaultConfig.notificationTypes,
        ...(storedConfig.notificationTypes || {})
      }

      return storedConfig
    } catch (error) {
      logger.error('获取webhook配置失败:', error)
      return this.getDefaultConfig()
    }
  }

  /**
   * 保存webhook配置
   */
  async saveConfig(config) {
    try {
      const defaultConfig = this.getDefaultConfig()

      config.notificationTypes = {
        ...defaultConfig.notificationTypes,
        ...(config.notificationTypes || {})
      }

      // 验证配置
      this.validateConfig(config)

      // 添加更新时间
      config.updatedAt = new Date().toISOString()

      await redis.client.set(this.DEFAULT_CONFIG_KEY, JSON.stringify(config))
      logger.info('✅ Webhook配置已保存')

      return config
    } catch (error) {
      logger.error('保存webhook配置失败:', error)
      throw error
    }
  }

  /**
   * 验证配置
   */
  validateConfig(config) {
    if (!config || typeof config !== 'object') {
      throw new Error('无效的配置格式')
    }

    // 验证平台配置
    if (config.platforms) {
      const validPlatforms = [
        'wechat_work',
        'dingtalk',
        'feishu',
        'slack',
        'discord',
        'telegram',
        'custom',
        'bark',
        'smtp'
      ]

      for (const platform of config.platforms) {
        if (!validPlatforms.includes(platform.type)) {
          throw new Error(`不支持的平台类型: ${platform.type}`)
        }

        // Bark和SMTP平台不使用标准URL
        if (!['bark', 'smtp', 'telegram'].includes(platform.type)) {
          if (!platform.url || !this.isValidUrl(platform.url)) {
            throw new Error(`无效的webhook URL: ${platform.url}`)
          }
        }

        // 验证平台特定的配置
        this.validatePlatformConfig(platform)
      }
    }
  }

  /**
   * 验证平台特定配置
   */
  validatePlatformConfig(platform) {
    switch (platform.type) {
      case 'wechat_work':
        // 企业微信不需要额外配置
        break
      case 'dingtalk':
        // 钉钉可能需要secret用于签名
        if (platform.enableSign && !platform.secret) {
          throw new Error('钉钉启用签名时必须提供secret')
        }
        break
      case 'feishu':
        // 飞书可能需要签名
        if (platform.enableSign && !platform.secret) {
          throw new Error('飞书启用签名时必须提供secret')
        }
        break
      case 'slack':
        // Slack webhook URL通常包含token
        if (!platform.url.includes('hooks.slack.com')) {
          logger.warn('⚠️ Slack webhook URL格式可能不正确')
        }
        break
      case 'discord':
        // Discord webhook URL格式检查
        if (!platform.url.includes('discord.com/api/webhooks')) {
          logger.warn('⚠️ Discord webhook URL格式可能不正确')
        }
        break
      case 'telegram':
        if (!platform.botToken) {
          throw new Error('Telegram 平台必须提供机器人 Token')
        }
        if (!platform.chatId) {
          throw new Error('Telegram 平台必须提供 Chat ID')
        }

        if (!platform.botToken.includes(':')) {
          logger.warn('⚠️ Telegram 机器人 Token 格式可能不正确')
        }

        if (!/^[-\d]+$/.test(String(platform.chatId))) {
          logger.warn('⚠️ Telegram Chat ID 应该是数字，如为频道请确认已获取正确ID')
        }

        if (platform.apiBaseUrl) {
          if (!this.isValidUrl(platform.apiBaseUrl)) {
            throw new Error('Telegram API 基础地址格式无效')
          }
          const { protocol } = new URL(platform.apiBaseUrl)
          if (!['http:', 'https:'].includes(protocol)) {
            throw new Error('Telegram API 基础地址仅支持 http 或 https 协议')
          }
        }

        if (platform.proxyUrl) {
          if (!this.isValidUrl(platform.proxyUrl)) {
            throw new Error('Telegram 代理地址格式无效')
          }
          const proxyProtocol = new URL(platform.proxyUrl).protocol
          const supportedProtocols = ['http:', 'https:', 'socks4:', 'socks4a:', 'socks5:']
          if (!supportedProtocols.includes(proxyProtocol)) {
            throw new Error('Telegram 代理仅支持 http/https/socks 协议')
          }
        }
        break
      case 'custom':
        // 自定义webhook，用户自行负责格式
        break
      case 'bark':
        // 验证设备密钥
        if (!platform.deviceKey) {
          throw new Error('Bark平台必须提供设备密钥')
        }

        // 验证设备密钥格式（通常是22-24位字符）
        if (platform.deviceKey.length < 20 || platform.deviceKey.length > 30) {
          logger.warn('⚠️ Bark设备密钥长度可能不正确，请检查是否完整复制')
        }

        // 验证服务器URL（如果提供）
        if (platform.serverUrl) {
          if (!this.isValidUrl(platform.serverUrl)) {
            throw new Error('Bark服务器URL格式无效')
          }
          if (!platform.serverUrl.includes('/push')) {
            logger.warn('⚠️ Bark服务器URL应该以/push结尾')
          }
        }

        // 验证声音参数（如果提供）
        if (platform.sound) {
          const validSounds = [
            'default',
            'alarm',
            'anticipate',
            'bell',
            'birdsong',
            'bloom',
            'calypso',
            'chime',
            'choo',
            'descent',
            'electronic',
            'fanfare',
            'glass',
            'gotosleep',
            'healthnotification',
            'horn',
            'ladder',
            'mailsent',
            'minuet',
            'multiwayinvitation',
            'newmail',
            'newsflash',
            'noir',
            'paymentsuccess',
            'shake',
            'sherwoodforest',
            'silence',
            'spell',
            'suspense',
            'telegraph',
            'tiptoes',
            'typewriters',
            'update',
            'alert'
          ]
          if (!validSounds.includes(platform.sound)) {
            logger.warn(`⚠️ 未知的Bark声音: ${platform.sound}`)
          }
        }

        // 验证级别参数
        if (platform.level) {
          const validLevels = ['active', 'timeSensitive', 'passive', 'critical']
          if (!validLevels.includes(platform.level)) {
            throw new Error(`无效的Bark通知级别: ${platform.level}`)
          }
        }

        // 验证图标URL（如果提供）
        if (platform.icon && !this.isValidUrl(platform.icon)) {
          logger.warn('⚠️ Bark图标URL格式可能不正确')
        }

        // 验证点击跳转URL（如果提供）
        if (platform.clickUrl && !this.isValidUrl(platform.clickUrl)) {
          logger.warn('⚠️ Bark点击跳转URL格式可能不正确')
        }
        break
      case 'smtp': {
        // 验证SMTP必需配置
        if (!platform.host) {
          throw new Error('SMTP平台必须提供主机地址')
        }
        if (!platform.user) {
          throw new Error('SMTP平台必须提供用户名')
        }
        if (!platform.pass) {
          throw new Error('SMTP平台必须提供密码')
        }
        if (!platform.to) {
          throw new Error('SMTP平台必须提供接收邮箱')
        }

        // 验证端口
        if (platform.port && (platform.port < 1 || platform.port > 65535)) {
          throw new Error('SMTP端口必须在1-65535之间')
        }

        // 验证邮箱格式
        // 支持两种格式：1. 纯邮箱 user@domain.com  2. 带名称 Name <user@domain.com>
        const simpleEmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

        // 验证接收邮箱
        const toEmails = Array.isArray(platform.to) ? platform.to : [platform.to]
        for (const email of toEmails) {
          // 提取实际邮箱地址（如果是 Name <email> 格式）
          const actualEmail = email.includes('<') ? email.match(/<([^>]+)>/)?.[1] : email
          if (!actualEmail || !simpleEmailRegex.test(actualEmail)) {
            throw new Error(`无效的接收邮箱格式: ${email}`)
          }
        }

        // 验证发送邮箱（支持 Name <email> 格式）
        if (platform.from) {
          const actualFromEmail = platform.from.includes('<')
            ? platform.from.match(/<([^>]+)>/)?.[1]
            : platform.from
          if (!actualFromEmail || !simpleEmailRegex.test(actualFromEmail)) {
            throw new Error(`无效的发送邮箱格式: ${platform.from}`)
          }
        }
        break
      }
    }
  }

  /**
   * 验证URL格式
   */
  isValidUrl(url) {
    try {
      new URL(url)
      return true
    } catch {
      return false
    }
  }

  /**
   * 获取默认配置
   */
  getDefaultConfig() {
    return {
      enabled: false,
      platforms: [],
      notificationTypes: {
        accountAnomaly: true, // 账号异常
        quotaWarning: true, // 配额警告
        systemError: true, // 系统错误
        securityAlert: true, // 安全警报
        rateLimitRecovery: true, // 限流恢复
        test: true // 测试通知
      },
      retrySettings: {
        maxRetries: 3,
        retryDelay: 1000, // 毫秒
        timeout: 10000 // 毫秒
      },
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    }
  }

  /**
   * 添加webhook平台
   */
  async addPlatform(platform) {
    try {
      const config = await this.getConfig()

      // 生成唯一ID
      platform.id = platform.id || uuidv4()
      platform.enabled = platform.enabled !== false
      platform.createdAt = new Date().toISOString()

      // 验证平台配置
      this.validatePlatformConfig(platform)

      // 添加到配置
      config.platforms = config.platforms || []
      config.platforms.push(platform)

      await this.saveConfig(config)

      return platform
    } catch (error) {
      logger.error('添加webhook平台失败:', error)
      throw error
    }
  }

  /**
   * 更新webhook平台
   */
  async updatePlatform(platformId, updates) {
    try {
      const config = await this.getConfig()

      const index = config.platforms.findIndex((p) => p.id === platformId)
      if (index === -1) {
        throw new Error('找不到指定的webhook平台')
      }

      // 合并更新
      config.platforms[index] = {
        ...config.platforms[index],
        ...updates,
        updatedAt: new Date().toISOString()
      }

      // 验证更新后的配置
      this.validatePlatformConfig(config.platforms[index])

      await this.saveConfig(config)

      return config.platforms[index]
    } catch (error) {
      logger.error('更新webhook平台失败:', error)
      throw error
    }
  }

  /**
   * 删除webhook平台
   */
  async deletePlatform(platformId) {
    try {
      const config = await this.getConfig()

      config.platforms = config.platforms.filter((p) => p.id !== platformId)

      await this.saveConfig(config)

      logger.info(`✅ 已删除webhook平台: ${platformId}`)
      return true
    } catch (error) {
      logger.error('删除webhook平台失败:', error)
      throw error
    }
  }

  /**
   * 切换webhook平台启用状态
   */
  async togglePlatform(platformId) {
    try {
      const config = await this.getConfig()

      const platform = config.platforms.find((p) => p.id === platformId)
      if (!platform) {
        throw new Error('找不到指定的webhook平台')
      }

      platform.enabled = !platform.enabled
      platform.updatedAt = new Date().toISOString()

      await this.saveConfig(config)

      logger.info(`✅ Webhook平台 ${platformId} 已${platform.enabled ? '启用' : '禁用'}`)
      return platform
    } catch (error) {
      logger.error('切换webhook平台状态失败:', error)
      throw error
    }
  }

  /**
   * 获取启用的平台列表
   */
  async getEnabledPlatforms() {
    try {
      const config = await this.getConfig()

      if (!config.enabled || !config.platforms) {
        return []
      }

      return config.platforms.filter((p) => p.enabled)
    } catch (error) {
      logger.error('获取启用的webhook平台失败:', error)
      return []
    }
  }
}

module.exports = new WebhookConfigService()
