import 'package:mypoint_flutter_app/base/base_response_model.dart';
import 'package:mypoint_flutter_app/configs/constants.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart';
import '../firebase/push_token_service.dart';
import '../model/auth/login_token_response_model.dart';
import '../networking/restful_api_viewmodel.dart';

/// Login result enum để handle các trạng thái khác nhau
enum LoginResult {
  success,
  invalidCredentials,
  deviceUndefined,
  requiredChangePass,
  invalidAccount,
  bioTokenInvalid,
  networkError,
  unknownError,
}

/// Login response model
class LoginResponse {
  final LoginResult result;
  final String? message;
  final String? errorCode;
  
  LoginResponse({
    required this.result,
    this.message,
    this.errorCode,
  });
}

/// Centralized Login Service
class LoginService extends RestfulApiViewModel {
  static final LoginService _instance = LoginService._internal();
  factory LoginService() => _instance;
  LoginService._internal();

  /// Main login method với proper error handling
  Future<LoginResponse> login(String phone, String password) async {
    try {
      // Step 1: Authenticate user
      final authResponse = await client.login(phone, password);
      
      if (!authResponse.isSuccess || authResponse.data == null) {
        return _handleAuthError(authResponse);
      }

      // Step 2: Save token
      await DataPreference.instance.saveLoginToken(authResponse.data!);

      // Step 3: Get user profile (critical step)
      final profileResult = await _getUserProfileWithRetry();
      if (profileResult.result != LoginResult.success) {
        // Rollback: Clear token if profile fetch fails
        await DataPreference.instance.clearLoginToken();
        return LoginResponse(
          result: LoginResult.networkError,
          message: profileResult.message ?? Constants.commonError,
        );
      }

      // Step 4: Upload FCM token (non-critical, don't fail login if this fails)
      await _uploadFCMTokenSafely();

      return LoginResponse(result: LoginResult.success);
      
    } catch (e) {
      return LoginResponse(
        result: LoginResult.networkError,
        message: 'Đăng nhập thất bại: ${e.toString()}',
      );
    }
  }

  /// Handle authentication errors
  LoginResponse _handleAuthError(BaseResponseModel<LoginTokenResponseModel> response) {
    final errorCode = response.errorCode;
    final errorMsg = response.errorMessage ?? Constants.commonError;

    switch (errorCode) {
      case ErrorCodes.deviceUndefined:
        return LoginResponse(
          result: LoginResult.deviceUndefined,
          message: errorMsg,
          errorCode: errorCode,
        );
      case ErrorCodes.requiredChangePass:
        return LoginResponse(
          result: LoginResult.requiredChangePass,
          message: errorMsg,
          errorCode: errorCode,
        );
      case ErrorCodes.invalidAccount:
        return LoginResponse(
          result: LoginResult.invalidAccount,
          message: errorMsg,
          errorCode: errorCode,
        );
      case ErrorCodes.bioTokenInvalid:
        return LoginResponse(
          result: LoginResult.bioTokenInvalid,
          message: errorMsg,
          errorCode: errorCode,
        );
      default:
        return LoginResponse(
          result: LoginResult.invalidCredentials,
          message: errorMsg,
          errorCode: errorCode,
        );
    }
  }

  /// Get user profile with retry mechanism
  Future<LoginResponse> _getUserProfileWithRetry({int maxRetries = 3}) async {
    for (int attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        final response = await client.getUserProfile();
        
        if (response.isSuccess && response.data != null) {
          await DataPreference.instance.saveUserProfile(response.data!);
          return LoginResponse(result: LoginResult.success);
        }
        
        // If not last attempt, wait before retry
        if (attempt < maxRetries) {
          await Future.delayed(Duration(seconds: attempt * 2));
        }
      } catch (e) {
        if (attempt == maxRetries) {
          return LoginResponse(
            result: LoginResult.networkError,
            message: 'Không thể tải thông tin người dùng: ${e.toString()}',
          );
        }
        await Future.delayed(Duration(seconds: attempt * 2));
      }
    }
    
    return LoginResponse(
      result: LoginResult.networkError,
      message: 'Không thể tải thông tin người dùng sau $maxRetries lần thử',
    );
  }

  /// Upload FCM token safely (non-blocking)
  Future<void> _uploadFCMTokenSafely() async {
    try {
      await PushTokenService.uploadIfLogged();
    } catch (e) {
      // Log error but don't fail login
      print('Warning: Failed to upload FCM token: $e');
    }
  }

  /// Biometric login
  Future<LoginResponse> biometricLogin(String phone) async {
    try {
      final response = await client.loginWithBiometric(phone);
      
      if (!response.isSuccess || response.data == null) {
        return _handleAuthError(response);
      }

      await DataPreference.instance.saveLoginToken(response.data!);
      
      final profileResult = await _getUserProfileWithRetry();
      if (profileResult.result != LoginResult.success) {
        await DataPreference.instance.clearLoginToken();
        return LoginResponse(
          result: LoginResult.networkError,
          message: profileResult.message ?? Constants.commonError,
        );
      }

      await _uploadFCMTokenSafely();
      return LoginResponse(result: LoginResult.success);
      
    } catch (e) {
      return LoginResponse(
        result: LoginResult.networkError,
        message: 'Đăng nhập sinh trắc thất bại: ${e.toString()}',
      );
    }
  }

  /// Clear biometric token for specific phone
  void clearBiometricToken(String phone) {
    DataPreference.instance.clearBioToken(phone);
  }
}
