/**
 * Integration Test for Multi-Platform Signing
 *
 * Tests end-to-end signing functionality across all supported platforms.
 * Validates the complete integration between credential manager, signers, and account pools.
 */

import { CredentialManager } from '@/core/credential-manager/CredentialManager'
import { Platform } from '@/types/credential'
import { TradingOperation } from '@/core/credential-manager/TradingIntegration'

describe('Multi-Platform Signing Integration Test', () => {
  let credentialManager: CredentialManager

  beforeEach(async () => {
    const config = {
      accounts: [
        {
          id: 'pacifica-main',
          name: 'Pacifica Main Account',
          platform: Platform.PACIFICA,
          enabled: true,
          credentials: {
            type: 'ed25519' as const,
            privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
          }
        },
        {
          id: 'aster-main',
          name: 'Aster Main Account',
          platform: Platform.ASTER,
          enabled: true,
          credentials: {
            type: 'secp256k1' as const,
            privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
          }
        },
        {
          id: 'binance-main',
          name: 'Binance Main Account',
          platform: Platform.BINANCE,
          enabled: true,
          credentials: {
            type: 'hmac' as const,
            apiKey: 'test-api-key',
            secretKey: 'test-secret-key'
          }
        }
      ],
      hedging: {
        platforms: {
          [Platform.PACIFICA]: {
            enabled: true,
            primaryAccounts: ['pacifica-main'],
            backupAccounts: [],
            loadBalanceStrategy: 'round-robin',
            healthCheckInterval: 30000,
            failoverThreshold: 3
          },
          [Platform.ASTER]: {
            enabled: true,
            primaryAccounts: ['aster-main'],
            backupAccounts: [],
            loadBalanceStrategy: 'round-robin',
            healthCheckInterval: 30000,
            failoverThreshold: 3
          },
          [Platform.BINANCE]: {
            enabled: true,
            primaryAccounts: ['binance-main'],
            backupAccounts: [],
            loadBalanceStrategy: 'round-robin',
            healthCheckInterval: 30000,
            failoverThreshold: 3
          }
        },
        hedging: {
          enableCrossplatformBalancing: true,
          maxAccountsPerPlatform: 5,
          reservationTimeoutMs: 60000
        }
      }
    }

    credentialManager = new CredentialManager()
    await credentialManager.loadConfiguration(config)
  })

  afterEach(async () => {
    await credentialManager.shutdown()
  })

  describe('Basic Signing Operations', () => {
    test('should sign messages for Pacifica platform', async () => {
      const message = new TextEncoder().encode('test message for pacifica')

      const result = await credentialManager.sign('pacifica-main', message)

      expect(result.success).toBe(true)
      expect(result.signature).toBeDefined()
      expect(result.algorithm).toBe('ed25519')
      expect(result.metadata?.platform).toBe(Platform.PACIFICA)
    })

    test('should sign messages for Aster platform', async () => {
      const message = new TextEncoder().encode('test message for aster')

      const result = await credentialManager.sign('aster-main', message)

      expect(result.success).toBe(true)
      expect(result.signature).toBeDefined()
      expect(result.algorithm).toBe('eip191')
      expect(result.metadata?.platform).toBe(Platform.ASTER)
    })

    test('should sign messages for Binance platform', async () => {
      const message = new TextEncoder().encode('test message for binance')

      const result = await credentialManager.sign('binance-main', message)

      expect(result.success).toBe(true)
      expect(result.signature).toBeDefined()
      expect(result.algorithm).toBe('hmac-sha256')
      expect(result.metadata?.platform).toBe(Platform.BINANCE)
    })

    test('should handle signing failures gracefully', async () => {
      const message = new TextEncoder().encode('test message')

      const result = await credentialManager.sign('non-existent-account', message)

      expect(result.success).toBe(false)
      expect(result.error).toBeDefined()
      expect(result.error).toContain('Account not found')
    })
  })

  describe('Performance Requirements', () => {
    test('should complete signing within 50ms for all platforms', async () => {
      const message = new TextEncoder().encode('performance test message')
      const platforms = [
        { accountId: 'pacifica-main', platform: Platform.PACIFICA },
        { accountId: 'aster-main', platform: Platform.ASTER },
        { accountId: 'binance-main', platform: Platform.BINANCE }
      ]

      for (const { accountId, platform } of platforms) {
        const startTime = Date.now()
        const result = await credentialManager.sign(accountId, message)
        const duration = Date.now() - startTime

        expect(result.success).toBe(true)
        expect(duration).toBeLessThan(50) // Performance requirement
        expect(result.metadata?.duration).toBeLessThan(50)
      }
    })

    test('should handle concurrent signing operations', async () => {
      const message = new TextEncoder().encode('concurrent test message')

      const startTime = Date.now()
      const promises = [
        credentialManager.sign('pacifica-main', message),
        credentialManager.sign('aster-main', message),
        credentialManager.sign('binance-main', message),
        credentialManager.sign('pacifica-main', message),
        credentialManager.sign('aster-main', message)
      ]

      const results = await Promise.all(promises)
      const duration = Date.now() - startTime

      expect(results).toHaveLength(5)
      expect(results.every(r => r.success)).toBe(true)
      expect(duration).toBeLessThan(100) // All 5 operations within 100ms
    })
  })

  describe('Trading Integration', () => {
    test('should sign trading requests for different platforms', async () => {
      const tradingRequests = [
        {
          operation: TradingOperation.PLACE_ORDER,
          platform: Platform.PACIFICA,
          parameters: {
            symbol: 'SOL/USDC',
            side: 'buy' as const,
            type: 'limit' as const,
            quantity: 1.0,
            price: 100.0
          }
        },
        {
          operation: TradingOperation.GET_BALANCE,
          platform: Platform.ASTER,
          parameters: {}
        },
        {
          operation: TradingOperation.CANCEL_ORDER,
          platform: Platform.BINANCE,
          parameters: {
            symbol: 'BTCUSDT',
            orderId: '12345'
          }
        }
      ]

      for (const request of tradingRequests) {
        const result = await credentialManager.signTradingRequest(request)

        expect(result.success).toBe(true)
        expect(result.selectedAccount).toBeDefined()
        expect(result.selectedAccount.platform).toBe(request.platform)
        expect(result.operation).toBe(request.operation)
        expect(result.platformSignature).toBeDefined()
      }
    })

    test('should handle batch trading requests', async () => {
      const batchRequests = [
        {
          operation: TradingOperation.PLACE_ORDER,
          platform: Platform.PACIFICA,
          parameters: { symbol: 'SOL/USDC', side: 'buy' as const, quantity: 1.0 }
        },
        {
          operation: TradingOperation.PLACE_ORDER,
          platform: Platform.ASTER,
          parameters: { symbol: 'ETH/USDC', side: 'sell' as const, quantity: 0.5 }
        },
        {
          operation: TradingOperation.GET_BALANCE,
          platform: Platform.BINANCE,
          parameters: {}
        }
      ]

      const results = await credentialManager.signBatchTradingRequests(batchRequests)

      expect(results).toHaveLength(3)
      expect(results.every(r => r.success)).toBe(true)

      const platforms = results.map(r => r.selectedAccount.platform)
      expect(platforms).toContain(Platform.PACIFICA)
      expect(platforms).toContain(Platform.ASTER)
      expect(platforms).toContain(Platform.BINANCE)
    })
  })

  describe('Account Pool Integration', () => {
    test('should select accounts from hedging pool for trading', async () => {
      const accounts = await credentialManager.getAvailableAccountsForTrading({
        minBalance: 1000,
        riskTolerance: 'medium'
      })

      expect(accounts.length).toBeGreaterThan(0)

      const platforms = new Set(accounts.map(a => a.platform))
      expect(platforms.size).toBeGreaterThan(1) // Multiple platforms available
    })

    test('should handle account health monitoring', async () => {
      const accountIds = ['pacifica-main', 'aster-main', 'binance-main']

      const healthStatuses = await credentialManager.checkAccountHealth(accountIds)

      expect(healthStatuses.size).toBe(3)

      for (const [accountId, status] of healthStatuses) {
        expect(accountIds).toContain(accountId)
        expect(status.accountId).toBe(accountId)
        expect(status.isHealthy).toBe(true) // Fresh accounts should be healthy
        expect(status.healthScore).toBeGreaterThan(0)
      }
    })

    test('should handle account reservation for trading', async () => {
      const accountIds = ['pacifica-main', 'aster-main']

      const reservation = await credentialManager.reserveAccountsForTrading(accountIds, 30000)

      expect(reservation.success).toBe(true)
      expect(reservation.reservedAccounts).toEqual(expect.arrayContaining(accountIds))

      // Reserved accounts should not be selected for other operations
      const availableAccounts = await credentialManager.getAvailableAccountsForTrading({})
      const availableIds = availableAccounts.map(a => a.accountId)

      // Should have fewer available accounts (reserved ones excluded)
      expect(availableIds).not.toContain('pacifica-main')
      expect(availableIds).not.toContain('aster-main')

      // Release reservations
      const release = await credentialManager.releaseReservedAccounts(accountIds)
      expect(release.success).toBe(true)
    })
  })

  describe('Cross-Platform Hedging', () => {
    test('should distribute hedging across multiple platforms', async () => {
      const platforms = [Platform.PACIFICA, Platform.ASTER, Platform.BINANCE]
      const totalVolume = 30000

      const distribution = await credentialManager.getHedgingAccountDistribution(
        totalVolume,
        platforms
      )

      expect(distribution.size).toBe(3) // All platforms should have accounts

      for (const [platform, accounts] of distribution) {
        expect(platforms).toContain(platform)
        expect(accounts.length).toBeGreaterThan(0)
        expect(accounts.every(a => a.platform === platform)).toBe(true)
      }
    })

    test('should handle cross-platform account selection', async () => {
      const platforms = [Platform.PACIFICA, Platform.ASTER]
      const accountCount = 2

      const accounts = await credentialManager.selectAccountsAcrossPlatforms(
        platforms,
        accountCount
      )

      expect(accounts.length).toBeLessThanOrEqual(accountCount)

      const selectedPlatforms = new Set(accounts.map(a => a.platform))
      expect(selectedPlatforms.size).toBeGreaterThan(1) // Multiple platforms selected
    })
  })

  describe('Error Recovery and Failover', () => {
    test('should handle account failures and recover', async () => {
      const message = new TextEncoder().encode('test message')

      // Simulate account failure
      credentialManager.updateAccountAfterTrade('pacifica-main', {
        success: false,
        error: 'Simulated failure',
        timestamp: new Date()
      })

      // Account should still be usable (not immediately disabled)
      const result = await credentialManager.sign('pacifica-main', message)
      expect(result.success).toBe(true)

      // Record success to recover
      credentialManager.updateAccountAfterTrade('pacifica-main', {
        success: true,
        tradeId: 'recovery-test',
        timestamp: new Date()
      })

      const healthCheck = await credentialManager.checkAccountHealth(['pacifica-main'])
      const health = healthCheck.get('pacifica-main')
      expect(health?.isHealthy).toBe(true)
    })

    test('should disable accounts after repeated failures', async () => {
      // Simulate multiple failures
      for (let i = 0; i < 5; i++) {
        credentialManager.updateAccountAfterTrade('pacifica-main', {
          success: false,
          error: `Failure ${i + 1}`,
          timestamp: new Date()
        })
      }

      const healthCheck = await credentialManager.checkAccountHealth(['pacifica-main'])
      const health = healthCheck.get('pacifica-main')
      expect(health?.consecutiveFailures).toBe(5)
      expect(health?.isHealthy).toBe(false)
    })
  })

  describe('Platform-Specific Signature Formats', () => {
    test('should generate correct signature format for Pacifica', async () => {
      const request = {
        operation: TradingOperation.PLACE_ORDER,
        platform: Platform.PACIFICA,
        parameters: {
          symbol: 'SOL/USDC',
          side: 'buy' as const,
          quantity: 1.0
        }
      }

      const result = await credentialManager.signTradingRequest(request)

      expect(result.platformSignature.format).toBe('base64')
      expect(result.platformSignature.headers?.['X-Algorithm']).toBe('ed25519')
    })

    test('should generate correct signature format for Aster', async () => {
      const request = {
        operation: TradingOperation.GET_BALANCE,
        platform: Platform.ASTER,
        parameters: {}
      }

      const result = await credentialManager.signTradingRequest(request)

      expect(result.platformSignature.format).toBe('hex')
      expect(result.platformSignature.headers?.['X-Algorithm']).toBe('eip191')
    })

    test('should generate correct signature format for Binance', async () => {
      const request = {
        operation: TradingOperation.GET_POSITIONS,
        platform: Platform.BINANCE,
        parameters: {
          apiKey: 'test-api-key'
        }
      }

      const result = await credentialManager.signTradingRequest(request)

      expect(result.platformSignature.format).toBe('hex')
      expect(result.platformSignature.headers?.['X-MBX-APIKEY']).toBeDefined()
      expect(result.platformSignature.headers?.['X-MBX-SIGNATURE']).toBeDefined()
    })
  })
})