/**
 * Simple Account Registry
 *
 * Provides simple account management for storing and retrieving credentials
 * without complex abstractions. Supports multiple platforms and accounts.
 */

import type { Credentials } from '@/types/credential'
import { logger } from '@/utils/logger'

export interface RegisteredAccount {
  /** Account identifier */
  accountId: string

  /** Platform identifier */
  platform: string

  /** Account credentials */
  credentials: Credentials

  /** Account metadata */
  metadata?: {
    name?: string
    description?: string
    tags?: string[]
    created?: Date
    lastUsed?: Date
  }
}

export interface AccountRegistryConfig {
  /** Maximum number of accounts to store */
  maxAccounts?: number

  /** Whether to log account operations */
  enableLogging?: boolean

  /** Whether to update lastUsed timestamp on credential access */
  trackUsage?: boolean
}

export class AccountRegistry {
  private accounts = new Map<string, RegisteredAccount>()
  private config: Required<AccountRegistryConfig>

  constructor(config: AccountRegistryConfig = {}) {
    this.config = {
      maxAccounts: 100,
      enableLogging: true,
      trackUsage: true,
      ...config,
    }
  }

  /**
   * Register an account with credentials
   */
  register(account: Omit<RegisteredAccount, 'metadata'> & { metadata?: RegisteredAccount['metadata'] }): void {
    const key = this.generateKey(account.platform, account.accountId)

    // Check account limit
    if (this.accounts.size >= this.config.maxAccounts && !this.accounts.has(key)) {
      throw new Error(`Cannot register account: maximum limit of ${this.config.maxAccounts} accounts reached`)
    }

    // Validate account data
    this.validateAccount(account)

    const registeredAccount: RegisteredAccount = {
      ...account,
      metadata: {
        created: new Date(),
        ...account.metadata,
      },
    }

    this.accounts.set(key, registeredAccount)

    if (this.config.enableLogging) {
      logger.info(`Account registered: ${account.platform}:${account.accountId}`)
    }
  }

  /**
   * Get credentials for an account
   */
  getCredentials(platform: string, accountId: string): Credentials | null {
    const key = this.generateKey(platform, accountId)
    const account = this.accounts.get(key)

    if (!account) {
      return null
    }

    // Update last used timestamp
    if (this.config.trackUsage && account.metadata) {
      account.metadata.lastUsed = new Date()
    }

    return account.credentials
  }

  /**
   * Check if account exists
   */
  hasAccount(platform: string, accountId: string): boolean {
    const key = this.generateKey(platform, accountId)
    return this.accounts.has(key)
  }

  /**
   * Get account information (without credentials)
   */
  getAccount(platform: string, accountId: string): Omit<RegisteredAccount, 'credentials'> | null {
    const key = this.generateKey(platform, accountId)
    const account = this.accounts.get(key)

    if (!account) {
      return null
    }

    // Return account without credentials
    const { credentials, ...accountInfo } = account
    return accountInfo
  }

  /**
   * List all registered accounts (without credentials)
   */
  listAccounts(): Array<Omit<RegisteredAccount, 'credentials'>> {
    return Array.from(this.accounts.values()).map(({ credentials, ...account }) => account)
  }

  /**
   * List accounts by platform
   */
  listAccountsByPlatform(platform: string): Array<Omit<RegisteredAccount, 'credentials'>> {
    return this.listAccounts().filter(account => account.platform === platform)
  }

  /**
   * Unregister an account
   */
  unregister(platform: string, accountId: string): boolean {
    const key = this.generateKey(platform, accountId)
    const existed = this.accounts.delete(key)

    if (existed && this.config.enableLogging) {
      logger.info(`Account unregistered: ${platform}:${accountId}`)
    }

    return existed
  }

  /**
   * Clear all accounts
   */
  clear(): void {
    const count = this.accounts.size
    this.accounts.clear()

    if (this.config.enableLogging) {
      logger.info(`Cleared ${count} registered accounts`)
    }
  }

  /**
   * Get registry statistics
   */
  getStats(): {
    totalAccounts: number
    accountsByPlatform: Record<string, number>
    oldestAccount?: Date
    newestAccount?: Date
    maxAccounts: number
  } {
    const accounts = Array.from(this.accounts.values())
    const accountsByPlatform: Record<string, number> = {}

    let oldestAccount: Date | undefined
    let newestAccount: Date | undefined

    for (const account of accounts) {
      // Count by platform
      accountsByPlatform[account.platform] = (accountsByPlatform[account.platform] || 0) + 1

      // Track dates
      const created = account.metadata?.created
      if (created) {
        if (!oldestAccount || created < oldestAccount) {
          oldestAccount = created
        }
        if (!newestAccount || created > newestAccount) {
          newestAccount = created
        }
      }
    }

    return {
      totalAccounts: this.accounts.size,
      accountsByPlatform,
      oldestAccount,
      newestAccount,
      maxAccounts: this.config.maxAccounts,
    }
  }

  /**
   * Update account metadata
   */
  updateMetadata(
    platform: string,
    accountId: string,
    metadata: Partial<RegisteredAccount['metadata']>
  ): boolean {
    const key = this.generateKey(platform, accountId)
    const account = this.accounts.get(key)

    if (!account) {
      return false
    }

    account.metadata = {
      ...account.metadata,
      ...metadata,
    }

    return true
  }

  // Private helper methods

  private generateKey(platform: string, accountId: string): string {
    return `${platform}:${accountId}`
  }

  private validateAccount(account: Omit<RegisteredAccount, 'metadata'>): void {
    if (!account.platform || account.platform.trim() === '') {
      throw new Error('Platform cannot be empty')
    }

    if (!account.accountId || account.accountId.trim() === '') {
      throw new Error('Account ID cannot be empty')
    }

    if (!account.credentials) {
      throw new Error('Credentials are required')
    }

    // Validate credentials based on type
    switch (account.credentials.type) {
      case 'ed25519':
        if (!account.credentials.privateKey) {
          throw new Error('Ed25519 credentials require privateKey')
        }
        break
      case 'hmac':
        if (!account.credentials.apiKey || !account.credentials.secretKey) {
          throw new Error('HMAC credentials require apiKey and secretKey')
        }
        break
      case 'eip191':
        if (!account.credentials.privateKey) {
          throw new Error('EIP-191 credentials require privateKey')
        }
        break
      default:
        throw new Error(`Unsupported credential type: ${account.credentials.type}`)
    }
  }
}

/**
 * Global account registry instance
 */
export const globalAccountRegistry = new AccountRegistry({
  maxAccounts: 1000,
  enableLogging: true,
  trackUsage: true,
})

/**
 * Create account registry with custom configuration
 */
export function createAccountRegistry(config?: AccountRegistryConfig): AccountRegistry {
  return new AccountRegistry(config)
}

export default AccountRegistry