import { generateSecretKey, getPublicKey, nip19 } from 'nostr-tools'
import { SecureStorage } from '@/lib/crypto/encryption'
import { bytesToHex, hexToBytes } from '@/lib/utils/crypto'

export interface NostrIdentity {
  privateKey: string
  publicKey: string
  npub: string
  nsec: string
}

export interface NostrProfile {
  name?: string
  display_name?: string
  about?: string
  picture?: string
  banner?: string
  website?: string
  nip05?: string
  lud16?: string // Lightning address
}

export class IdentityManager {
  private static readonly STORAGE_KEY = 'nostr_identity'
  private static readonly PROFILE_KEY = 'nostr_profile'

  /**
   * Generate a new Nostr identity
   */
  static generateIdentity(): NostrIdentity {
    const privateKey = generateSecretKey()
    const publicKey = getPublicKey(privateKey)
    
    return {
      privateKey: bytesToHex(privateKey),
      publicKey,
      npub: nip19.npubEncode(publicKey),
      nsec: nip19.nsecEncode(privateKey)
    }
  }

  /**
   * Import identity from private key (hex or nsec format)
   */
  static importIdentity(privateKeyInput: string): NostrIdentity {
    let privateKeyBytes: Uint8Array

    try {
      // Try to decode as nsec first
      if (privateKeyInput.startsWith('nsec')) {
        const decoded = nip19.decode(privateKeyInput)
        if (decoded.type === 'nsec') {
          privateKeyBytes = decoded.data
        } else {
          throw new Error('Invalid nsec format')
        }
      } else {
        // Try as hex string
        if (privateKeyInput.length !== 64) {
          throw new Error('Private key must be 64 hex characters')
        }
        privateKeyBytes = hexToBytes(privateKeyInput)
      }

      if (privateKeyBytes.length !== 32) {
        throw new Error('Private key must be 32 bytes')
      }

      const publicKey = getPublicKey(privateKeyBytes)
      
      return {
        privateKey: bytesToHex(privateKeyBytes),
        publicKey,
        npub: nip19.npubEncode(publicKey),
        nsec: nip19.nsecEncode(privateKeyBytes)
      }
    } catch (error) {
      throw new Error(`Failed to import identity: ${error instanceof Error ? error.message : 'Unknown error'}`)
    }
  }

  /**
   * Save identity to localStorage (encrypted)
   */
  static async saveIdentity(identity: NostrIdentity, password?: string): Promise<void> {
    try {
      let dataToStore: any = identity
      
      if (password) {
        if (!SecureStorage.isSupported()) {
          throw new Error('Secure encryption is not supported in this browser')
        }
        
        // Encrypt sensitive data using Web Crypto API
        const sensitiveData = JSON.stringify({
          privateKey: identity.privateKey,
          nsec: identity.nsec
        })
        
        const encryptedData = await SecureStorage.encrypt(sensitiveData, password)
        
        dataToStore = {
          publicKey: identity.publicKey,
          npub: identity.npub,
          encrypted: true,
          encryptedData
        }
      }
      
      localStorage.setItem(this.STORAGE_KEY, JSON.stringify(dataToStore))
    } catch (error) {
      throw new Error(`Failed to save identity: ${error instanceof Error ? error.message : 'Unknown error'}`)
    }
  }

  /**
   * Load identity from localStorage
   */
  static async loadIdentity(password?: string): Promise<NostrIdentity | null> {
    try {
      const stored = localStorage.getItem(this.STORAGE_KEY)
      if (!stored) return null

      const storedData = JSON.parse(stored)
      
      if (storedData.encrypted && password) {
        if (!SecureStorage.isSupported()) {
          throw new Error('Secure encryption is not supported in this browser')
        }
        
        // Decrypt sensitive data
        const decryptedSensitiveData = await SecureStorage.decrypt(storedData.encryptedData, password)
        const { privateKey, nsec } = JSON.parse(decryptedSensitiveData)
        
        return {
          privateKey,
          publicKey: storedData.publicKey,
          npub: storedData.npub,
          nsec
        }
      } else if (storedData.encrypted && !password) {
        throw new Error('Password required to decrypt stored identity')
      }

      // Non-encrypted identity (legacy support)
      const identity = storedData as NostrIdentity
      
      // Validate the loaded identity
      if (!identity.privateKey || !identity.publicKey) {
        throw new Error('Invalid stored identity')
      }

      return identity
    } catch (error) {
      console.error('Failed to load identity:', error)
      throw error
    }
  }

  /**
   * Clear stored identity
   */
  static clearIdentity(): void {
    localStorage.removeItem(this.STORAGE_KEY)
    localStorage.removeItem(this.PROFILE_KEY)
  }

  /**
   * Check if identity exists in storage
   */
  static hasStoredIdentity(): boolean {
    return !!localStorage.getItem(this.STORAGE_KEY)
  }

  /**
   * Check if stored identity is encrypted
   */
  static isStoredIdentityEncrypted(): boolean {
    try {
      const stored = localStorage.getItem(this.STORAGE_KEY)
      if (!stored) return false
      
      const storedData = JSON.parse(stored)
      return !!storedData.encrypted
    } catch {
      return false
    }
  }

  /**
   * Save user profile
   */
  static saveProfile(profile: NostrProfile): void {
    localStorage.setItem(this.PROFILE_KEY, JSON.stringify(profile))
  }

  /**
   * Load user profile
   */
  static loadProfile(): NostrProfile | null {
    try {
      const stored = localStorage.getItem(this.PROFILE_KEY)
      return stored ? JSON.parse(stored) : null
    } catch (error) {
      console.error('Failed to load profile:', error)
      return null
    }
  }

}