import 'dart:developer';

import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:krow/core/application/common/validators/email_validator.dart';
import 'package:krow/core/application/di/injectable.dart';
import 'package:krow/core/data/models/staff/staff.dart';
import 'package:krow/core/data/enums/state_status.dart';
import 'package:krow/features/profile/email_verification/data/email_verification_service.dart';
import 'package:krow/features/profile/personal_info/data/staff_repository.dart';

part 'personal_info_event.dart';

part 'personal_info_state.dart';

class PersonalInfoBloc extends Bloc<PersonalInfoEvent, PersonalInfoState> {
  PersonalInfoBloc() : super(const PersonalInfoState()) {
    on<InitializeProfileInfoEvent>(_onInitializeProfileInfoEvent);

    on<UpdateProfileImage>(_onUpdateProfileImage);

    on<UpdateFirstName>(_onUpdateFirstName);

    on<UpdateLastName>(_onUpdateLastName);

    on<UpdateMiddleName>(_onUpdateMiddleName);

    on<UpdateEmail>(_onUpdateEmail);

    on<UpdatePhoneNumber>(_onUpdatePhoneNumber);

    on<UpdateEmailVerificationStatus>(_onUpdateEmailVerification);

    on<SaveProfileChanges>(_onSaveProfileChanges);
  }

  Future<void> _onInitializeProfileInfoEvent(
    InitializeProfileInfoEvent event,
    Emitter<PersonalInfoState> emit,
  ) async {
    emit(
      state.copyWith(
        isInEditMode: event.isInEditMode,
        status: event.isInEditMode ? StateStatus.loading : StateStatus.idle,
      ),
    );
    if (!state.isInEditMode) return;

    await for (final currentStaffData
        in getIt<StaffPersonalInfoRepository>().getPersonalInfo()) {
      try {
        emit(
          state.copyWith(
            firstName: currentStaffData.firstName,
            lastName: currentStaffData.lastName,
            middleName: currentStaffData.middleName,
            email: currentStaffData.email,
            phoneNumber: currentStaffData.phone,
            profileImageUrl: currentStaffData.avatar,
            isUpdateReceived: true,
            status: StateStatus.idle,
          ),
        );
      } catch (except) {
        log(except.toString());
      } finally {
        emit(state.copyWith(isUpdateReceived: false));
      }
    }

    if (state.status == StateStatus.loading) {
      emit(state.copyWith(status: StateStatus.idle));
    }
  }

  void _onUpdateProfileImage(
    UpdateProfileImage event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(state.copyWith(profileImagePath: event.imagePath));
  }

  void _onUpdateFirstName(
    UpdateFirstName event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(
      state.copyWith(
        firstName: event.firstName,
        validationErrors: Map.from(state.validationErrors)
          ..remove(ProfileRequiredField.firstName),
      ),
    );
  }

  void _onUpdateLastName(
    UpdateLastName event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(
      state.copyWith(
        lastName: event.lastName,
        validationErrors: Map.from(state.validationErrors)
          ..remove(ProfileRequiredField.lastName),
      ),
    );
  }

  void _onUpdateMiddleName(
    UpdateMiddleName event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(state.copyWith(middleName: event.middleName));
  }

  void _onUpdateEmail(
    UpdateEmail event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(
      state.copyWith(
        email: event.email,
        validationErrors: Map.from(state.validationErrors)
          ..remove(ProfileRequiredField.email),
      ),
    );
  }

  void _onUpdatePhoneNumber(
    UpdatePhoneNumber event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(state.copyWith(phoneNumber: event.phoneNumber));
  }

  void _onUpdateEmailVerification(
    UpdateEmailVerificationStatus event,
    Emitter<PersonalInfoState> emit,
  ) {
    emit(
      state.copyWith(
        isEmailVerified: event.isEmailVerified,
        shouldRouteToVerification: false,
      ),
    );

    if (state.isEmailVerified) {
      add(const SaveProfileChanges(shouldSkipEmailVerification: true));
    }
  }

  Future<void> _onSaveProfileChanges(
    SaveProfileChanges event,
    Emitter<PersonalInfoState> emit,
  ) async {
    final errorsMap = state.invalidate();
    if (errorsMap.isNotEmpty) {
      emit(
        state.copyWith(
          status: StateStatus.error,
          validationErrors: errorsMap,
        ),
      );
      return;
    }

    emit(state.copyWith(status: StateStatus.loading, validationErrors: {}));

    if (!event.shouldSkipEmailVerification) {
      log('Verifying email');
      bool isEmailVerified = getIt<EmailVerificationService>()
          .checkEmailForVerification(email: state.email);
      log('Email verified: $isEmailVerified');
      emit(
        state.copyWith(
          isEmailVerified: isEmailVerified,
          shouldRouteToVerification: !isEmailVerified,
        ),
      );

      log('Should route to Verification ${state.shouldRouteToVerification}');
      if (!isEmailVerified) {
        emit(
          state.copyWith(
            status: StateStatus.idle,
            shouldRouteToVerification: false,
          ),
        );
        return;
      }
      log('Continuing with profile saving');
    }

    Staff? response;
    try {
      response = await getIt<StaffPersonalInfoRepository>().updatePersonalInfo(
        firstName: state.firstName,
        middleName: state.middleName,
        lastName: state.lastName,
        email: state.email,
        avatarPath: state.profileImagePath,
      );
    } catch (except) {
      log(
        'Error in PersonalInfoBloc. Event SaveProfileChanges',
        error: except,
      );
    } finally {
      emit(
        state.copyWith(
          status: response != null ? StateStatus.success : StateStatus.idle,
        ),
      );
    }
  }
}
