/**
 * Contract test for IUniversalHttpClient.registerPlatform()
 *
 * This test validates the platform registration functionality of the Universal HTTP Client
 * according to the contract specification. Tests MUST FAIL until implementation is complete.
 */

import { describe, test, expect, beforeEach, jest } from '@jest/globals'

// Import types that will be implemented
import type { IUniversalHttpClient, IPlatformAdapter, HealthStatus } from '@/types/httpClientCore'

describe('IUniversalHttpClient.registerPlatform() Contract', () => {
  let httpClient: IUniversalHttpClient

  beforeEach(() => {
    // This will fail until IUniversalHttpClient is implemented
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const { HttpClientCore } = require('@/core/http-client/HttpClientCore')
    httpClient = new HttpClientCore()
  })

  describe('Platform Registration', () => {
    test('should register a new platform adapter successfully', () => {
      const mockAdapter: IPlatformAdapter = {
        platform: 'test-platform',
        baseUrl: 'https://api.test-platform.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      expect(() => {
        httpClient.registerPlatform('test-platform', mockAdapter)
      }).not.toThrow()

      // Verify the platform is registered by checking if it's available for requests
      expect(httpClient.isPlatformRegistered?.('test-platform')).toBe(true)
    })

    test('should register multiple platform adapters', () => {
      const adapters = [
        {
          platform: 'platform-1',
          baseUrl: 'https://api.platform-1.com',
          request: jest.fn(),
          prepareRequest: jest.fn(),
          setProxyConfig: jest.fn(),
          getProxyStatus: jest.fn(),
          processResponse: jest.fn(),
          checkHealth: jest.fn(),
          getConfig: jest.fn(),
          validateConfig: jest.fn().mockReturnValue(true)
        },
        {
          platform: 'platform-2',
          baseUrl: 'https://api.platform-2.com',
          request: jest.fn(),
          prepareRequest: jest.fn(),
          setProxyConfig: jest.fn(),
          getProxyStatus: jest.fn(),
          processResponse: jest.fn(),
          checkHealth: jest.fn(),
          getConfig: jest.fn(),
          validateConfig: jest.fn().mockReturnValue(true)
        }
      ]

      adapters.forEach(adapter => {
        expect(() => {
          httpClient.registerPlatform(adapter.platform, adapter as IPlatformAdapter)
        }).not.toThrow()
      })

      // Verify both platforms are registered
      expect(httpClient.isPlatformRegistered?.('platform-1')).toBe(true)
      expect(httpClient.isPlatformRegistered?.('platform-2')).toBe(true)
    })

    test('should replace existing platform adapter when re-registered', () => {
      const originalAdapter: IPlatformAdapter = {
        platform: 'replaceable-platform',
        baseUrl: 'https://api.original.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      const newAdapter: IPlatformAdapter = {
        platform: 'replaceable-platform',
        baseUrl: 'https://api.new.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      // Register original adapter
      httpClient.registerPlatform('replaceable-platform', originalAdapter)
      expect(httpClient.isPlatformRegistered?.('replaceable-platform')).toBe(true)

      // Register new adapter with same platform name
      httpClient.registerPlatform('replaceable-platform', newAdapter)
      expect(httpClient.isPlatformRegistered?.('replaceable-platform')).toBe(true)

      // Verify the new adapter is being used (baseUrl should be from new adapter)
      const registeredAdapter = httpClient.getPlatformAdapter?.('replaceable-platform')
      expect(registeredAdapter?.baseUrl).toBe('https://api.new.com')
    })

    test('should validate adapter configuration before registration', () => {
      const invalidAdapter: IPlatformAdapter = {
        platform: 'invalid-platform',
        baseUrl: 'https://api.invalid.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(false) // Invalid configuration
      }

      expect(() => {
        httpClient.registerPlatform('invalid-platform', invalidAdapter)
      }).toThrow('Invalid platform configuration')
    })
  })

  describe('Platform Access', () => {
    test('should provide access to registered platform adapters', () => {
      const adapter: IPlatformAdapter = {
        platform: 'accessible-platform',
        baseUrl: 'https://api.accessible.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      httpClient.registerPlatform('accessible-platform', adapter)

      const retrievedAdapter = httpClient.getPlatformAdapter?.('accessible-platform')
      expect(retrievedAdapter).toBeDefined()
      expect(retrievedAdapter?.platform).toBe('accessible-platform')
      expect(retrievedAdapter?.baseUrl).toBe('https://api.accessible.com')
    })

    test('should return list of registered platforms', () => {
      const platforms = ['platform-a', 'platform-b', 'platform-c']

      platforms.forEach(platform => {
        const adapter: IPlatformAdapter = {
          platform,
          baseUrl: `https://api.${platform}.com`,
          request: jest.fn(),
          prepareRequest: jest.fn(),
          setProxyConfig: jest.fn(),
          getProxyStatus: jest.fn(),
          processResponse: jest.fn(),
          checkHealth: jest.fn(),
          getConfig: jest.fn(),
          validateConfig: jest.fn().mockReturnValue(true)
        }
        httpClient.registerPlatform(platform, adapter)
      })

      const registeredPlatforms = httpClient.getRegisteredPlatforms?.()
      expect(registeredPlatforms).toEqual(expect.arrayContaining(platforms))
      expect(registeredPlatforms).toHaveLength(platforms.length)
    })

    test('should check if specific platform is registered', () => {
      const adapter: IPlatformAdapter = {
        platform: 'checkable-platform',
        baseUrl: 'https://api.checkable.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      expect(httpClient.isPlatformRegistered?.('checkable-platform')).toBe(false)

      httpClient.registerPlatform('checkable-platform', adapter)

      expect(httpClient.isPlatformRegistered?.('checkable-platform')).toBe(true)
      expect(httpClient.isPlatformRegistered?.('non-existent-platform')).toBe(false)
    })
  })

  describe('Platform Management', () => {
    test('should support unregistering platforms', async () => {
      const adapter: IPlatformAdapter = {
        platform: 'removable-platform',
        baseUrl: 'https://api.removable.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      httpClient.registerPlatform('removable-platform', adapter)
      expect(httpClient.isPlatformRegistered?.('removable-platform')).toBe(true)

      const result = await httpClient.unregisterPlatform?.('removable-platform')
      expect(result?.success).toBe(true)
      expect(httpClient.isPlatformRegistered?.('removable-platform')).toBe(false)
    })

    test('should support updating platform configuration', async () => {
      const adapter: IPlatformAdapter = {
        platform: 'updatable-platform',
        baseUrl: 'https://api.updatable.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      httpClient.registerPlatform('updatable-platform', adapter)

      const updatedConfig = {
        baseUrl: 'https://api.updated.com',
        timeout: { connect: 10000, read: 60000, write: 30000 }
      }

      const result = await httpClient.updatePlatformConfig?.('updatable-platform', updatedConfig)
      expect(result?.success).toBe(true)

      const retrievedAdapter = httpClient.getPlatformAdapter?.('updatable-platform')
      expect(retrievedAdapter?.baseUrl).toBe('https://api.updated.com')
    })

    test('should provide platform configuration information', () => {
      const adapter: IPlatformAdapter = {
        platform: 'info-platform',
        baseUrl: 'https://api.info.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn().mockReturnValue({
          platform: 'info-platform',
          baseUrl: 'https://api.info.com',
          authConfig: { type: 'signature' },
          timeouts: { connect: 5000, read: 30000, write: 15000 }
        }),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      httpClient.registerPlatform('info-platform', adapter)

      const platformInfo = httpClient.getPlatformInfo?.('info-platform')
      expect(platformInfo).toBeDefined()
      expect(platformInfo?.platform).toBe('info-platform')
      expect(platformInfo?.baseUrl).toBe('https://api.info.com')
    })
  })

  describe('Health and Status', () => {
    test('should provide overall client health status', async () => {
      const adapters = [
        {
          platform: 'healthy-platform-1',
          baseUrl: 'https://api.healthy1.com',
          checkHealth: jest.fn().mockResolvedValue({ status: 'healthy', responseTime: 50 })
        },
        {
          platform: 'healthy-platform-2',
          baseUrl: 'https://api.healthy2.com',
          checkHealth: jest.fn().mockResolvedValue({ status: 'healthy', responseTime: 75 })
        }
      ]

      adapters.forEach(adapter => {
        const fullAdapter: IPlatformAdapter = {
          ...adapter,
          request: jest.fn(),
          prepareRequest: jest.fn(),
          setProxyConfig: jest.fn(),
          getProxyStatus: jest.fn(),
          processResponse: jest.fn(),
          getConfig: jest.fn(),
          validateConfig: jest.fn().mockReturnValue(true)
        }
        httpClient.registerPlatform(adapter.platform, fullAdapter)
      })

      const health: HealthStatus = await httpClient.getHealth()

      expect(health).toBeDefined()
      expect(health.status).toBe('healthy')
      expect(health.platforms).toBeDefined()
      expect(Object.keys(health.platforms)).toHaveLength(2)
      expect(health.platforms['healthy-platform-1']?.status).toBe('healthy')
      expect(health.platforms['healthy-platform-2']?.status).toBe('healthy')
    })

    test('should detect unhealthy platforms', async () => {
      const adapters = [
        {
          platform: 'healthy-platform',
          baseUrl: 'https://api.healthy.com',
          checkHealth: jest.fn().mockResolvedValue({ status: 'healthy', responseTime: 50 })
        },
        {
          platform: 'unhealthy-platform',
          baseUrl: 'https://api.unhealthy.com',
          checkHealth: jest.fn().mockRejectedValue(new Error('Platform unavailable'))
        }
      ]

      adapters.forEach(adapter => {
        const fullAdapter: IPlatformAdapter = {
          ...adapter,
          request: jest.fn(),
          prepareRequest: jest.fn(),
          setProxyConfig: jest.fn(),
          getProxyStatus: jest.fn(),
          processResponse: jest.fn(),
          getConfig: jest.fn(),
          validateConfig: jest.fn().mockReturnValue(true)
        }
        httpClient.registerPlatform(adapter.platform, fullAdapter)
      })

      const health: HealthStatus = await httpClient.getHealth()

      expect(health).toBeDefined()
      expect(health.status).toBe('degraded') // Overall status should be degraded
      expect(health.platforms['healthy-platform']?.status).toBe('healthy')
      expect(health.platforms['unhealthy-platform']?.status).toBe('unhealthy')
    })
  })

  describe('Error Handling', () => {
    test('should reject registration with empty platform name', () => {
      const adapter: IPlatformAdapter = {
        platform: '',
        baseUrl: 'https://api.test.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      expect(() => {
        httpClient.registerPlatform('', adapter)
      }).toThrow('Platform name cannot be empty')
    })

    test('should reject registration with mismatched platform name', () => {
      const adapter: IPlatformAdapter = {
        platform: 'adapter-platform',
        baseUrl: 'https://api.test.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      expect(() => {
        httpClient.registerPlatform('different-platform', adapter)
      }).toThrow('Platform name mismatch')
    })

    test('should reject registration with null or undefined adapter', () => {
      expect(() => {
        httpClient.registerPlatform('test-platform', null as any)
      }).toThrow('Platform adapter cannot be null or undefined')

      expect(() => {
        httpClient.registerPlatform('test-platform', undefined as any)
      }).toThrow('Platform adapter cannot be null or undefined')
    })
  })

  describe('Resource Cleanup', () => {
    test('should properly clean up resources when client is closed', async () => {
      const adapter: IPlatformAdapter = {
        platform: 'cleanup-platform',
        baseUrl: 'https://api.cleanup.com',
        request: jest.fn(),
        prepareRequest: jest.fn(),
        setProxyConfig: jest.fn(),
        getProxyStatus: jest.fn(),
        processResponse: jest.fn(),
        checkHealth: jest.fn(),
        getConfig: jest.fn(),
        validateConfig: jest.fn().mockReturnValue(true)
      }

      httpClient.registerPlatform('cleanup-platform', adapter)
      expect(httpClient.isPlatformRegistered?.('cleanup-platform')).toBe(true)

      await httpClient.close()

      // After closing, platform should still be registered but client should be inactive
      expect(httpClient.isPlatformRegistered?.('cleanup-platform')).toBe(true)

      // Attempting to make requests should fail
      await expect(httpClient.request({
        platform: 'cleanup-platform',
        accountId: 'test',
        method: 'GET',
        url: '/test'
      })).rejects.toThrow('Client is closed')
    })
  })
})