/**
 * Account Status Monitoring Implementation
 *
 * Tracks health, performance, and status information for individual accounts
 * in the hedging account pool system.
 */

import { Platform } from '@/types/credential'

// ============================================================================
// Types and Interfaces
// ============================================================================

export enum AccountState {
  LOADING = 'loading',
  ACTIVE = 'active',
  WARNING = 'warning',
  ERROR = 'error',
  DISABLED = 'disabled',
  MAINTENANCE = 'maintenance'
}

export interface AccountHealthMetrics {
  successCount: number
  failureCount: number
  totalOperations: number
  lastSuccess: Date | null
  lastFailure: Date | null
  averageResponseTime: number
  consecutiveFailures: number
  healthScore: number // 0-1 scale
}

export interface AccountBalanceInfo {
  totalValue: number
  positions: Record<string, number>
  lastUpdated: Date
  currency: string
}

export interface AccountMetadata {
  alias?: string
  description?: string
  tags?: string[]
  priority?: number
  maintenanceWindow?: {
    start: string // HH:mm format
    end: string   // HH:mm format
    timezone: string
  }
}

// ============================================================================
// Main Implementation
// ============================================================================

export class AccountStatus {
  public readonly accountId: string
  public readonly platform: Platform
  public readonly createdAt: Date

  private state: AccountState = AccountState.LOADING
  private healthMetrics: AccountHealthMetrics
  private balanceInfo?: AccountBalanceInfo
  private metadata: AccountMetadata = {}
  private stateHistory: Array<{ state: AccountState; timestamp: Date; reason?: string }> = []
  private lastActivity: Date = new Date()

  constructor(accountId: string, platform: Platform, metadata?: AccountMetadata) {
    this.accountId = accountId
    this.platform = platform
    this.createdAt = new Date()
    this.metadata = metadata || {}

    this.healthMetrics = {
      successCount: 0,
      failureCount: 0,
      totalOperations: 0,
      lastSuccess: null,
      lastFailure: null,
      averageResponseTime: 0,
      consecutiveFailures: 0,
      healthScore: 1.0
    }

    this.recordStateChange(AccountState.LOADING, 'Account status initialized')
  }

  // ============================================================================
  // State Management
  // ============================================================================

  /**
   * Get current account state
   */
  getState(): AccountState {
    return this.state
  }

  /**
   * Check if account is active and healthy
   */
  isActive(): boolean {
    return this.state === AccountState.ACTIVE && this.healthMetrics.healthScore > 0.5
  }

  /**
   * Check if account is available for operations
   */
  isAvailable(): boolean {
    return [AccountState.ACTIVE, AccountState.WARNING].includes(this.state)
  }

  /**
   * Manually set account state
   */
  setState(newState: AccountState, reason?: string): void {
    if (this.state !== newState) {
      this.recordStateChange(newState, reason)
      this.state = newState
    }
  }

  // ============================================================================
  // Health Monitoring
  // ============================================================================

  /**
   * Record successful operation
   */
  recordSuccess(responseTime?: number): void {
    this.healthMetrics.successCount++
    this.healthMetrics.totalOperations++
    this.healthMetrics.lastSuccess = new Date()
    this.healthMetrics.consecutiveFailures = 0
    this.lastActivity = new Date()

    if (responseTime !== undefined) {
      this.updateAverageResponseTime(responseTime)
    }

    this.updateHealthScore()
    this.updateStateBasedOnHealth()
  }

  /**
   * Record failed operation
   */
  recordFailure(error: Error, responseTime?: number): void {
    this.healthMetrics.failureCount++
    this.healthMetrics.totalOperations++
    this.healthMetrics.lastFailure = new Date()
    this.healthMetrics.consecutiveFailures++
    this.lastActivity = new Date()

    if (responseTime !== undefined) {
      this.updateAverageResponseTime(responseTime)
    }

    this.updateHealthScore()
    this.updateStateBasedOnHealth()

    // Auto-disable account if too many consecutive failures
    if (this.healthMetrics.consecutiveFailures >= 5) {
      this.setState(AccountState.ERROR, `Too many consecutive failures: ${error.message}`)
    }
  }

  /**
   * Update health status with external health check
   */
  updateHealth(isHealthy: boolean, details?: any): void {
    this.lastActivity = new Date()

    if (!isHealthy && this.state === AccountState.ACTIVE) {
      this.setState(AccountState.WARNING, 'External health check failed')
    } else if (isHealthy && this.state === AccountState.WARNING) {
      this.setState(AccountState.ACTIVE, 'External health check passed')
    }

    // Update metadata with health check details
    if (details) {
      this.metadata = { ...this.metadata, ...details }
    }
  }

  /**
   * Get current health metrics
   */
  getHealthMetrics(): AccountHealthMetrics {
    return { ...this.healthMetrics }
  }

  /**
   * Get failure rate (0-1)
   */
  getFailureRate(): number {
    if (this.healthMetrics.totalOperations === 0) {
      return 0
    }
    return this.healthMetrics.failureCount / this.healthMetrics.totalOperations
  }

  /**
   * Get success rate (0-1)
   */
  getSuccessRate(): number {
    return 1 - this.getFailureRate()
  }

  // ============================================================================
  // Balance Information
  // ============================================================================

  /**
   * Update balance information
   */
  updateBalanceInfo(balanceInfo: AccountBalanceInfo): void {
    this.balanceInfo = { ...balanceInfo, lastUpdated: new Date() }
    this.lastActivity = new Date()
  }

  /**
   * Get current balance information
   */
  getBalanceInfo(): AccountBalanceInfo | undefined {
    return this.balanceInfo ? { ...this.balanceInfo } : undefined
  }

  /**
   * Check if balance information is stale
   */
  isBalanceStale(maxAgeMs: number = 5 * 60 * 1000): boolean {
    if (!this.balanceInfo) {
      return true
    }
    return Date.now() - this.balanceInfo.lastUpdated.getTime() > maxAgeMs
  }

  // ============================================================================
  // Activity Tracking
  // ============================================================================

  /**
   * Get last activity timestamp
   */
  getLastActivity(): Date {
    return new Date(this.lastActivity.getTime())
  }

  /**
   * Check if account is idle
   */
  isIdle(maxIdleMs: number = 10 * 60 * 1000): boolean {
    return Date.now() - this.lastActivity.getTime() > maxIdleMs
  }

  /**
   * Record activity without success/failure
   */
  recordActivity(): void {
    this.lastActivity = new Date()
  }

  // ============================================================================
  // State History and Diagnostics
  // ============================================================================

  /**
   * Get state history
   */
  getStateHistory(): Array<{ state: AccountState; timestamp: Date; reason?: string }> {
    return [...this.stateHistory]
  }

  /**
   * Get diagnostic information
   */
  getDiagnostics(): AccountDiagnostics {
    const now = new Date()
    const uptime = now.getTime() - this.createdAt.getTime()
    const timeSinceLastActivity = now.getTime() - this.lastActivity.getTime()

    return {
      accountId: this.accountId,
      platform: this.platform,
      currentState: this.state,
      healthScore: this.healthMetrics.healthScore,
      successRate: this.getSuccessRate(),
      failureRate: this.getFailureRate(),
      consecutiveFailures: this.healthMetrics.consecutiveFailures,
      totalOperations: this.healthMetrics.totalOperations,
      averageResponseTime: this.healthMetrics.averageResponseTime,
      uptime,
      timeSinceLastActivity,
      isActive: this.isActive(),
      isAvailable: this.isAvailable(),
      isIdle: this.isIdle(),
      balanceStale: this.isBalanceStale(),
      recentStateChanges: this.stateHistory.slice(-5)
    }
  }

  // ============================================================================
  // Metadata Management
  // ============================================================================

  /**
   * Update account metadata
   */
  updateMetadata(metadata: Partial<AccountMetadata>): void {
    this.metadata = { ...this.metadata, ...metadata }
  }

  /**
   * Get account metadata
   */
  getMetadata(): AccountMetadata {
    return { ...this.metadata }
  }

  // ============================================================================
  // Private Helper Methods
  // ============================================================================

  private recordStateChange(newState: AccountState, reason?: string): void {
    this.stateHistory.push({
      state: newState,
      timestamp: new Date(),
      reason
    })

    // Keep only last 50 state changes
    if (this.stateHistory.length > 50) {
      this.stateHistory = this.stateHistory.slice(-50)
    }
  }

  private updateAverageResponseTime(responseTime: number): void {
    const totalOps = this.healthMetrics.totalOperations
    const currentAvg = this.healthMetrics.averageResponseTime

    // Weighted average with more weight on recent operations
    this.healthMetrics.averageResponseTime =
      totalOps === 1
        ? responseTime
        : (currentAvg * 0.8) + (responseTime * 0.2)
  }

  private updateHealthScore(): void {
    const { totalOperations, successCount, consecutiveFailures, averageResponseTime } = this.healthMetrics

    if (totalOperations === 0) {
      this.healthMetrics.healthScore = 1.0
      return
    }

    // Base score from success rate
    const successRate = successCount / totalOperations
    let healthScore = successRate

    // Penalty for consecutive failures
    if (consecutiveFailures > 0) {
      const failurePenalty = Math.min(0.5, consecutiveFailures * 0.1)
      healthScore -= failurePenalty
    }

    // Penalty for slow response times (if we have performance requirements)
    if (averageResponseTime > 1000) { // > 1 second
      const performancePenalty = Math.min(0.2, (averageResponseTime - 1000) / 10000)
      healthScore -= performancePenalty
    }

    // Ensure score is between 0 and 1
    this.healthMetrics.healthScore = Math.max(0, Math.min(1, healthScore))
  }

  private updateStateBasedOnHealth(): void {
    const { healthScore, consecutiveFailures } = this.healthMetrics

    if (consecutiveFailures >= 5) {
      this.setState(AccountState.ERROR, 'Too many consecutive failures')
    } else if (healthScore < 0.3) {
      this.setState(AccountState.ERROR, 'Health score too low')
    } else if (healthScore < 0.7) {
      this.setState(AccountState.WARNING, 'Health score degraded')
    } else if (this.state !== AccountState.ACTIVE && healthScore >= 0.8) {
      this.setState(AccountState.ACTIVE, 'Health score recovered')
    }
  }
}

// ============================================================================
// Supporting Types
// ============================================================================

export interface AccountDiagnostics {
  accountId: string
  platform: Platform
  currentState: AccountState
  healthScore: number
  successRate: number
  failureRate: number
  consecutiveFailures: number
  totalOperations: number
  averageResponseTime: number
  uptime: number
  timeSinceLastActivity: number
  isActive: boolean
  isAvailable: boolean
  isIdle: boolean
  balanceStale: boolean
  recentStateChanges: Array<{ state: AccountState; timestamp: Date; reason?: string }>
}