import 'package:flutter/foundation.dart';
import 'package:mypoint_flutter_app/shared/widgets/base_view/base_response_model.dart';
import 'package:mypoint_flutter_app/app/config/constants.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import '../firebase/push_token_service.dart';
import '../../features/login/model/login_token_response_model.dart';
import '../network/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) {
        debugPrint('Login failed: ${authResponse.errorMessage}');
        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: ErrorCodes.commonError,
      );
    }
  }

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

    switch (errorCode) {
      case ErrorCodes.deviceUndefined || ErrorCodes.deviceLock:
        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: ErrorCodes.commonError,
          );
        }
        await Future.delayed(Duration(seconds: attempt * 2));
      }
    }
    debugPrint('Failed to fetch user profile after $maxRetries attempts');
    return LoginResponse(
      result: LoginResult.networkError,
      message: ErrorCodes.commonError,
    );
  }

  /// Upload FCM token safely (non-blocking)
  Future<void> _uploadFCMTokenSafely() async {
    try {
      await PushTokenService.uploadIfLogged();
    } catch (e) {
      // Log error but don't fail login
      debugPrint('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: ErrorCodes.commonError,
      );
    }
  }

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