/**
 * Contract Test for AccountRegistry Interface
 *
 * Tests the core AccountRegistry functionality following TDD principles.
 * These tests MUST fail initially and pass after implementation.
 */

import { AccountRegistry } from '@/core/credential-manager/AccountRegistry'
import { Platform, Account } from '@/types/credential'

describe('AccountRegistry Contract Test', () => {
  let registry: AccountRegistry

  beforeEach(() => {
    registry = new AccountRegistry()
  })

  describe('Account Loading', () => {
    test('should load accounts from configuration', async () => {
      const config = {
        accounts: [
          {
            id: 'test-account-1',
            name: 'Test Account 1',
            platform: Platform.PACIFICA,
            enabled: true,
            credentials: {
              type: 'ed25519' as const,
              privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
            }
          }
        ]
      }

      await registry.loadAccounts(config)
      const accounts = registry.getAllAccounts()

      expect(accounts).toHaveLength(1)
      expect(accounts[0].id).toBe('test-account-1')
      expect(accounts[0].platform).toBe(Platform.PACIFICA)
    })

    test('should handle empty configuration gracefully', async () => {
      const config = { accounts: [] }

      await registry.loadAccounts(config)
      const accounts = registry.getAllAccounts()

      expect(accounts).toHaveLength(0)
    })

    test('should validate account configuration before loading', async () => {
      const invalidConfig = {
        accounts: [
          {
            id: 'invalid-account',
            // Missing required fields
            platform: Platform.PACIFICA
          }
        ]
      }

      await expect(registry.loadAccounts(invalidConfig as any))
        .rejects.toThrow('Invalid account configuration')
    })
  })

  describe('Account Retrieval', () => {
    beforeEach(async () => {
      const config = {
        accounts: [
          {
            id: 'pacifica-account',
            name: 'Pacifica Test',
            platform: Platform.PACIFICA,
            enabled: true,
            credentials: {
              type: 'ed25519' as const,
              privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
            }
          },
          {
            id: 'aster-account',
            name: 'Aster Test',
            platform: Platform.ASTER,
            enabled: true,
            credentials: {
              type: 'secp256k1' as const,
              privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
            }
          }
        ]
      }
      await registry.loadAccounts(config)
    })

    test('should get account by ID', () => {
      const account = registry.getAccount('pacifica-account')

      expect(account).toBeDefined()
      expect(account?.id).toBe('pacifica-account')
      expect(account?.platform).toBe(Platform.PACIFICA)
    })

    test('should return undefined for non-existent account', () => {
      const account = registry.getAccount('non-existent')

      expect(account).toBeUndefined()
    })

    test('should get accounts by platform', () => {
      const pacificaAccounts = registry.getAccountsByPlatform(Platform.PACIFICA)
      const asterAccounts = registry.getAccountsByPlatform(Platform.ASTER)
      const binanceAccounts = registry.getAccountsByPlatform(Platform.BINANCE)

      expect(pacificaAccounts).toHaveLength(1)
      expect(asterAccounts).toHaveLength(1)
      expect(binanceAccounts).toHaveLength(0)

      expect(pacificaAccounts[0].id).toBe('pacifica-account')
      expect(asterAccounts[0].id).toBe('aster-account')
    })

    test('should get all accounts', () => {
      const allAccounts = registry.getAllAccounts()

      expect(allAccounts).toHaveLength(2)
      expect(allAccounts.map(a => a.id)).toContain('pacifica-account')
      expect(allAccounts.map(a => a.id)).toContain('aster-account')
    })

    test('should get enabled accounts only', () => {
      const enabledAccounts = registry.getEnabledAccounts()

      expect(enabledAccounts).toHaveLength(2)
      expect(enabledAccounts.every(a => a.enabled)).toBe(true)
    })
  })

  describe('Account Management', () => {
    test('should add new account', () => {
      const newAccount: Account = {
        id: 'new-account',
        name: 'New Account',
        platform: Platform.BINANCE,
        enabled: true,
        credentials: {
          type: 'hmac' as const,
          apiKey: 'test-api-key',
          secretKey: 'test-secret-key'
        }
      }

      registry.addAccount(newAccount)
      const retrieved = registry.getAccount('new-account')

      expect(retrieved).toBeDefined()
      expect(retrieved?.platform).toBe(Platform.BINANCE)
    })

    test('should prevent duplicate account IDs', () => {
      const account1: Account = {
        id: 'duplicate-id',
        name: 'Account 1',
        platform: Platform.PACIFICA,
        enabled: true,
        credentials: {
          type: 'ed25519' as const,
          privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
        }
      }

      const account2: Account = {
        id: 'duplicate-id',
        name: 'Account 2',
        platform: Platform.ASTER,
        enabled: true,
        credentials: {
          type: 'secp256k1' as const,
          privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
        }
      }

      registry.addAccount(account1)

      expect(() => registry.addAccount(account2))
        .toThrow('Account with ID duplicate-id already exists')
    })

    test('should update existing account', () => {
      const originalAccount: Account = {
        id: 'update-test',
        name: 'Original Name',
        platform: Platform.PACIFICA,
        enabled: true,
        credentials: {
          type: 'ed25519' as const,
          privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
        }
      }

      registry.addAccount(originalAccount)

      const updatedAccount: Account = {
        ...originalAccount,
        name: 'Updated Name',
        enabled: false
      }

      registry.updateAccount('update-test', updatedAccount)
      const retrieved = registry.getAccount('update-test')

      expect(retrieved?.name).toBe('Updated Name')
      expect(retrieved?.enabled).toBe(false)
    })

    test('should remove account', () => {
      const account: Account = {
        id: 'remove-test',
        name: 'Remove Test',
        platform: Platform.PACIFICA,
        enabled: true,
        credentials: {
          type: 'ed25519' as const,
          privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
        }
      }

      registry.addAccount(account)
      expect(registry.getAccount('remove-test')).toBeDefined()

      const removed = registry.removeAccount('remove-test')
      expect(removed).toBe(true)
      expect(registry.getAccount('remove-test')).toBeUndefined()
    })

    test('should return false when removing non-existent account', () => {
      const removed = registry.removeAccount('non-existent')
      expect(removed).toBe(false)
    })
  })

  describe('Platform Support', () => {
    test('should return supported platforms', () => {
      const platforms = registry.getSupportedPlatforms()

      expect(platforms).toContain(Platform.PACIFICA)
      expect(platforms).toContain(Platform.ASTER)
      expect(platforms).toContain(Platform.BINANCE)
    })

    test('should check if platform is supported', () => {
      expect(registry.isPlatformSupported(Platform.PACIFICA)).toBe(true)
      expect(registry.isPlatformSupported(Platform.ASTER)).toBe(true)
      expect(registry.isPlatformSupported(Platform.BINANCE)).toBe(true)
    })
  })

  describe('Performance Requirements', () => {
    test('should load accounts within performance limits', async () => {
      const config = {
        accounts: Array.from({ length: 100 }, (_, i) => ({
          id: `account-${i}`,
          name: `Account ${i}`,
          platform: Platform.PACIFICA,
          enabled: true,
          credentials: {
            type: 'ed25519' as const,
            privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
          }
        }))
      }

      const startTime = Date.now()
      await registry.loadAccounts(config)
      const duration = Date.now() - startTime

      // Should load 100 accounts within 100ms
      expect(duration).toBeLessThan(100)
      expect(registry.getAllAccounts()).toHaveLength(100)
    })

    test('should retrieve accounts efficiently', async () => {
      const config = {
        accounts: Array.from({ length: 50 }, (_, i) => ({
          id: `account-${i}`,
          name: `Account ${i}`,
          platform: i % 2 === 0 ? Platform.PACIFICA : Platform.ASTER,
          enabled: true,
          credentials: {
            type: 'ed25519' as const,
            privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
          }
        }))
      }

      await registry.loadAccounts(config)

      const startTime = Date.now()
      for (let i = 0; i < 1000; i++) {
        registry.getAccount(`account-${i % 50}`)
      }
      const duration = Date.now() - startTime

      // Should handle 1000 lookups within 10ms
      expect(duration).toBeLessThan(10)
    })
  })

  describe('Error Handling', () => {
    test('should handle malformed configuration gracefully', async () => {
      const malformedConfig = {
        accounts: [
          {
            id: 'malformed',
            platform: 'invalid-platform',
            credentials: 'not-an-object'
          }
        ]
      }

      await expect(registry.loadAccounts(malformedConfig as any))
        .rejects.toThrow()
    })

    test('should provide meaningful error messages', async () => {
      const invalidConfig = {
        accounts: [
          {
            id: '',  // Empty ID
            name: 'Test',
            platform: Platform.PACIFICA,
            enabled: true,
            credentials: {
              type: 'ed25519' as const,
              privateKey: 'invalid-key'
            }
          }
        ]
      }

      await expect(registry.loadAccounts(invalidConfig))
        .rejects.toThrow('Account ID cannot be empty')
    })
  })
})