import { BaseService } from '@/core/base/BaseService'

/**
 * Centralized storage service providing user-scoped localStorage operations
 * 
 * Features:
 * - Automatic user-scoped key generation
 * - Type-safe storage operations  
 * - Consistent data isolation between users
 * - Fallback to global storage for anonymous users
 * - Error handling with graceful degradation
 */
export class StorageService extends BaseService {
  // Service metadata
  protected readonly metadata = {
    name: 'StorageService',
    version: '1.0.0',
    dependencies: ['AuthService'] // Depends on auth for user pubkey
  }

  /**
   * Service-specific initialization (called by BaseService)
   */
  protected async onInitialize(): Promise<void> {
    this.debug('StorageService initialized')
  }

  /**
   * Generate user-scoped storage key
   * @param baseKey - Base key to scope to current user
   * @returns User-scoped key or base key if no user
   */
  private getUserStorageKey(baseKey: string): string {
    if (!this.authService?.user?.value?.pubkey) {
      // No user authenticated, use global key
      return baseKey
    }
    
    const userPubkey = this.authService.user.value.pubkey
    return `${baseKey}_${userPubkey}`
  }

  /**
   * Store user-scoped data in localStorage
   * @param key - Base storage key
   * @param data - Data to store (will be JSON serialized)
   */
  setUserData<T>(key: string, data: T): void {
    try {
      const storageKey = this.getUserStorageKey(key)
      const serializedData = JSON.stringify(data)
      localStorage.setItem(storageKey, serializedData)
      
      this.debug(`Stored user data: ${storageKey}`)
    } catch (error) {
      console.error(`Failed to store user data for key "${key}":`, error)
    }
  }

  /**
   * Retrieve user-scoped data from localStorage
   * @param key - Base storage key
   * @param defaultValue - Default value if not found
   * @returns Stored data or default value
   */
  getUserData<T>(key: string, defaultValue?: T): T | undefined {
    try {
      const storageKey = this.getUserStorageKey(key)
      const stored = localStorage.getItem(storageKey)
      
      if (stored === null) {
        this.debug(`No stored data found for key: ${storageKey}`)
        return defaultValue
      }
      
      const parsed = JSON.parse(stored) as T
      this.debug(`Retrieved user data: ${storageKey}`)
      return parsed
      
    } catch (error) {
      console.error(`Failed to retrieve user data for key "${key}":`, error)
      return defaultValue
    }
  }

  /**
   * Remove user-scoped data from localStorage
   * @param key - Base storage key
   */
  clearUserData(key: string): void {
    try {
      const storageKey = this.getUserStorageKey(key)
      localStorage.removeItem(storageKey)
      
      this.debug(`Cleared user data: ${storageKey}`)
    } catch (error) {
      console.error(`Failed to clear user data for key "${key}":`, error)
    }
  }

  /**
   * Check if user-scoped data exists
   * @param key - Base storage key
   * @returns True if data exists
   */
  hasUserData(key: string): boolean {
    try {
      const storageKey = this.getUserStorageKey(key)
      return localStorage.getItem(storageKey) !== null
    } catch (error) {
      console.error(`Failed to check user data for key "${key}":`, error)
      return false
    }
  }

  /**
   * Get all keys for the current user (useful for cleanup)
   * @returns Array of storage keys belonging to current user
   */
  getUserKeys(): string[] {
    try {
      if (!this.authService?.user?.value?.pubkey) {
        return []
      }

      const userPubkey = this.authService.user.value.pubkey
      const userKeys: string[] = []

      // Scan localStorage for keys belonging to this user
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (key && key.endsWith(`_${userPubkey}`)) {
          userKeys.push(key)
        }
      }

      return userKeys
    } catch (error) {
      console.error('Failed to get user keys:', error)
      return []
    }
  }

  /**
   * Clear all data for the current user (useful on logout)
   */
  clearAllUserData(): void {
    try {
      const userKeys = this.getUserKeys()
      
      for (const key of userKeys) {
        localStorage.removeItem(key)
      }
      
      this.debug(`Cleared all user data: ${userKeys.length} keys`)
    } catch (error) {
      console.error('Failed to clear all user data:', error)
    }
  }

  /**
   * Migrate data from old storage pattern to user-scoped pattern
   * @param oldKey - Old global key
   * @param newKey - New base key for user scoping
   */
  migrateToUserScoped<T>(oldKey: string, newKey: string): void {
    try {
      // Only migrate if we have a user and old data exists
      if (!this.authService?.user?.value?.pubkey) {
        return
      }

      const oldData = localStorage.getItem(oldKey)
      if (oldData) {
        const parsed = JSON.parse(oldData) as T
        this.setUserData(newKey, parsed)
        localStorage.removeItem(oldKey)
        
        this.debug(`Migrated data from "${oldKey}" to user-scoped "${newKey}"`)
      }
    } catch (error) {
      console.error(`Failed to migrate data from "${oldKey}" to "${newKey}":`, error)
    }
  }

  /**
   * Get current user pubkey (for debugging)
   */
  getCurrentUserPubkey(): string | null {
    return this.authService?.user?.value?.pubkey || null
  }

  /**
   * Cleanup when service is disposed (called by BaseService)
   */
  protected async onDispose(): Promise<void> {
    this.debug('StorageService disposed')
  }
}

// Export singleton instance
export const storageService = new StorageService()