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

import '../../domain/auth/auth.dart';
import '../../domain/outlet/outlet.dart';

part 'auth_event.dart';
part 'auth_state.dart';
part 'auth_bloc.freezed.dart';

@injectable
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final IAuthRepository _repository;
  final IOutletRepository _outletRepository;
  AuthBloc(this._repository, this._outletRepository)
    : super(AuthState.initial()) {
    on<AuthEvent>(_onAuthEvent);
  }

  Future<void> _onAuthEvent(AuthEvent event, Emitter<AuthState> emit) {
    return event.map(
      fetchCurrentUser: (e) async {
        emit(state.copyWith(failureOption: none()));

        final token = await _repository.hasToken();

        final failureOrAuth = await _repository.currentUser();

        failureOrAuth.fold(
          (f) => emit(
            state.copyWith(
              failureOption: optionOf(f),
              status: token
                  ? AuthStatus.authenticated()
                  : AuthStatus.unauthenticated(),
            ),
          ),
          (user) => emit(
            state.copyWith(
              user: user,
              status: token
                  ? AuthStatus.authenticated()
                  : AuthStatus.unauthenticated(),
            ),
          ),
        );

        add(AuthEvent.fetchCurrentOutlet(state.user.outletId));
      },
      fetchCurrentOutlet: (e) async {
        emit(state.copyWith(failureOutletOption: none()));

        final failureOrOutlet = await _outletRepository.getOutletById(
          e.outletId,
        );

        failureOrOutlet.fold(
          (f) => emit(state.copyWith(failureOutletOption: optionOf(f))),
          (outlet) => emit(state.copyWith(outlet: outlet)),
        );
      },
    );
  }
}
