import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';

import 'profile_setup_event.dart';
import 'profile_setup_state.dart';

export 'profile_setup_event.dart';
export 'profile_setup_state.dart';

/// BLoC responsible for managing the profile setup state and logic.
class ProfileSetupBloc extends Bloc<ProfileSetupEvent, ProfileSetupState> {
  ProfileSetupBloc({
    required auth.FirebaseAuth firebaseAuth,
    required dc.ExampleConnector dataConnect,
  }) : _firebaseAuth = firebaseAuth,
       _dataConnect = dataConnect,
       super(const ProfileSetupState()) {
    on<ProfileSetupFullNameChanged>(_onFullNameChanged);
    on<ProfileSetupBioChanged>(_onBioChanged);
    on<ProfileSetupLocationsChanged>(_onLocationsChanged);
    on<ProfileSetupDistanceChanged>(_onDistanceChanged);
    on<ProfileSetupSkillsChanged>(_onSkillsChanged);
    on<ProfileSetupIndustriesChanged>(_onIndustriesChanged);
    on<ProfileSetupSubmitted>(_onSubmitted);
  }

  final auth.FirebaseAuth _firebaseAuth;
  final dc.ExampleConnector _dataConnect;

  /// Handles the [ProfileSetupFullNameChanged] event.
  void _onFullNameChanged(
    ProfileSetupFullNameChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(fullName: event.fullName));
  }

  /// Handles the [ProfileSetupBioChanged] event.
  void _onBioChanged(
    ProfileSetupBioChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(bio: event.bio));
  }

  /// Handles the [ProfileSetupLocationsChanged] event.
  void _onLocationsChanged(
    ProfileSetupLocationsChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(preferredLocations: event.locations));
  }

  /// Handles the [ProfileSetupDistanceChanged] event.
  void _onDistanceChanged(
    ProfileSetupDistanceChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(maxDistanceMiles: event.distance));
  }

  /// Handles the [ProfileSetupSkillsChanged] event.
  void _onSkillsChanged(
    ProfileSetupSkillsChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(skills: event.skills));
  }

  /// Handles the [ProfileSetupIndustriesChanged] event.
  void _onIndustriesChanged(
    ProfileSetupIndustriesChanged event,
    Emitter<ProfileSetupState> emit,
  ) {
    emit(state.copyWith(industries: event.industries));
  }

  /// Handles the [ProfileSetupSubmitted] event.
  Future<void> _onSubmitted(
    ProfileSetupSubmitted event,
    Emitter<ProfileSetupState> emit,
  ) async {
    emit(state.copyWith(status: ProfileSetupStatus.loading));

    try {
      final auth.User? firebaseUser = _firebaseAuth.currentUser;
      if (firebaseUser == null) {
        throw Exception('User not authenticated.');
      }

      final dc.StaffSession? session = dc.StaffSessionStore.instance.session;
      final String email = session?.user.email ?? '';
      final String? phone = firebaseUser.phoneNumber;

      final fdc.OperationResult<dc.CreateStaffData, dc.CreateStaffVariables>
          result = await _dataConnect
              .createStaff(
                userId: firebaseUser.uid,
                fullName: state.fullName,
              )
              .bio(state.bio.isEmpty ? null : state.bio)
              .preferredLocations(state.preferredLocations)
              .maxDistanceMiles(state.maxDistanceMiles.toInt())
              .industries(state.industries)
              .skills(state.skills)
              .email(email.isEmpty ? null : email)
              .phone(phone)
              .execute();

      final String staffId = result.data.staff_insert.id ;
      final Staff staff = Staff(
        id: staffId,
        authProviderId: firebaseUser.uid,
        name: state.fullName,
        email: email,
        phone: phone,
        status: StaffStatus.completedProfile,
      );
      if (session != null) {
        dc.StaffSessionStore.instance.setSession(
          dc.StaffSession(user: session.user, staff: staff),
        );
      }

      emit(state.copyWith(status: ProfileSetupStatus.success));
    } catch (e) {
      emit(
        state.copyWith(
          status: ProfileSetupStatus.failure,
          errorMessage: e.toString(),
        ),
      );
    }
  }
}
