import 'package:bloc/bloc.dart';
import 'package:kmobile/api/services/user_service.dart';
import 'package:kmobile/core/errors/exceptions.dart';
import 'package:kmobile/data/models/user.dart';
import 'package:kmobile/features/auth/models/auth_token.dart';
import 'package:kmobile/security/secure_storage.dart';
import '../../../data/repositories/auth_repository.dart';
import 'auth_state.dart';

class AuthCubit extends Cubit<AuthState> {
  final AuthRepository _authRepository;
  final UserService _userService;
  final SecureStorage _secureStorage;

  AuthCubit(this._authRepository, this._userService, this._secureStorage)
      : super(AuthInitial()) {
    checkAuthStatus();
  }

  Future<void> checkAuthStatus() async {
    emit(AuthLoading());
    try {
      final isLoggedIn = await _authRepository.isLoggedIn();
      if (isLoggedIn) {
        final users = await _userService.getUserDetails();
        emit(Authenticated(users));
      } else {
        emit(Unauthenticated());
      }
    } catch (e) {
      emit(AuthError(e.toString()));
    }
  }

  Future<void> refreshUserData() async {
    try {
      final users = await _userService.getUserDetails();
      emit(Authenticated(users));
    } catch (e) {
      emit(AuthError('Failed to refresh user data: ${e.toString()}'));
    }
  }

  Future<void> login(String customerNo, String password) async {
    emit(AuthLoading());
    try {
      final (users, authToken) =
          await _authRepository.login(customerNo, password);

      if (authToken.tnc == false) {
        emit(ShowTncDialog(authToken, users));
      } else {
        await _checkMpinAndNavigate(users);
      }
    } catch (e) {
      emit(AuthError(e is AuthException ? e.message : e.toString()));
    }
  }

  Future<void> onTncDialogResult(
      bool agreed, AuthToken authToken, List<User> users) async {
    if (agreed) {
      try {
        await _authRepository.acceptTnc();
        // The user is NOT fully authenticated yet. Just check for MPIN.
        await _checkMpinAndNavigate(users);
      } catch (e) {
        emit(AuthError('Failed to accept TNC: $e'));
      }
    } else {
      emit(NavigateToTncRequiredScreen());
    }
  }

  void mpinSetupCompleted() {
    if (state is NavigateToMpinSetupScreen) {
      final users = (state as NavigateToMpinSetupScreen).users;
      emit(Authenticated(users));
    } else {
      // Handle unexpected state if necessary
      emit(AuthError("Invalid state during MPIN setup completion."));
    }
  }

  Future<void> _checkMpinAndNavigate(List<User> users) async {
    final mpin = await _secureStorage.read('mpin');
    if (mpin == null) {
      // No MPIN, tell UI to navigate to MPIN setup, carrying user data
      emit(NavigateToMpinSetupScreen(users));
    } else {
      // MPIN exists, user is authenticated
      emit(Authenticated(users));
    }
  }
}
