import 'package:be_happy/data/repositories/app_settings_repository_impl.dart';
import 'package:be_happy/data/repositories/certificate_repository_impl.dart';
import 'package:be_happy/data/repositories/notification_repository_impl.dart';
import 'package:be_happy/data/repositories/payment_repository_impl.dart'; // ← новый
import 'package:be_happy/data/repositories/scooter_repository_impl.dart';
import 'package:be_happy/data/repositories/zone_repository_impl.dart';
import 'package:be_happy/data/service/app_setting_service.dart';
import 'package:be_happy/data/service/device_info_service_impl.dart';
import 'package:be_happy/data/service/security_service_impl.dart';
import 'package:be_happy/domain/repositories/app_settings_repository.dart';
import 'package:be_happy/domain/repositories/certificate_repository.dart';
import 'package:be_happy/domain/repositories/notification_repository.dart';
import 'package:be_happy/domain/repositories/payment_repository.dart'; // ← новый
import 'package:be_happy/domain/repositories/pin_repository.dart';
import 'package:be_happy/domain/repositories/profile_repository.dart';
import 'package:be_happy/domain/repositories/scooter_repository.dart';
import 'package:be_happy/domain/repositories/zone_repository.dart';
import 'package:be_happy/domain/service/security_service.dart';
import 'package:be_happy/domain/usecase/add_payment_card_usecase.dart'; // ← новый
import 'package:be_happy/domain/usecase/get_certificates_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_order_route_history_usecase.dart';
import 'package:be_happy/domain/usecase/is_pin_set_usecase.dart';
import 'package:be_happy/domain/usecase/purchase_certificate_usecase.dart';
import 'package:be_happy/domain/usecase/book_scooter_usecase.dart';
import 'package:be_happy/domain/usecase/cancel_notification_usecase.dart';
import 'package:be_happy/domain/usecase/create_pin_usecase.dart';
import 'package:be_happy/domain/usecase/get_address_by_point_usecase.dart';
import 'package:be_happy/domain/usecase/get_available_scooters_usecase.dart';
import 'package:be_happy/domain/usecase/get_available_subscriptions_usecase.dart';
import 'package:be_happy/domain/usecase/get_available_tariffs_usecase.dart';
import 'package:be_happy/domain/usecase/get_available_zones_usecase.dart';
import 'package:be_happy/domain/usecase/get_client_orders_usecase.dart';
import 'package:be_happy/domain/usecase/get_map_settings_usecase.dart';
import 'package:be_happy/domain/usecase/get_notifications_stream_usecase.dart';
import 'package:be_happy/domain/usecase/get_payment_cards_usecase.dart';
import 'package:be_happy/domain/usecase/get_pedestrian_routes_usecase.dart';
import 'package:be_happy/domain/usecase/get_profile_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_usecase.dart';
import 'package:be_happy/domain/usecase/get_subscription_by_id_usecase.dart';
import 'package:be_happy/domain/usecase/get_subscription_by_id_usecase.dart';
import 'package:be_happy/domain/usecase/login_usecase.dart';
import 'package:be_happy/domain/usecase/logout_usecase.dart';
import 'package:be_happy/domain/usecase/pay_ride_usecase.dart';
import 'package:be_happy/domain/usecase/refresh_token_usecase.dart';
import 'package:be_happy/domain/usecase/save_map_settings_usecase.dart';
import 'package:be_happy/domain/usecase/update_profile_usecase.dart';
import 'package:be_happy/domain/usecase/upload_profile_photo_usecase.dart';
import 'package:be_happy/domain/usecase/verify_code_usecase.dart';
import 'package:be_happy/domain/usecase/upload_scooter_photos_usecase.dart';
import 'package:be_happy/domain/usecase/update_scooter_order_data_usecase.dart';
import 'package:be_happy/domain/usecase/pay_scooter_order_with_photos_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_order_by_id_usecase.dart';
import 'package:be_happy/domain/usecase/finish_ride_usecase.dart';
import 'package:be_happy/domain/usecase/pause_ride_usecase.dart';
import 'package:be_happy/domain/usecase/resume_ride_usecase.dart';
import 'package:be_happy/domain/usecase/verify_pin_usecase.dart';
import 'package:be_happy/presentation/viewmodel/active_ride_bloc.dart';
import 'package:be_happy/presentation/viewmodel/add_card_bloc.dart'; // ← новый
import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart';
import 'package:be_happy/presentation/viewmodel/map_settings_modal_bloc.dart';
import 'package:be_happy/presentation/viewmodel/payment_confirm_bloc.dart';
import 'package:be_happy/presentation/viewmodel/payment_method_sheet_bloc.dart';
import 'package:be_happy/presentation/viewmodel/payment_methods_bloc.dart';
import 'package:be_happy/presentation/viewmodel/pin_bloc.dart';
import 'package:be_happy/presentation/viewmodel/profile_bloc.dart';
import 'package:be_happy/presentation/viewmodel/scooter_detail_bloc.dart';
import 'package:be_happy/presentation/viewmodel/scooter_code_bloc.dart';
import 'package:be_happy/presentation/viewmodel/send_photo_bloc.dart';
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
import 'package:be_happy/presentation/viewmodel/tariff_sheet_bloc.dart';
import 'package:be_happy/domain/usecase/cancel_ride_usecase.dart';
import 'package:be_happy/domain/usecase/start_ride_usecase.dart';
import 'package:be_happy/domain/usecase/check_user_usecase.dart';
import 'package:be_happy/presentation/viewmodel/reserved_ride_bloc.dart';
import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

import '../data/interceptor/auth_interceptor.dart';
import '../data/network/api_service.dart';
import '../data/network/geocoding_remote_datasource.dart';
import '../data/repositories/auth_repository_impl.dart';
import '../data/repositories/news_repository_impl.dart';
import '../data/repositories/pin_repository_impl.dart';
import '../data/repositories/profile_repository_impl.dart';
import '../data/repositories/promo_code_repository_impl.dart';
import '../data/service/news_api_service.dart';
import '../domain/repositories/auth_repository.dart';
import '../domain/repositories/news_repository.dart';
import '../domain/repositories/promo_code_repository.dart';
import '../domain/service/device_info_service.dart';
import '../domain/usecase/activate_subscription_usecase.dart';
import '../domain/usecase/apply_promo_code_usecase.dart';
import '../domain/usecase/get_client_subscriptions_usecase.dart';
import '../domain/usecase/get_news_by_id_usecase.dart';
import '../domain/usecase/get_notifications_usecase.dart';
import '../domain/usecase/get_scooter_by_title_usecase.dart';
import '../domain/usecase/get_scooter_order_history_usecase.dart';
import '../domain/usecase/remove_payment_card_usecase.dart';
import '../domain/usecase/set_main_payment_card_usecase.dart';
import '../presentation/viewmodel/auth_bloc.dart';
import '../presentation/viewmodel/edit_profile_bloc.dart';
import '../presentation/viewmodel/map_bloc.dart';
import '../presentation/viewmodel/news_bloc.dart';
import '../presentation/viewmodel/notifications_bloc.dart';
import '../presentation/viewmodel/order_history_bloc.dart';
import '../presentation/viewmodel/promo_code_bloc.dart';
import '../presentation/viewmodel/scooter_detail_modal_bloc.dart';
import '../presentation/viewmodel/subscription_list_bloc.dart';
import '../presentation/viewmodel/verify_code_bloc.dart';

final getIt = GetIt.instance;

Future<void> setupDependencies() async {
  final sharedPreferences = await SharedPreferences.getInstance();
  final dio = Dio();
  dio.interceptors.add(LogInterceptor(/*requestHeader: false, responseHeader:false, */responseBody: true, requestBody: true));
  dio.interceptors.add(AuthInterceptor());
  // HTTP
  getIt.registerSingleton<http.Client>(http.Client());
  //SecureStorage
  getIt.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());

  //SharedPrefs
  getIt.registerSingleton<SharedPreferences>(sharedPreferences);

  // Service
  getIt.registerSingleton<SecurityService>(SecurityServiceImpl(getIt()));

  getIt.registerLazySingleton(() => ApiService(getIt<SecurityService>(), dio));

  getIt.registerSingleton<GeocodingRemoteDataSource>(
    GeocodingRemoteDataSource(),
  );

  getIt.registerSingleton<DeviceInfoService>(DeviceInfoServiceImpl());

  getIt.registerSingleton<AppSettingsService>(AppSettingsService(getIt()));

  getIt.registerLazySingleton<NewsApiService>(
        () => NewsApiService(getIt<ApiService>()),
  );

  // Repository
  getIt.registerSingleton<AuthRepository>(
    AuthRepositoryImpl(getIt(), getIt(), getIt()),
  );

  getIt.registerSingleton<PinRepository>(PinRepositoryImpl(getIt()));

  getIt.registerSingleton<UserProfileRepository>(
    UserProfileRepositoryImpl(getIt()),
  );

  getIt.registerSingleton<ScooterRepository>(ScooterRepositoryImpl(getIt()));

  getIt.registerSingleton<ZoneRepository>(ZoneRepositoryImpl(getIt()));

  getIt.registerSingleton<AppSettingsRepository>(
    AppSettingsRepositoryImpl(getIt()),
  );

  getIt.registerSingleton<PaymentRepository>(
    PaymentRepositoryImpl(getIt(), getIt()),
  );

  getIt.registerSingleton<CertificateRepository>(
    CertificateRepositoryImpl(getIt(), getIt()),
  );

  getIt.registerLazySingleton<NewsRepository>(
        () => NewsRepositoryImpl(getIt<NewsApiService>()),
  );

  getIt.registerSingleton<NotificationRepository>(
    NotificationRepositoryImpl(getIt()),
  );

  // Use Cases
  getIt.registerSingleton<LoginUseCase>(LoginUseCase(getIt()));

  getIt.registerSingleton<LogoutUseCase>(LogoutUseCase(getIt(), getIt()));

  getIt.registerSingleton<VerifyCodeUseCase>(VerifyCodeUseCase(getIt()));

  getIt.registerSingleton<RefreshTokenUseCase>(RefreshTokenUseCase(getIt()));

  getIt.registerSingleton<CreatePinUseCase>(CreatePinUseCase(getIt()));

  getIt.registerSingleton<VerifyPinUseCase>(VerifyPinUseCase(getIt()));

  getIt.registerSingleton<IsPinSetUsecase>(IsPinSetUsecase(getIt()));

  getIt.registerSingleton<GetProfileUseCase>(GetProfileUseCase(getIt()));

  getIt.registerSingleton<UpdateProfileUseCase>(UpdateProfileUseCase(getIt()));

  getIt.registerSingleton<UploadProfilePhotoUsecase>(
    UploadProfilePhotoUsecase(getIt()),
  );

  getIt.registerSingleton<GetAvailableScootersUsecase>(
    GetAvailableScootersUsecase(getIt()),
  );

  getIt.registerSingleton<GetNewsByIdUsecase>(
    GetNewsByIdUsecase(getIt<NewsRepository>()),
  );

  getIt.registerSingleton<GetScooterUsecase>(GetScooterUsecase(getIt()));
  getIt.registerSingleton<GetAvailableTariffsUsecase>(
    GetAvailableTariffsUsecase(getIt()),
  );
  getIt.registerSingleton<GetAddressByPointUsecase>(
    GetAddressByPointUsecase(getIt()),
  );
  getIt.registerSingleton<GetPedestrianRoutesUsecase>(
    GetPedestrianRoutesUsecase(getIt()),
  );
  getIt.registerSingleton<GetScooterOrderRouteHistoryUsecase>(
    GetScooterOrderRouteHistoryUsecase(getIt()),
  );
  getIt.registerSingleton<GetAvailableZonesUsecase>(
    GetAvailableZonesUsecase(getIt()),
  );
  getIt.registerSingleton<GetMapSettingsUsecase>(
    GetMapSettingsUsecase(getIt()),
  );
  getIt.registerSingleton<SaveMapSettingsUsecase>(
    SaveMapSettingsUsecase(getIt()),
  );

  getIt.registerSingleton<AddPaymentCardUsecase>(
    AddPaymentCardUsecase(getIt()),
  );
  getIt.registerSingleton<GetPaymentCardsUsecase>(
    GetPaymentCardsUsecase(getIt(), getIt()),
  );
  getIt.registerSingleton<SetMainPaymentCardUsecase>(
    SetMainPaymentCardUsecase(getIt()),
  );
  getIt.registerSingleton<RemovePaymentCardUsecase>(
    RemovePaymentCardUsecase(getIt()),
  );

  getIt.registerSingleton<GetCertificatesUsecase>(
    GetCertificatesUsecase(getIt()),
  );
  getIt.registerSingleton<PurchaseCertificateUsecase>(
    PurchaseCertificateUsecase(getIt()),
  );

  getIt.registerSingleton<GetClientOrdersUsecase>(
    GetClientOrdersUsecase(getIt()),
  );
  getIt.registerSingleton<BookScooterUsecase>(BookScooterUsecase(getIt()));

  getIt.registerSingleton<StartRideUsecase>(StartRideUsecase(getIt()));
  getIt.registerSingleton<CancelRideUsecase>(CancelRideUsecase(getIt()));

  getIt.registerSingleton<UploadScooterPhotosUsecase>(
    UploadScooterPhotosUsecase(getIt()),
  );
  getIt.registerSingleton<UpdateScooterOrderDataUsecase>(
    UpdateScooterOrderDataUsecase(getIt()),
  );
  getIt.registerSingleton<PayScooterOrderWithPhotosUsecase>(
    PayScooterOrderWithPhotosUsecase(getIt()),
  );
  getIt.registerSingleton<GetScooterOrderByIdUsecase>(
    GetScooterOrderByIdUsecase(getIt()),
  );

  getIt.registerSingleton<FinishRideUsecase>(FinishRideUsecase(getIt()));
  getIt.registerSingleton<PauseRideUsecase>(PauseRideUsecase(getIt()));
  getIt.registerSingleton<ResumeRideUsecase>(ResumeRideUsecase(getIt()));
  getIt.registerSingleton<PayRideUsecase>(PayRideUsecase(getIt()));
  getIt.registerSingleton<GetAvailableSubscriptionsUsecase>(
    GetAvailableSubscriptionsUsecase(getIt()),
  );
  getIt.registerSingleton<GetSubscriptionByIdUsecase>(
    GetSubscriptionByIdUsecase(getIt()),
  );
  getIt.registerSingleton<ActivateSubscriptionUsecase>(
    ActivateSubscriptionUsecase(getIt()),
  );
  getIt.registerSingleton<GetClientSubscriptionsUsecase>(
    GetClientSubscriptionsUsecase(getIt()),
  );
  getIt.registerSingleton<GetScooterByTitleUsecase>(
    GetScooterByTitleUsecase(getIt()),
  );
  getIt.registerSingleton<GetNotificationsUsecase>(
    GetNotificationsUsecase(getIt<NotificationRepository>()),
  );
  getIt.registerFactory<NotificationsBloc>(
        () => NotificationsBloc(getIt<GetNotificationsUsecase>()),
  );


  // Blocs
  getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));

  getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));

  getIt.registerFactory<VerifyCodeBloc>(() => VerifyCodeBloc(getIt()));

  getIt.registerFactory<ProfileBloc>(() => ProfileBloc(getIt(), getIt(), getIt()));

  getIt.registerFactory<EditProfileBloc>(
        () => EditProfileBloc(getIt(), getIt()),
  );

  getIt.registerFactory<MapBloc>(
        () => MapBloc(
      getIt(),
      getIt(),
      getIt(),
      getIt(),
      getIt(),
      getIt(),
      getIt(),
      getIt(),
      getIt(),
    ),
  );

  getIt.registerFactory<ScooterDetailBloc>(() => ScooterDetailBloc(getIt()));

  getIt.registerFactory<MapSettingsModalBloc>(
        () => MapSettingsModalBloc(getIt(), getIt()),
  );

  getIt.registerFactory<AddCardBloc>(() => AddCardBloc(getIt()));


  getIt.registerFactory<PaymentMethodSheetBloc>(
        () => PaymentMethodSheetBloc(getIt()),
  );

  getIt.registerFactory<CurrentRidesBloc>(() => CurrentRidesBloc(getIt()));

  getIt.registerFactory<ActiveRideBloc>(
        () => ActiveRideBloc(getIt(), getIt(), getIt(), getIt(), getIt()),
  );

  getIt.registerFactory<ReservedRideBloc>(
        () => ReservedRideBloc(getIt(), getIt()),
  );

  getIt.registerFactory<NewsBloc>(() => NewsBloc(getIt<NewsRepository>()));


  getIt.registerFactory<SendPhotoBloc>(() => SendPhotoBloc(getIt(), getIt()));

  getIt.registerFactory<SubscriptionListBloc>(
        () => SubscriptionListBloc(
      getAvailableSubscriptionsUsecase: getIt(),
      getClientSubscriptionsUsecase: getIt(),
    ),
  );

  // UseCase
  getIt.registerSingleton<GetScooterOrderHistoryUsecase>(
    GetScooterOrderHistoryUsecase(getIt<ScooterRepository>()),
  );

  getIt.registerSingleton<CheckUserUseCase>(
    CheckUserUseCase(getIt<UserProfileRepository>()),
  );

  getIt.registerSingleton<GetNotificationsStreamUseCase>(
    GetNotificationsStreamUseCase(getIt<NotificationRepository>()),
  );

  getIt.registerSingleton<CancelNotificationUseCase>(
    CancelNotificationUseCase(getIt<NotificationRepository>()),
  );

  // Bloc
  getIt.registerFactory<OrderHistoryBloc>(
        () => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()),
  );

  getIt.registerFactory<ScooterCodeBloc>(
        () => ScooterCodeBloc(getScooterByTitleUsecase: getIt<GetScooterByTitleUsecase>()),
  );


  // Repository
  getIt.registerSingleton<PromoCodeRepository>(
    PromoCodeRepositoryImpl(getIt<ApiService>()),
  );

// UseCase
  getIt.registerSingleton<ApplyPromoCodeUsecase>(
    ApplyPromoCodeUsecase(getIt<PromoCodeRepository>()),
  );

// Bloc (factory, т.к. экран создаёт новый экземпляр)
  getIt.registerFactory<PromoCodeBloc>(
        () => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
  );
}
