/**
 * 模块化凭据服务实现
 * 基于依赖注入和面向对象设计原则
 */

import { EventEmitter } from 'events'
import {
  ICredentialService,
  SignRequest,
  BatchSignRequest,
  SignResponse,
  ServiceStatus,
} from './interfaces/ICredentialService'
import { ICredentialRepository } from './interfaces/ICredentialRepository'
import { ISignatureProvider } from './interfaces/ISignatureProvider'
import { PlatformAccount, ErrorCode } from '../shared/credential-types'
import { createApiError, formatTimestamp, PerformanceTimer } from '../shared/credential-utils'

/**
 * 服务配置接口
 */
export interface CredentialServiceConfig {
  autoInitialize?: boolean
  enableWatching?: boolean
  performanceTracking?: boolean
}

/**
 * 性能统计接口
 */
interface PerformanceStats {
  totalSigns: number
  totalSignTime: number
  errorCount: number
  lastSignTime?: number
}

/**
 * 主凭据服务实现
 */
export class CredentialService extends EventEmitter implements ICredentialService {
  private _repository: ICredentialRepository
  private _signatureProviders: Map<string, ISignatureProvider>
  private _initialized = false
  private _config: CredentialServiceConfig
  private _performanceStats: PerformanceStats

  constructor(
    repository: ICredentialRepository,
    signatureProviders: Map<string, ISignatureProvider>,
    config: CredentialServiceConfig = {},
  ) {
    super()

    this._repository = repository
    this._signatureProviders = signatureProviders
    this._config = {
      autoInitialize: true,
      enableWatching: true,
      performanceTracking: true,
      ...config,
    }

    this._performanceStats = {
      totalSigns: 0,
      totalSignTime: 0,
      errorCount: 0,
    }

    this._setupRepositoryEvents()

    // 自动初始化
    if (this._config.autoInitialize) {
      this.initialize().catch(error => {
        this.emit('initialization:error', error)
      })
    }
  }

  async initialize(): Promise<void> {
    if (this._initialized) {
      return
    }

    try {
      await this._repository.load()

      if (this._config.enableWatching) {
        this._repository.startWatching()
      }

      this._initialized = true

      console.log(`✅ [CredentialService] 服务初始化完成`)
      this.emit('service:initialized', {
        timestamp: formatTimestamp(),
        accountCount: this._repository.getStats().totalAccounts,
      })
    } catch (error) {
      console.error(`❌ [CredentialService] 初始化失败:`, error)
      this.emit('initialization:error', error)
      throw error
    }
  }

  async sign(platformId: string, request: SignRequest): Promise<SignResponse> {
    const timer = new PerformanceTimer()

    try {
      await this._ensureInitialized()

      // 验证平台支持
      const provider = this._getSignatureProvider(platformId)

      // 获取账户
      const account = this._getValidAccount(platformId, request.accountId)

      // 执行签名
      const result = await provider.sign(request.data, {
        privateKey: account.credentials.privateKey,
      })

      const executionTimeMs = timer.elapsed()

      // 更新统计和账户使用情况
      this._updatePerformanceStats(executionTimeMs, true)
      this._updateAccountUsage(account, true, executionTimeMs)

      console.log(
        `✅ [CredentialService] 签名完成: ${platformId}/${request.accountId} (${executionTimeMs.toFixed(1)}ms)`,
      )

      this.emit('signature:success', {
        platformId,
        accountId: request.accountId,
        requestId: request.requestId,
        algorithm: result.algorithm,
        executionTimeMs,
        timestamp: formatTimestamp(),
      })

      return {
        accountId: request.accountId,
        requestId: request.requestId,
        success: true,
        result,
        executionTimeMs,
      }
    } catch (error) {
      const executionTimeMs = timer.elapsed()

      this._updatePerformanceStats(executionTimeMs, false)

      console.error(
        `❌ [CredentialService] 签名失败: ${platformId}/${request.accountId} (${executionTimeMs.toFixed(1)}ms)`,
        error,
      )

      this.emit('signature:error', {
        platformId,
        accountId: request.accountId,
        requestId: request.requestId,
        error: error instanceof Error ? error.message : String(error),
        executionTimeMs,
        timestamp: formatTimestamp(),
      })

      return {
        accountId: request.accountId,
        requestId: request.requestId,
        success: false,
        error: error instanceof Error ? error.message : String(error),
        executionTimeMs,
      }
    }
  }

  async signBatch(platformId: string, batchRequest: BatchSignRequest): Promise<SignResponse[]> {
    const timer = new PerformanceTimer()

    console.log(`🔄 [CredentialService] 开始批量签名: ${platformId}, ${batchRequest.requests.length}个请求`)

    const results: SignResponse[] = []

    for (const request of batchRequest.requests) {
      const response = await this.sign(platformId, request)
      results.push(response)
    }

    const totalTime = timer.elapsed()
    const successful = results.filter(r => r.success).length

    console.log(`✅ [CredentialService] 批量签名完成: ${successful}/${results.length} (${totalTime.toFixed(1)}ms)`)

    this.emit('batch:completed', {
      platformId,
      total: results.length,
      successful,
      failed: results.length - successful,
      totalTimeMs: totalTime,
      timestamp: formatTimestamp(),
    })

    return results
  }

  getAccount(platformId: string, accountId: string): PlatformAccount | null {
    return this._repository.findAccount(platformId, accountId)
  }

  getAccounts(platformId: string): PlatformAccount[] {
    return this._repository.findAccountsByPlatform(platformId)
  }

  hasAccount(platformId: string, accountId: string): boolean {
    return this._repository.hasAccount(platformId, accountId)
  }

  getAccountPublicKey(platformId: string, accountId: string): string | null {
    try {
      const provider = this._getSignatureProvider(platformId)
      const account = this._repository.findAccount(platformId, accountId)

      if (!account?.credentials.privateKey || !provider.derivePublicKey) {
        return null
      }

      return provider.derivePublicKey(account.credentials.privateKey)
    } catch (error) {
      console.error(`❌ [CredentialService] 获取公钥失败: ${platformId}/${accountId}`, error)
      return null
    }
  }

  async reloadConfig(): Promise<void> {
    console.log(`🔄 [CredentialService] 重新加载配置`)
    await this._repository.reload()
  }

  getStatus(): ServiceStatus {
    const repoStats = this._repository.getStats()
    const platformAccounts: Record<string, number> = {}

    // 统计每个平台的账户数
    for (const [platformId] of this._signatureProviders) {
      platformAccounts[platformId] = this._repository.findAccountsByPlatform(platformId).length
    }

    return {
      initialized: this._initialized,
      configPath: repoStats.configPath,
      lastLoaded: repoStats.lastLoaded,
      totalAccounts: repoStats.totalAccounts,
      platformAccounts,
      performance: {
        totalSigns: this._performanceStats.totalSigns,
        averageSignTime:
          this._performanceStats.totalSigns > 0
            ? this._performanceStats.totalSignTime / this._performanceStats.totalSigns
            : 0,
        errorRate:
          this._performanceStats.totalSigns > 0
            ? this._performanceStats.errorCount / this._performanceStats.totalSigns
            : 0,
      },
    }
  }

  async dispose(): Promise<void> {
    console.log(`🛑 [CredentialService] 销毁服务`)

    try {
      await this._repository.dispose()
      this.removeAllListeners()
      this._initialized = false

      console.log(`✅ [CredentialService] 服务已销毁`)
    } catch (error) {
      console.error(`❌ [CredentialService] 销毁服务时出错:`, error)
      throw error
    }
  }

  /**
   * 获取支持的平台列表
   */
  getSupportedPlatforms(): string[] {
    return Array.from(this._signatureProviders.keys())
  }

  /**
   * 获取平台的签名提供者信息
   */
  getProviderInfo(platformId: string) {
    const provider = this._signatureProviders.get(platformId)
    return provider?.getInfo() || null
  }

  // ========== 私有方法 ==========

  private async _ensureInitialized(): Promise<void> {
    if (!this._initialized) {
      await this.initialize()
    }
  }

  private _getSignatureProvider(platformId: string): ISignatureProvider {
    const provider = this._signatureProviders.get(platformId)
    if (!provider) {
      throw createApiError(ErrorCode.PLATFORM_NOT_SUPPORTED, {
        platformId,
        supportedPlatforms: this.getSupportedPlatforms(),
      })
    }
    return provider
  }

  private _getValidAccount(platformId: string, accountId: string): PlatformAccount {
    const account = this._repository.findAccount(platformId, accountId)
    if (!account) {
      throw createApiError(ErrorCode.ACCOUNT_NOT_FOUND, {
        platformId,
        accountId,
      })
    }

    if (account.status !== 'active') {
      throw createApiError(ErrorCode.ACCOUNT_INACTIVE, {
        platformId,
        accountId,
        status: account.status,
      })
    }

    return account
  }

  private _updatePerformanceStats(executionTimeMs: number, success: boolean): void {
    if (!this._config.performanceTracking) {
      return
    }

    this._performanceStats.totalSigns++
    this._performanceStats.totalSignTime += executionTimeMs
    this._performanceStats.lastSignTime = executionTimeMs

    if (!success) {
      this._performanceStats.errorCount++
    }
  }

  private _updateAccountUsage(account: PlatformAccount, success: boolean, executionTimeMs: number): void {
    try {
      if (success) {
        account.usage.totalSigns++
        account.usage.lastSignAt = new Date()
      } else {
        account.usage.errorCount++
      }
      account.updatedAt = new Date()
    } catch (error) {
      console.error(`❌ [CredentialService] 更新账户统计失败:`, error)
    }
  }

  private _setupRepositoryEvents(): void {
    this._repository.on('config:loaded', event => {
      this.emit('config:loaded', event)
    })

    this._repository.on('config:reloaded', event => {
      this.emit('config:reloaded', event)
    })

    this._repository.on('config:error', event => {
      this.emit('config:error', event)
    })
  }
}
