import 'package:flutter_secure_storage/flutter_secure_storage.dart';

/// Secure storage service for managing sensitive data like tokens
///
/// Uses FlutterSecureStorage to encrypt and store data securely on the device.
/// This ensures tokens and other sensitive information are protected.
///
/// Usage:
/// ```dart
/// final storage = SecureStorage();
///
/// // Save token
/// await storage.saveAccessToken('your_token_here');
///
/// // Read token
/// final token = await storage.getAccessToken();
///
/// // Clear all data
/// await storage.clearAll();
/// ```
class SecureStorage {
  // Private constructor for singleton pattern
  SecureStorage._();

  /// Singleton instance
  static final SecureStorage _instance = SecureStorage._();

  /// Factory constructor returns singleton instance
  factory SecureStorage() => _instance;

  /// FlutterSecureStorage instance with default options
  static const FlutterSecureStorage _storage = FlutterSecureStorage(
    aOptions: AndroidOptions(
      encryptedSharedPreferences: true,
    ),
    iOptions: IOSOptions(
      accessibility: KeychainAccessibility.first_unlock,
    ),
  );

  // ==================== Storage Keys ====================

  /// Key for storing access token
  static const String _accessTokenKey = 'access_token';

  /// Key for storing refresh token
  static const String _refreshTokenKey = 'refresh_token';

  /// Key for storing user ID
  static const String _userIdKey = 'user_id';

  /// Key for storing username
  static const String _usernameKey = 'username';

  /// Key for storing email
  static const String _emailKey = 'email';

  /// Key for storing current user ID
  static const String _currentUserIdKey = 'current_user_id';

  // ==================== Token Management ====================

  /// Save access token securely
  Future<void> saveAccessToken(String token) async {
    try {
      await _storage.write(key: _accessTokenKey, value: token);
    } catch (e) {
      throw Exception('Failed to save access token: $e');
    }
  }

  /// Get access token
  Future<String?> getAccessToken() async {
    try {
      return await _storage.read(key: _accessTokenKey);
    } catch (e) {
      throw Exception('Failed to read access token: $e');
    }
  }

  /// Save refresh token securely
  Future<void> saveRefreshToken(String token) async {
    try {
      await _storage.write(key: _refreshTokenKey, value: token);
    } catch (e) {
      throw Exception('Failed to save refresh token: $e');
    }
  }

  /// Get refresh token
  Future<String?> getRefreshToken() async {
    try {
      return await _storage.read(key: _refreshTokenKey);
    } catch (e) {
      throw Exception('Failed to read refresh token: $e');
    }
  }

  /// Save user ID
  Future<void> saveUserId(String userId) async {
    try {
      await _storage.write(key: _userIdKey, value: userId);
    } catch (e) {
      throw Exception('Failed to save user ID: $e');
    }
  }

  /// Get user ID
  Future<String?> getUserId() async {
    try {
      return await _storage.read(key: _userIdKey);
    } catch (e) {
      throw Exception('Failed to read user ID: $e');
    }
  }

  /// Save username
  Future<void> saveUsername(String username) async {
    try {
      await _storage.write(key: _usernameKey, value: username);
    } catch (e) {
      throw Exception('Failed to save username: $e');
    }
  }

  /// Get username
  Future<String?> getUsername() async {
    try {
      return await _storage.read(key: _usernameKey);
    } catch (e) {
      throw Exception('Failed to read username: $e');
    }
  }

  /// Save email
  Future<void> saveEmail(String email) async {
    try {
      await _storage.write(key: _emailKey, value: email);
    } catch (e) {
      throw Exception('Failed to save email: $e');
    }
  }

  /// Get email
  Future<String?> getEmail() async {
    try {
      return await _storage.read(key: _emailKey);
    } catch (e) {
      throw Exception('Failed to read email: $e');
    }
  }

  /// Save current user ID
  Future<void> saveCurrentUserId(int userId) async {
    try {
      await _storage.write(key: _currentUserIdKey, value: userId.toString());
    } catch (e) {
      throw Exception('Failed to save current user ID: $e');
    }
  }

  /// Get current user ID
  Future<int?> getCurrentUserId() async {
    try {
      final value = await _storage.read(key: _currentUserIdKey);
      return value != null ? int.tryParse(value) : null;
    } catch (e) {
      throw Exception('Failed to read current user ID: $e');
    }
  }

  /// Check if user is authenticated (has valid access token)
  Future<bool> isAuthenticated() async {
    final token = await getAccessToken();
    return token != null && token.isNotEmpty;
  }

  /// Clear all stored data (logout)
  Future<void> clearAll() async {
    try {
      await _storage.deleteAll();
    } catch (e) {
      throw Exception('Failed to clear storage: $e');
    }
  }

  /// Clear only auth tokens
  Future<void> clearTokens() async {
    try {
      await _storage.delete(key: _accessTokenKey);
      await _storage.delete(key: _refreshTokenKey);
    } catch (e) {
      throw Exception('Failed to clear tokens: $e');
    }
  }

  /// Get all stored keys (useful for debugging)
  Future<Map<String, String>> readAll() async {
    try {
      return await _storage.readAll();
    } catch (e) {
      throw Exception('Failed to read all data: $e');
    }
  }

  /// Check if storage contains a specific key
  Future<bool> containsKey(String key) async {
    try {
      return await _storage.containsKey(key: key);
    } catch (e) {
      throw Exception('Failed to check key: $e');
    }
  }

  /// Write custom key-value pair
  Future<void> write(String key, String value) async {
    try {
      await _storage.write(key: key, value: value);
    } catch (e) {
      throw Exception('Failed to write data: $e');
    }
  }

  /// Read custom key
  Future<String?> read(String key) async {
    try {
      return await _storage.read(key: key);
    } catch (e) {
      throw Exception('Failed to read data: $e');
    }
  }

  /// Delete custom key
  Future<void> delete(String key) async {
    try {
      await _storage.delete(key: key);
    } catch (e) {
      throw Exception('Failed to delete data: $e');
    }
  }
}
