import 'package:food_delivery_client/feature/auth/domain/usecases/verify_otp_code_login_usecase.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_otp_code_register_usecase.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_login_usecase.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_register_usecase.dart';
import 'package:food_delivery_client/feature/common/presentation/widgets/w_toastification.dart';
import 'package:food_delivery_client/food_delivery_client.dart';

part 'verify_otp_event.dart';

part 'verify_otp_state.dart';

part 'verify_otp_bloc.freezed.dart';

@injectable
class VerifyOtpBloc extends Bloc<VerifyOtpEvent, VerifyOtpState> {
  final VerifyOtpCodeRegisterUseCase _registerUseCase;
  final VerifyOtpCodeForgotPasswordUseCase _passwordUseCase;
  final VerifyPhoneRegisterUseCase _phoneRegisterUseCase;
  final VerifyPhoneNumberLoginUseCase _phoneNumberLoginUseCase;

  VerifyOtpBloc(
    this._registerUseCase,
    this._passwordUseCase,
    this._phoneRegisterUseCase,
    this._phoneNumberLoginUseCase,
  ) : super(const VerifyOtpState()) {
    Timer? timer1;

    on<_CancelTimer>((event, emit) {
      timer1?.cancel();
    });

    on<_Started>((event, emit) {
      int seconds = state.time;
      emit(state.copyWith(time: seconds));
      timer1 = Timer.periodic(TimeDelayConst.duration1, (timer) {
        if (seconds == 0) {
          timer.cancel();
        } else {
          seconds--;
          add(VerifyOtpEvent.ticked(seconds));
        }
      });
    });

    on<_Ticked>(_onTicked);
    on<_VerifyOtpReset>(_onVerifyOtpReset);
    on<_VerifyOtpRegister>(_onVerifyOtpRegister);
    on<_ResendRegister>(_onResendVerifyPhoneRegister);
    on<_ResendForgot>(_onResendVerifyPhoneForgot);
  }

  void _onTicked(_Ticked event, Emitter<VerifyOtpState> emit) {
    emit(state.copyWith(time: event.seconds));
  }

  Future<void> _onVerifyOtpReset(
    _VerifyOtpReset event,
    Emitter<VerifyOtpState> emit,
  ) async {
    emit(state.copyWith(status: RequestStatus.loading));
    final response = await _passwordUseCase.call(event.params);

    response.fold(
      (l) {
        showErrorToast(l.errorMessage);
        emit(state.copyWith(status: RequestStatus.error));
      },
      (r) {
        emit(state.copyWith(status: RequestStatus.loaded));
        add(VerifyOtpEvent.cancelTimer());
      },
    );
  }

  Future<void> _onVerifyOtpRegister(
    _VerifyOtpRegister event,
    Emitter<VerifyOtpState> emit,
  ) async {
    emit(state.copyWith(status: RequestStatus.loading));
    final response = await _registerUseCase.call(event.params);

    response.fold(
      (l) {
        showErrorToast(l.errorMessage);
        emit(state.copyWith(status: RequestStatus.error));
      },
      (r) {
        emit(state.copyWith(status: RequestStatus.loaded));
        add(VerifyOtpEvent.cancelTimer());
      },
    );
  }

  Future<void> _onResendVerifyPhoneRegister(
    _ResendRegister event,
    Emitter<VerifyOtpState> emit,
  ) async {
    emit(state.copyWith(resendStatus: RequestStatus.loading));
    final response = await _phoneRegisterUseCase.call(
      VerifyPhoneNumberParams(phoneNumber: event.phoneNUmber),
    );

    response.fold(
      (l) {
        showErrorToast(l.errorMessage);
        emit(state.copyWith(resendStatus: RequestStatus.error));
      },
      (r) {
        emit(state.copyWith(resendStatus: RequestStatus.loaded));
        add(VerifyOtpEvent.ticked(120));
        add(VerifyOtpEvent.started());
      },
    );
  }

  Future<void> _onResendVerifyPhoneForgot(
    _ResendForgot event,
    Emitter<VerifyOtpState> emit,
  ) async {
    emit(state.copyWith(resendStatus: RequestStatus.loading));
    final response = await _phoneNumberLoginUseCase.call(
      VerifyPhoneNumberParams(phoneNumber: event.phoneNUmber),
    );

    response.fold(
      (l) {
        showErrorToast(l.errorMessage);
        emit(state.copyWith(resendStatus: RequestStatus.error));
      },
      (r) {
        emit(state.copyWith(resendStatus: RequestStatus.loaded));
        add(VerifyOtpEvent.ticked(120));
        add(VerifyOtpEvent.started());
      },
    );
  }
}
