import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';

import '../../../common/service/device_info_service.dart';
import '../../../common/service/fcm_service.dart';
import '../../../domain/auth/auth.dart';

part 'login_form_event.dart';
part 'login_form_state.dart';
part 'login_form_bloc.freezed.dart';

@injectable
class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
  final IAuthRepository _authRepository;
  final FcmService _fcmService;
  final DeviceInfoService _deviceInfoService;

  LoginFormBloc(
    this._authRepository,
    this._fcmService,
    this._deviceInfoService,
  ) : super(LoginFormState.initial()) {
    on<LoginFormEvent>(_onLoginFormEvent);
  }

  Future<void> _onLoginFormEvent(
    LoginFormEvent event,
    Emitter<LoginFormState> emit,
  ) {
    return event.map(
      emailChanged: (e) async {
        emit(state.copyWith(email: e.email, failureOrLoginOption: none()));
      },
      passwordChanged: (e) async {
        emit(
          state.copyWith(password: e.password, failureOrLoginOption: none()),
        );
      },
      submitted: (e) async {
        Either<AuthFailure, Login>? failureOrLogin;
        emit(state.copyWith(isSubmitting: true, failureOrLoginOption: none()));

        final emailValid = state.email.isNotEmpty;
        final passwordValid = state.password.isNotEmpty;

        log(
          'emailValid: $emailValid, passwordValid: $passwordValid, email: ${state.email}, password: ${state.password}',
        );

        if (emailValid && passwordValid) {
          final fcmToken = await _fcmService.getToken() ?? '';
          final devicePayload = await _deviceInfoService.getDevicePayload();

          failureOrLogin = await _authRepository.login(
            email: state.email,
            password: state.password,
            fcmToken: fcmToken,
            devicePayload: devicePayload,
          );

          emit(
            state.copyWith(
              isSubmitting: false,
              failureOrLoginOption: optionOf(failureOrLogin),
            ),
          );
        }
        emit(state.copyWith(showErrorMessages: true, isSubmitting: false));
      },
    );
  }
}
