/**
 * Trading Module Integration Interface
 *
 * Provides integration interfaces between the credential manager and trading systems
 * for hedging operations and account management.
 */

import { Platform, Account, SignResult } from '@/types/credential'
import { HedgingAccountPool, AccountSelection } from './HedgingAccountPool'
import { AccountStatus } from './AccountStatus'

// ============================================================================
// Trading Integration Types
// ============================================================================

export interface TradingSignRequest {
  /**
   * Trading operation type
   */
  operation: TradingOperation

  /**
   * Target platform for the operation
   */
  platform: Platform

  /**
   * Trading parameters
   */
  parameters: TradingParameters

  /**
   * Account selection criteria
   */
  accountCriteria?: AccountSelectionCriteria

  /**
   * Additional context for the operation
   */
  context?: Record<string, any>
}

export interface TradingSignResponse extends SignResult {
  /**
   * Selected account information
   */
  selectedAccount: AccountSelection

  /**
   * Trading operation details
   */
  operation: TradingOperation

  /**
   * Platform-specific signature format
   */
  platformSignature: PlatformSignatureFormat
}

export enum TradingOperation {
  PLACE_ORDER = 'place_order',
  CANCEL_ORDER = 'cancel_order',
  CANCEL_ALL_ORDERS = 'cancel_all_orders',
  MODIFY_ORDER = 'modify_order',
  TRANSFER_FUNDS = 'transfer_funds',
  WITHDRAW_FUNDS = 'withdraw_funds',
  GET_BALANCE = 'get_balance',
  GET_POSITIONS = 'get_positions'
}

export interface TradingParameters {
  symbol?: string
  side?: 'buy' | 'sell'
  type?: 'market' | 'limit' | 'stop'
  quantity?: number
  price?: number
  orderId?: string
  amount?: number
  destination?: string
  [key: string]: any
}

export interface AccountSelectionCriteria {
  preferPrimary?: boolean
  excludeAccounts?: string[]
  minBalance?: number
  maxExposure?: number
  riskTolerance?: 'low' | 'medium' | 'high'
}

export interface PlatformSignatureFormat {
  format: 'base64' | 'hex' | 'base58'
  encoding: string
  headers?: Record<string, string>
  body?: any
}

export interface AccountHealthStatus {
  accountId: string
  platform: Platform
  isHealthy: boolean
  healthScore: number
  lastActivity: Date
  failureCount: number
  balanceInfo?: {
    totalValue: number
    positions: Record<string, number>
  }
}

export interface TradeResult {
  success: boolean
  tradeId?: string
  executedPrice?: number
  executedQuantity?: number
  fees?: number
  timestamp: Date
  error?: string
}

export interface AvailableAccount {
  accountId: string
  platform: Platform
  healthScore: number
  balanceInfo?: {
    totalValue: number
    availableBalance: number
  }
  capabilities: string[]
  estimatedCapacity: number
}

// ============================================================================
// Main Trading Integration Interface
// ============================================================================

export interface ITradingModuleIntegration {
  /**
   * Sign a trading request with automatic account selection
   */
  signTradingRequest(request: TradingSignRequest): Promise<TradingSignResponse>

  /**
   * Sign multiple trading requests in batch
   */
  signBatchTradingRequests(requests: TradingSignRequest[]): Promise<TradingSignResponse[]>

  /**
   * Get available accounts for trading with specified criteria
   */
  getAvailableAccountsForTrading(criteria: AccountSelectionCriteria): Promise<AvailableAccount[]>

  /**
   * Check health status of multiple accounts
   */
  checkAccountHealth(accountIds: string[]): Promise<Map<string, AccountHealthStatus>>

  /**
   * Update account status after trade execution
   */
  updateAccountAfterTrade(accountId: string, tradeResult: TradeResult): Promise<void>

  /**
   * Get optimal account distribution for hedging strategy
   */
  getHedgingAccountDistribution(
    totalVolume: number,
    platforms: Platform[]
  ): Promise<Map<Platform, AccountSelection[]>>

  /**
   * Reserve accounts for upcoming trading operations
   */
  reserveAccountsForTrading(
    accountIds: string[],
    durationMs: number
  ): Promise<{ success: boolean; reservedAccounts: string[] }>

  /**
   * Release reserved accounts
   */
  releaseReservedAccounts(accountIds: string[]): Promise<{ success: boolean; releasedAccounts: string[] }>
}

// ============================================================================
// Implementation
// ============================================================================

export class TradingModuleIntegration implements ITradingModuleIntegration {
  private hedgingPool: HedgingAccountPool
  private accountStatuses: Map<string, AccountStatus> = new Map()
  private reservedAccounts: Map<string, { reservedUntil: Date; context?: any }> = new Map()
  private signFunction?: (accountId: string, message: Uint8Array) => Promise<SignResult>

  constructor(hedgingPool: HedgingAccountPool) {
    this.hedgingPool = hedgingPool
  }

  /**
   * Set the signing function from credential manager
   */
  setSignFunction(signFn: (accountId: string, message: Uint8Array) => Promise<SignResult>): void {
    this.signFunction = signFn
  }

  async signTradingRequest(request: TradingSignRequest): Promise<TradingSignResponse> {
    if (!this.signFunction) {
      throw new Error('Signing function not configured')
    }

    // Select optimal account for the trading operation
    const accountSelection = await this.hedgingPool.selectAccount(
      request.platform,
      request.accountCriteria
    )

    // Create trading message based on operation and parameters
    const tradingMessage = this.createTradingMessage(request.operation, request.parameters)

    // Sign the trading message
    const signResult = await this.signFunction(accountSelection.accountId, tradingMessage)

    // Create platform-specific signature format
    const platformSignature = this.formatSignatureForPlatform(
      request.platform,
      signResult,
      request.parameters
    )

    return {
      ...signResult,
      selectedAccount: accountSelection,
      operation: request.operation,
      platformSignature
    }
  }

  async signBatchTradingRequests(requests: TradingSignRequest[]): Promise<TradingSignResponse[]> {
    const results: TradingSignResponse[] = []

    // Process requests in parallel for different platforms
    const platformGroups = this.groupRequestsByPlatform(requests)

    for (const [platform, platformRequests] of Object.entries(platformGroups)) {
      const platformResults = await Promise.all(
        platformRequests.map(request => this.signTradingRequest(request))
      )
      results.push(...platformResults)
    }

    return results
  }

  async getAvailableAccountsForTrading(criteria: AccountSelectionCriteria): Promise<AvailableAccount[]> {
    const platforms = [Platform.PACIFICA, Platform.ASTER, Platform.BINANCE]
    const availableAccounts: AvailableAccount[] = []

    for (const platform of platforms) {
      try {
        const poolStatus = this.hedgingPool.getPoolStatus(platform)

        // Get accounts that meet the criteria
        const accounts = await this.getAccountsForPlatform(platform, criteria)
        availableAccounts.push(...accounts)
      } catch (error) {
        console.warn(`Failed to get accounts for platform ${platform}:`, error)
      }
    }

    return availableAccounts
  }

  async checkAccountHealth(accountIds: string[]): Promise<Map<string, AccountHealthStatus>> {
    const healthStatuses = new Map<string, AccountHealthStatus>()

    for (const accountId of accountIds) {
      const accountStatus = this.accountStatuses.get(accountId)

      if (accountStatus) {
        const healthStatus: AccountHealthStatus = {
          accountId,
          platform: accountStatus.platform,
          isHealthy: accountStatus.isActive(),
          healthScore: accountStatus.getHealthMetrics().healthScore,
          lastActivity: accountStatus.getLastActivity(),
          failureCount: accountStatus.getHealthMetrics().failureCount,
          balanceInfo: accountStatus.getBalanceInfo()
        }

        healthStatuses.set(accountId, healthStatus)
      }
    }

    return healthStatuses
  }

  async updateAccountAfterTrade(accountId: string, tradeResult: TradeResult): Promise<void> {
    const accountStatus = this.accountStatuses.get(accountId)

    if (accountStatus) {
      if (tradeResult.success) {
        accountStatus.recordSuccess()

        // Update balance information if provided
        if (tradeResult.executedPrice && tradeResult.executedQuantity) {
          // This would typically involve calling an API to get updated balance
          // For now, we'll just record the activity
          accountStatus.recordActivity()
        }
      } else {
        const error = new Error(tradeResult.error || 'Trade execution failed')
        accountStatus.recordFailure(error)
      }
    }

    // Update hedging pool with account performance
    if (tradeResult.success) {
      this.hedgingPool.markAccountSuccess(accountId)
    } else {
      const error = new Error(tradeResult.error || 'Trade execution failed')
      this.hedgingPool.markAccountFailed(accountId, error)
    }
  }

  async getHedgingAccountDistribution(
    totalVolume: number,
    platforms: Platform[]
  ): Promise<Map<Platform, AccountSelection[]>> {
    const distribution = new Map<Platform, AccountSelection[]>()

    // Simple equal distribution strategy
    const volumePerPlatform = totalVolume / platforms.length

    for (const platform of platforms) {
      try {
        // Select multiple accounts for the platform based on volume
        const accountCount = Math.ceil(volumePerPlatform / 10000) // Assume 10k per account max
        const accounts = await this.hedgingPool.selectMultipleAccounts(platform, accountCount)
        distribution.set(platform, accounts)
      } catch (error) {
        console.warn(`Failed to get accounts for platform ${platform}:`, error)
        distribution.set(platform, [])
      }
    }

    return distribution
  }

  async reserveAccountsForTrading(
    accountIds: string[],
    durationMs: number
  ): Promise<{ success: boolean; reservedAccounts: string[] }> {
    const reservedUntil = new Date(Date.now() + durationMs)
    const reservedAccounts: string[] = []

    for (const accountId of accountIds) {
      // Check if account is already reserved
      const existingReservation = this.reservedAccounts.get(accountId)

      if (!existingReservation || existingReservation.reservedUntil < new Date()) {
        this.reservedAccounts.set(accountId, { reservedUntil })
        reservedAccounts.push(accountId)
      }
    }

    return {
      success: reservedAccounts.length > 0,
      reservedAccounts
    }
  }

  async releaseReservedAccounts(accountIds: string[]): Promise<{ success: boolean; releasedAccounts: string[] }> {
    const releasedAccounts: string[] = []

    for (const accountId of accountIds) {
      if (this.reservedAccounts.delete(accountId)) {
        releasedAccounts.push(accountId)
      }
    }

    return {
      success: releasedAccounts.length > 0,
      releasedAccounts
    }
  }

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

  private createTradingMessage(operation: TradingOperation, parameters: TradingParameters): Uint8Array {
    // Create standardized trading message format
    const message = {
      operation,
      timestamp: Date.now(),
      ...parameters
    }

    return new TextEncoder().encode(JSON.stringify(message))
  }

  private formatSignatureForPlatform(
    platform: Platform,
    signResult: SignResult,
    parameters: TradingParameters
  ): PlatformSignatureFormat {
    switch (platform) {
      case Platform.PACIFICA:
        return {
          format: 'base64',
          encoding: signResult.signature || '',
          headers: {
            'X-Signature': signResult.signature || '',
            'X-Algorithm': 'ed25519'
          }
        }

      case Platform.ASTER:
        return {
          format: 'hex',
          encoding: signResult.signature || '',
          headers: {
            'X-Signature': signResult.signature || '',
            'X-Algorithm': 'eip191'
          }
        }

      case Platform.BINANCE:
        return {
          format: 'hex',
          encoding: signResult.signature || '',
          headers: {
            'X-MBX-APIKEY': parameters.apiKey || '',
            'X-MBX-SIGNATURE': signResult.signature || ''
          }
        }

      default:
        return {
          format: 'base64',
          encoding: signResult.signature || ''
        }
    }
  }

  private groupRequestsByPlatform(requests: TradingSignRequest[]): Record<string, TradingSignRequest[]> {
    const groups: Record<string, TradingSignRequest[]> = {}

    requests.forEach(request => {
      const platform = request.platform

      if (!groups[platform]) {
        groups[platform] = []
      }

      groups[platform].push(request)
    })

    return groups
  }

  private async getAccountsForPlatform(
    platform: Platform,
    criteria: AccountSelectionCriteria
  ): Promise<AvailableAccount[]> {
    // This would typically query the account registry
    // For now, return mock data based on pool status
    const poolStatus = this.hedgingPool.getPoolStatus(platform)

    const mockAccounts: AvailableAccount[] = []

    for (let i = 0; i < poolStatus.activeAccounts; i++) {
      mockAccounts.push({
        accountId: `${platform}-account-${i + 1}`,
        platform,
        healthScore: 0.8 + Math.random() * 0.2,
        balanceInfo: {
          totalValue: 10000 + Math.random() * 90000,
          availableBalance: 5000 + Math.random() * 45000
        },
        capabilities: ['trading', 'withdrawal'],
        estimatedCapacity: 50000 + Math.random() * 50000
      })
    }

    return mockAccounts
  }
}