import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart';
import 'package:local_auth/local_auth.dart';
import 'package:sigap/src/cores/services/supabase_service.dart';
import 'package:sigap/src/features/personalization/data/models/models/user_metadata_model.dart';

class BiometricService extends GetxService {
  static BiometricService get instance => Get.find<BiometricService>();

  final LocalAuthentication _localAuth = LocalAuthentication();
  final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();

  final RxBool isBiometricAvailable = false.obs;
  final RxBool isAuthenticated = false.obs;

  // Keys for secure storage
  static const String _biometricEnabledKey = 'biometric_enabled';
  static const String _userIdKey = 'user_id';
  static const String _sessionKey = 'session';
  static const String _identifierKey = 'identifier'; // NIK or NRP

  // Initialize the biometric service
  Future<BiometricService> init() async {
    await _checkBiometrics();
    return this;
  }

  // Check if biometric authentication is available
  Future<bool> _checkBiometrics() async {
    try {
      isBiometricAvailable.value =
          await _localAuth.canCheckBiometrics &&
          await _localAuth.isDeviceSupported();
      return isBiometricAvailable.value;
    } on PlatformException catch (_) {
      isBiometricAvailable.value = false;
      return false;
    }
  }

  // Get available biometric types
  Future<List<BiometricType>> getAvailableBiometrics() async {
    try {
      return await _localAuth.getAvailableBiometrics();
    } on PlatformException catch (_) {
      return [];
    }
  }

  // Request biometric authentication
  Future<bool> authenticate({
    String reason = 'Authenticate to continue',
  }) async {
    try {
      if (!isBiometricAvailable.value) {
        await _checkBiometrics();
        if (!isBiometricAvailable.value) return false;
      }

      isAuthenticated.value = await _localAuth.authenticate(
        localizedReason: reason,
        options: const AuthenticationOptions(
          stickyAuth: true,
          biometricOnly: true,
        ),
      );

      return isAuthenticated.value;
    } on PlatformException catch (_) {
      isAuthenticated.value = false;
      return false;
    }
  }

  // Enable biometric login for the current user
  Future<void> enableBiometricLogin() async {
    final user = SupabaseService.instance.currentUser;
    if (user == null) return;

    await _secureStorage.write(key: _biometricEnabledKey, value: 'true');
    await _secureStorage.write(key: _userIdKey, value: user.id);

    // Store user email and hashed password for session recovery
    final userMetadata = UserMetadataModel.fromJson(user.userMetadata);
    if (userMetadata.officerData?.email != null) {
      await _secureStorage.write(
        key: 'user_email',
        value: userMetadata.officerData?.email,
      );
    }

    // Store the current session's refresh token instead of access token
    // The refresh token has longer validity and can be used to generate new tokens
    final session = SupabaseService.instance.client.auth.currentSession;
    if (session != null) {
      await _secureStorage.write(key: _sessionKey, value: session.refreshToken);
    }

    // Parse user metadata with our type-safe model
    String? identifier;

    if (userMetadata.isOfficer && userMetadata.officerData != null) {
      identifier = userMetadata.officerData!.nrp;
    } else if (userMetadata.nik != null) {
      identifier = userMetadata.nik;
    }

    if (identifier != null) {
      await _secureStorage.write(key: _identifierKey, value: identifier);
    }
  }

  // Disable biometric login
  Future<void> disableBiometricLogin() async {
    await _secureStorage.delete(key: _biometricEnabledKey);
    await _secureStorage.delete(key: _userIdKey);
    await _secureStorage.delete(key: _sessionKey);
    await _secureStorage.delete(key: _identifierKey);
  }

  // Check if biometric login is enabled
  Future<bool> isBiometricLoginEnabled() async {
    final enabled = await _secureStorage.read(key: _biometricEnabledKey);
    return enabled == 'true';
  }

  // Attempt to perform biometric login
  Future<String?> attemptBiometricLogin() async {
    if (!await isBiometricLoginEnabled()) return null;

    final success = await authenticate(reason: 'Log in to your account');
    if (!success) return null;

    // Return the stored refresh token
    final token = await _secureStorage.read(key: _sessionKey);

    if (token == null || token.isEmpty) {
      // If no token is found, disable biometric login as it's in an inconsistent state
      await disableBiometricLogin();
      return null;
    }

    return token;
  }

  // Get stored user identifier (NIK or NRP)
  Future<String?> getStoredIdentifier() async {
    return await _secureStorage.read(key: _identifierKey);
  }
}
