/**
 * Platform Detection Utility
 *
 * Smart platform identification for accounts based on credential patterns,
 * key formats, and other distinguishing characteristics.
 */

import { Platform, IPlatformDetector, Credentials } from '@/types/credential'

/**
 * Pacifica platform detector
 * Detects Ed25519 credentials with specific patterns
 */
export class PacificaDetector implements IPlatformDetector {
  readonly confidence = 0.9

  detect(credentials: any): Platform | null {
    if (!credentials || typeof credentials !== 'object') {
      return null
    }

    // Check for Ed25519 signature type
    if (credentials.type === 'ed25519') {
      return Platform.PACIFICA
    }

    // Check for 64-character hex private key (Ed25519 format)
    if (credentials.privateKey && typeof credentials.privateKey === 'string') {
      const privateKey = credentials.privateKey.toLowerCase()

      // Ed25519 private key: 64 hex characters (32 bytes)
      if (/^[0-9a-f]{64}$/.test(privateKey)) {
        return Platform.PACIFICA
      }
    }

    // Check for base58 public key pattern (common in Pacifica)
    if (credentials.publicKey && typeof credentials.publicKey === 'string') {
      const publicKey = credentials.publicKey

      // Base58 encoded keys are typically 32-44 characters
      if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(publicKey) && !publicKey.startsWith('0x')) {
        return Platform.PACIFICA
      }
    }

    return null
  }
}

/**
 * Aster platform detector
 * Detects EIP-191 (Ethereum-style) credentials
 */
export class AsterDetector implements IPlatformDetector {
  readonly confidence = 0.85

  detect(credentials: any): Platform | null {
    if (!credentials || typeof credentials !== 'object') {
      return null
    }

    // Check for EIP-191 signature type
    if (credentials.type === 'eip191') {
      return Platform.ASTER
    }

    // Check for 0x-prefixed private key (Ethereum format)
    if (credentials.privateKey && typeof credentials.privateKey === 'string') {
      const privateKey = credentials.privateKey.toLowerCase()

      // Ethereum private key: 0x + 64 hex characters
      if (/^0x[0-9a-f]{64}$/.test(privateKey)) {
        return Platform.ASTER
      }
    }

    // Check for Ethereum address pattern
    if (credentials.address && typeof credentials.address === 'string') {
      const address = credentials.address.toLowerCase()

      // Ethereum address: 0x + 40 hex characters
      if (/^0x[0-9a-f]{40}$/.test(address)) {
        return Platform.ASTER
      }
    }

    // Check for public key in Ethereum format
    if (credentials.publicKey && typeof credentials.publicKey === 'string') {
      const publicKey = credentials.publicKey.toLowerCase()

      // Ethereum public key: 0x + 128 hex characters (uncompressed)
      if (/^0x[0-9a-f]{128}$/.test(publicKey)) {
        return Platform.ASTER
      }
    }

    return null
  }
}

/**
 * Binance platform detector
 * Detects HMAC-SHA256 API key/secret credentials
 */
export class BinanceDetector implements IPlatformDetector {
  readonly confidence = 0.95

  detect(credentials: any): Platform | null {
    if (!credentials || typeof credentials !== 'object') {
      return null
    }

    // Check for HMAC signature type
    if (credentials.type === 'hmac') {
      return Platform.BINANCE
    }

    // Check for API key/secret pattern
    const hasApiKey = credentials.apiKey && typeof credentials.apiKey === 'string'
    const hasSecretKey = credentials.secretKey && typeof credentials.secretKey === 'string'

    if (hasApiKey && hasSecretKey) {
      const apiKey = credentials.apiKey
      const secretKey = credentials.secretKey

      // Binance API keys are typically 64 characters, alphanumeric
      const binanceApiKeyPattern = /^[A-Za-z0-9]{64}$/

      // Binance secret keys are typically 64 characters, alphanumeric
      const binanceSecretKeyPattern = /^[A-Za-z0-9]{64}$/

      if (binanceApiKeyPattern.test(apiKey) && binanceSecretKeyPattern.test(secretKey)) {
        return Platform.BINANCE
      }

      // Alternative: any API key/secret combination for HMAC
      if (apiKey.length >= 16 && secretKey.length >= 16) {
        return Platform.BINANCE
      }
    }

    return null
  }
}

/**
 * Main platform detector that uses multiple detectors
 */
export class PlatformDetector {
  private detectors: IPlatformDetector[]

  constructor() {
    this.detectors = [
      new BinanceDetector(), // Highest confidence first
      new PacificaDetector(),
      new AsterDetector(),
    ]
  }

  /**
   * Detect platform for given credentials
   * @param credentials Credential object to analyze
   * @returns Detected platform or null if cannot determine
   */
  detectPlatform(credentials: any): Platform | null {
    if (!credentials) {
      return null
    }

    // Try each detector in order of confidence
    for (const detector of this.detectors) {
      const platform = detector.detect(credentials)
      if (platform) {
        return platform
      }
    }

    return null
  }

  /**
   * Get detection results from all detectors
   * @param credentials Credential object to analyze
   * @returns Array of detection results with confidence scores
   */
  getAllDetectionResults(credentials: any): Array<{
    platform: Platform | null
    confidence: number
    detector: string
  }> {
    const results = []

    for (const detector of this.detectors) {
      const platform = detector.detect(credentials)
      results.push({
        platform,
        confidence: detector.confidence,
        detector: detector.constructor.name,
      })
    }

    return results
  }

  /**
   * Validate that credentials match the specified platform
   * @param credentials Credential object
   * @param expectedPlatform Expected platform
   * @returns True if credentials match the platform
   */
  validatePlatformMatch(credentials: any, expectedPlatform: Platform): boolean {
    const detectedPlatform = this.detectPlatform(credentials)
    return detectedPlatform === expectedPlatform
  }

  /**
   * Get suggested platforms for ambiguous credentials
   * @param credentials Credential object
   * @returns Array of possible platforms with confidence scores
   */
  getSuggestedPlatforms(credentials: any): Array<{
    platform: Platform
    confidence: number
    reason: string
  }> {
    const suggestions = []

    const results = this.getAllDetectionResults(credentials)

    for (const result of results) {
      if (result.platform) {
        suggestions.push({
          platform: result.platform,
          confidence: result.confidence,
          reason: `Detected by ${result.detector}`,
        })
      }
    }

    // Sort by confidence (highest first)
    return suggestions.sort((a, b) => b.confidence - a.confidence)
  }

  /**
   * Add custom detector
   * @param detector Custom platform detector
   */
  addDetector(detector: IPlatformDetector): void {
    this.detectors.push(detector)

    // Re-sort by confidence (highest first)
    this.detectors.sort((a, b) => b.confidence - a.confidence)
  }

  /**
   * Remove detector by class name
   * @param detectorName Name of detector class to remove
   */
  removeDetector(detectorName: string): void {
    this.detectors = this.detectors.filter(detector => detector.constructor.name !== detectorName)
  }

  /**
   * Check if credentials are valid for any supported platform
   * @param credentials Credential object
   * @returns True if credentials are valid for at least one platform
   */
  isValidCredentials(credentials: any): boolean {
    return this.detectPlatform(credentials) !== null
  }

  /**
   * Generate credential validation report
   * @param credentials Credential object
   * @returns Detailed validation report
   */
  generateValidationReport(credentials: any): {
    isValid: boolean
    detectedPlatform: Platform | null
    allResults: Array<{
      platform: Platform | null
      confidence: number
      detector: string
    }>
    suggestions: Array<{
      platform: Platform
      confidence: number
      reason: string
    }>
    issues: string[]
  } {
    const detectedPlatform = this.detectPlatform(credentials)
    const allResults = this.getAllDetectionResults(credentials)
    const suggestions = this.getSuggestedPlatforms(credentials)
    const issues = []

    // Check for common issues
    if (!credentials) {
      issues.push('No credentials provided')
    } else if (typeof credentials !== 'object') {
      issues.push('Credentials must be an object')
    } else {
      if (!detectedPlatform) {
        issues.push('Could not detect platform from credentials')
      }

      if (!credentials.type) {
        issues.push('Missing credential type')
      }

      // Platform-specific validation
      if (credentials.type === 'ed25519' && !credentials.privateKey) {
        issues.push('Ed25519 credentials missing privateKey')
      }

      if (credentials.type === 'eip191' && !credentials.privateKey) {
        issues.push('EIP-191 credentials missing privateKey')
      }

      if (credentials.type === 'hmac' && (!credentials.apiKey || !credentials.secretKey)) {
        issues.push('HMAC credentials missing apiKey or secretKey')
      }
    }

    return {
      isValid: detectedPlatform !== null && issues.length === 0,
      detectedPlatform,
      allResults,
      suggestions,
      issues,
    }
  }
}
