/**
 * Platform Adapter Factory
 *
 * Factory for creating platform-specific HTTP adapters with credential manager integration.
 * Provides a unified interface for adapter instantiation and configuration.
 */

import type { IPlatformAdapter, PlatformConfig } from '@/types/platformAdapter'

export class PlatformAdapterFactory {
  private static adapters: Map<string, new (config: PlatformConfig) => IPlatformAdapter> = new Map()

  /**
   * Register platform adapter class
   * @param platform Platform identifier
   * @param adapterClass Adapter class constructor
   */
  static registerAdapter(platform: string, adapterClass: new (config: PlatformConfig) => IPlatformAdapter): void {
    if (!platform || platform.trim() === '') {
      throw new Error('Platform name cannot be empty')
    }

    if (!adapterClass) {
      throw new Error('Adapter class cannot be null or undefined')
    }

    this.adapters.set(platform, adapterClass)
  }

  /**
   * Create platform adapter instance
   * @param platform Platform identifier
   * @param config Platform configuration
   * @returns Platform adapter instance
   */
  static createAdapter(platform: string, config: PlatformConfig): IPlatformAdapter {
    const AdapterClass = this.adapters.get(platform)

    if (!AdapterClass) {
      throw new Error(`No adapter registered for platform: ${platform}`)
    }

    if (!config || config.platform !== platform) {
      throw new Error(`Invalid configuration for platform: ${platform}`)
    }

    const adapter = new AdapterClass(config)

    if (!adapter.validateConfig()) {
      throw new Error(`Invalid adapter configuration for platform: ${platform}`)
    }

    return adapter
  }

  /**
   * Check if platform adapter is registered
   * @param platform Platform identifier
   * @returns Whether adapter is registered
   */
  static isAdapterRegistered(platform: string): boolean {
    return this.adapters.has(platform)
  }

  /**
   * Get list of registered platforms
   * @returns Array of registered platform names
   */
  static getRegisteredPlatforms(): string[] {
    return Array.from(this.adapters.keys())
  }

  /**
   * Unregister platform adapter
   * @param platform Platform identifier
   * @returns Whether adapter was unregistered
   */
  static unregisterAdapter(platform: string): boolean {
    return this.adapters.delete(platform)
  }

  /**
   * Clear all registered adapters
   */
  static clearAdapters(): void {
    this.adapters.clear()
  }

  /**
   * Create platform adapter with default configuration
   * @param platform Platform identifier
   * @returns Platform adapter instance with default config
   */
  static createAdapterWithDefaults(platform: string): IPlatformAdapter {
    const defaultConfigs: Record<string, PlatformConfig> = {
      pacifica: {
        platform: 'pacifica',
        baseUrl: 'https://api.pacifica.fi',
        authConfig: {
          type: 'signature',
          algorithm: 'Ed25519',
        },
        timeouts: {
          connect: 5000,
          read: 30000,
          write: 30000,
        },
      },
      binance: {
        platform: 'binance',
        baseUrl: 'https://api.binance.com',
        authConfig: {
          type: 'signature',
          algorithm: 'HMAC-SHA256',
        },
        timeouts: {
          connect: 5000,
          read: 30000,
          write: 30000,
        },
      },
      aster: {
        platform: 'aster',
        baseUrl: 'https://api.aster.network',
        authConfig: {
          type: 'signature',
          algorithm: 'EIP-191',
        },
        timeouts: {
          connect: 5000,
          read: 30000,
          write: 30000,
        },
      },
    }

    const config = defaultConfigs[platform]
    if (!config) {
      throw new Error(`No default configuration available for platform: ${platform}`)
    }

    return this.createAdapter(platform, config)
  }

  /**
   * Create multiple adapters
   * @param configs Array of platform configurations
   * @returns Map of platform adapters
   */
  static createMultipleAdapters(configs: PlatformConfig[]): Map<string, IPlatformAdapter> {
    const adapters = new Map<string, IPlatformAdapter>()

    for (const config of configs) {
      const adapter = this.createAdapter(config.platform, config)
      adapters.set(config.platform, adapter)
    }

    return adapters
  }

  /**
   * Validate platform configuration
   * @param config Platform configuration
   * @returns Whether configuration is valid
   */
  static validateConfig(config: PlatformConfig): boolean {
    if (!config) {
      return false
    }

    if (!config.platform || config.platform.trim() === '') {
      return false
    }

    if (!config.baseUrl || !this.isValidUrl(config.baseUrl)) {
      return false
    }

    if (!config.authConfig?.type) {
      return false
    }

    return true
  }

  /**
   * Get platform adapter information
   * @param platform Platform identifier
   * @returns Adapter information
   */
  static getAdapterInfo(platform: string): {
    registered: boolean
    defaultConfigAvailable: boolean
    supportedAuthTypes: string[]
  } {
    const registered = this.isAdapterRegistered(platform)
    const defaultConfigAvailable = ['pacifica', 'binance', 'aster'].includes(platform)

    const authTypeMap: Record<string, string[]> = {
      pacifica: ['signature'],
      binance: ['signature', 'apikey'],
      aster: ['signature'],
    }

    return {
      registered,
      defaultConfigAvailable,
      supportedAuthTypes: authTypeMap[platform] || ['signature'],
    }
  }

  private static isValidUrl(url: string): boolean {
    try {
      new URL(url)
      return true
    } catch {
      return false
    }
  }
}

export default PlatformAdapterFactory
