import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import '../../../model/location/city.dart';
import '../../../model/location/country.dart';
import '../../../model/location/provinces.dart';
import '../../../model/location/region.dart';
import '../../../model/profile/eligibility.dart';
import '../../../model/utils/eligibility.dart';
import '../../../sevices/profile/eligibility_services.dart';
import '../../../utils/location_utilities.dart';
import '../../../utils/profile_utilities.dart';
part 'eligibility_event.dart';
part 'eligibility_state.dart';

class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
  EligibilityBloc() : super(EligibilityInitial()) {
    List<Country> globalCountries = [];
    List<Region> globalRegions = [];
    List<Eligibility> globalEligibilities = [];
    List<EligibityCert> eligibilities = [];
//// LOAD ELIGIBILTY
    on<LoadEligibility>((event, emit) {
      emit(EligibilityLoadingState());
      emit(EligibilityLoaded(eligibilities: eligibilities));
    });

    //// DELETE
    on<DeleteEligibility>((event, emit) async {
      try {
        final bool success = await EligibilityService.instance.delete(
            eligibilityId: event.eligibilityId,
            profileId: int.parse(event.profileId),
            token: event.token);
        if (success) {
          eligibilities.removeWhere(
              ((EligibityCert element) => element.id == event.eligibilityId));
          emit(DeletedState(
            success: success,
          ));
        } else {
          emit(DeletedState(success: success));
        }
      } catch (e) {
        emit(EligibilityErrorState(message: e.toString()));
      }
    });

//// GET ELIGIBILITY
    on<GetEligibilities>((event, emit) async {
      try {
        if (eligibilities.isNotEmpty) {
          emit(EligibilityLoaded(eligibilities: eligibilities));
        } else {
          emit(EligibilityLoadingState());
          eligibilities = await EligibilityService.instance
              .getEligibilities(event.profileId, event.token);
          emit(EligibilityLoaded(eligibilities: eligibilities));
        }
      } catch (e) {
        emit(EligibilityErrorState(message: e.toString()));
      }
    });
//// SHOW EDIT FORM
    on<ShowEditEligibilityForm>((event, emit) async {
      try {
        if (globalCountries.isEmpty) {
          List<Country> countries = await LocationUtils.instance.getCountries();
          globalCountries = countries;
        }
        if (globalRegions.isEmpty) {
          List<Region> regions = await LocationUtils.instance.getRegions();
          globalRegions = regions;
        }
        if (globalEligibilities.isEmpty) {
          List<Eligibility> eligibilities =
              await ProfileUtilities.instance.getEligibilities();
          globalEligibilities = eligibilities;
        }
        Eligibility currentEligibility = globalEligibilities.firstWhere(
            (Eligibility eligibility) =>
                event.eligibityCert.eligibility!.id == eligibility.id);
        bool? isOverseas = event.eligibityCert.overseas;
        Country currentCountry = globalCountries.firstWhere((Country country) =>
            event.eligibityCert.examAddress!.country!.code == country.code);
        if (event.eligibityCert.examAddress?.cityMunicipality?.province
                ?.region !=
            null) {
          Region currrentRegion = globalRegions.firstWhere((Region region) =>
              event.eligibityCert.examAddress!.cityMunicipality!.province!
                  .region!.code ==
              region.code);
          List<Province> provinces = await LocationUtils.instance
              .getProvinces(regionCode: currrentRegion.code.toString());
          Province currentProvince = provinces.firstWhere((Province province) =>
              event.eligibityCert.examAddress!.cityMunicipality!.province!
                  .code ==
              province.code);
          List<CityMunicipality> cities = await LocationUtils.instance
              .getCities(code: currentProvince.code.toString());
          CityMunicipality currentCity = cities.firstWhere(
              (CityMunicipality cityMunicipality) =>
                  event.eligibityCert.examAddress!.cityMunicipality!.code ==
                  cityMunicipality.code);

          emit(EditEligibilityState(
              currentCity: currentCity,
              selectedCountry: currentCountry,
              currentProvince: currentProvince,
              currentRegion: currrentRegion,
              currentEligibility: currentEligibility,
              provinces: provinces,
              cities: cities,
              isOverseas: isOverseas!,
              eligibityCert: event.eligibityCert,
              countries: globalCountries,
              regions: globalRegions,
              eligibilities: globalEligibilities));
        } else {
          emit(EditEligibilityState(
              selectedCountry: currentCountry,
              currentCity: null,
              currentProvince: null,
              currentRegion: null,
              provinces: null,
              cities: null,
              currentEligibility: currentEligibility,
              isOverseas: isOverseas!,
              eligibityCert: event.eligibityCert,
              countries: globalCountries,
              regions: globalRegions,
              eligibilities: globalEligibilities));
        }
      } catch (e) {
        emit(EligibilityErrorState(message: e.toString()));
      }
    });

    //// UPDATE
    on<UpdateEligibility>((event, emit) async {
      try {
        Map<dynamic, dynamic> status = await EligibilityService.instance.update(
            eligibityCert: event.eligibityCert,
            token: event.token,
            profileId: int.parse(event.profileId),
            oldEligibility: event.oldEligibility);
        if (status['success']) {
          EligibityCert newEligibility = EligibityCert.fromJson(status['data']);
          eligibilities.removeWhere(
              (EligibityCert element) => element.id == event.eligibityCert.id);
          eligibilities.add(newEligibility);
          emit(EligibilityEditedState(response: status));
        } else {
          emit(EligibilityEditedState(response: status));
        }
      } catch (e) {
        emit(EligibilityErrorState(message: e.toString()));
      }
    });
    //// SHOW ADD FORM
    on<ShowAddEligibilityForm>((event, emit) async {
      emit(EligibilityLoadingState());
      try {
        if (globalRegions.isEmpty) {
          List<Region> regions = await LocationUtils.instance.getRegions();
          globalRegions = regions;
        }
        if (globalEligibilities.isEmpty) {
          List<Eligibility> eligibilities =
              await ProfileUtilities.instance.getEligibilities();
          globalEligibilities = eligibilities;
        }
        if (globalCountries.isEmpty) {
          List<Country> countries = await LocationUtils.instance.getCountries();
          globalCountries = countries;
        }

        emit(AddEligibilityState(
            eligibilities: globalEligibilities,
            regions: globalRegions,
            countries: globalCountries));
      } catch (e) {
        emit(EligibilityErrorState(message: e.toString()));
      }
    });

    //// ADD
    on<AddEligibility>(
      (event, emit) async {
        try {
          Map<dynamic, dynamic> status = await EligibilityService.instance.add(
              eligibityCert: event.eligibityCert,
              token: event.token,
              profileId: int.parse(event.profileId));
          if (status['success']) {
            EligibityCert? eligibityCert =
                EligibityCert.fromJson(status['data']);
            eligibilities.add(eligibityCert);
            emit(EligibilityAddedState(response: status));
          } else {
            emit(EligibilityAddedState(response: status));
          }
        } catch (e) {
          emit(EligibilityErrorState(message: e.toString()));
        }
      },
    );
    on<CallErrorState>((event, emit) {
      emit(const EligibilityErrorState(
          message: "Something went wrong. Please try again"));
    });
  }
}
