import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/features/active_prescriptions/active_prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_repo.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_repo.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/common/common_repo.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_repo.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
import 'package:hmg_patient_app_new/features/doctor_filter/doctor_filter_view_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_repo.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/health_trackers/health_trackers_repo.dart';
import 'package:hmg_patient_app_new/features/health_trackers/health_trackers_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_repo.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_repo.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/location/location_repo.dart';
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/monthly_report/monthly_report_repo.dart';
import 'package:hmg_patient_app_new/features/monthly_report/monthly_report_view_model.dart';
import 'package:hmg_patient_app_new/features/monthly_reports/monthly_reports_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_repo.dart';
import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_view_model.dart';
import 'package:hmg_patient_app_new/features/notifications/notifications_repo.dart';
import 'package:hmg_patient_app_new/features/notifications/notifications_view_model.dart';
import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_repo.dart';
import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/paytabs/paytabs_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_picture/profile_picture_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/features/refund_request/refund_request_repo.dart';
import 'package:hmg_patient_app_new/features/refund_request/refund_request_view_model.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_repo.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_view_model.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_repo.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_repo.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_repo.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_view_model.dart';
import 'package:hmg_patient_app_new/features/weather/weather_repo.dart';
import 'package:hmg_patient_app_new/features/weather/weather_view_model.dart';
import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart';
import 'package:hmg_patient_app_new/services/app_lifecycle_service.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/clarity_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/firebase_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/services/notification_service.dart';
import 'package:hmg_patient_app_new/services/permission_service.dart';
import 'package:hmg_patient_app_new/core/services/turnstile_service.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart';
import 'package:local_auth/local_auth.dart';
import 'package:logger/web.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../features/active_prescriptions/active_prescriptions_repo.dart';
import '../features/monthly_reports/terms_conditions_repo.dart';
import '../features/monthly_reports/terms_conditions_view_model.dart';
import '../features/qr_parking/qr_parking_view_model.dart';
import '../presentation/health_calculators_and_converts/health_calculator_view_model.dart';

GetIt getIt = GetIt.instance;

class AppDependencies {
  static Future<void> addDependencies() async {
    Logger logger = Logger(
      printer: PrettyPrinter(
        methodCount: 2,
        errorMethodCount: 5,
        lineLength: 1000,
        colors: true,
        printEmojis: true,
      ),
    );

    // Core Services
    getIt.registerLazySingleton<LoggerService>(() => LoggerServiceImp(logger: logger));
    getIt.registerLazySingleton<FirebaseService>(() => FirebaseServiceImpl(
          loggerService: getIt(),
          appState: getIt(),
          firebaseMessaging: FirebaseMessaging.instance,
        ));

    getIt.registerLazySingleton<NavigationService>(() => NavigationService());
    getIt.registerLazySingleton<LocalAuthentication>(() => LocalAuthentication());

    getIt.registerLazySingleton<GAnalytics>(() => GAnalytics());

    // Register CacheService before AppState so it can be injected
    final sharedPreferences = await SharedPreferences.getInstance();
    getIt.registerLazySingleton<CacheService>(() => CacheServiceImp(sharedPreferences: sharedPreferences, loggerService: getIt()));

    getIt.registerLazySingleton<AppState>(() => AppState(navigationService: getIt(), cacheService: getIt()));
    getIt.registerLazySingleton<LocationUtils>(() => LocationUtils(
          isShowConfirmDialog: false,
          navigationService: getIt(),
          appState: getIt(),
        ));
    getIt.registerLazySingleton<DialogService>(() => DialogServiceImp(navigationService: getIt<NavigationService>()));
    getIt.registerLazySingleton<ErrorHandlerService>(() => ErrorHandlerServiceImp(
          dialogService: getIt(),
          loggerService: getIt(),
          navigationService: getIt(),
        ));

    final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    getIt.registerLazySingleton<NotificationService>(() => NotificationServiceImp(
          flutterLocalNotificationsPlugin: flutterLocalNotificationsPlugin,
          loggerService: getIt(),
        ));

    // App Lifecycle Service - must be registered before ApiClient
    getIt.registerLazySingleton<AppLifecycleService>(() => AppLifecycleService());

    getIt.registerLazySingleton<ApiClient>(() => ApiClientImp(appState: getIt()));
    getIt.registerLazySingleton<LocalAuthService>(
      () => LocalAuthService(loggerService: getIt<LoggerService>(), localAuth: getIt<LocalAuthentication>()),
    );

    getIt.registerLazySingleton<PermissionService>(() => PermissionService());
    getIt.registerLazySingleton<TurnstileService>(() => TurnstileService(getIt<LoggerService>()));

    // Repositories
    getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt()));
    getIt.registerLazySingleton<AuthenticationRepo>(() => AuthenticationRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<BookAppointmentsRepo>(() => BookAppointmentsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<MyAppointmentsRepo>(() => MyAppointmentsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<LabRepo>(() => LabRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<RadiologyRepo>(() => RadiologyRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<PrescriptionsRepo>(() => PrescriptionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<InsuranceRepo>(() => InsuranceRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<PayfortRepo>(() => PayfortRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<HabibWalletRepo>(() => HabibWalletRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<MedicalFileRepo>(() => MedicalFileRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<ImmediateLiveCareRepo>(() => ImmediateLiveCareRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<EmergencyServicesRepo>(() => EmergencyServicesRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<TodoSectionRepo>(() => TodoSectionRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<LocationRepo>(() => LocationRepoImpl(apiClient: getIt()));
    getIt.registerLazySingleton<ContactUsRepo>(() => ContactUsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<HmgServicesRepo>(() => HmgServicesRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<SymptomsCheckerRepo>(() => SymptomsCheckerRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<BloodDonationRepo>(() => BloodDonationRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<WaterMonitorRepo>(() => WaterMonitorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<WeatherRepo>(() => WeatherRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<MyInvoicesRepo>(() => MyInvoicesRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<HealthTrackersRepo>(() => HealthTrackersRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<MonthlyReportRepo>(() => MonthlyReportRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<ActivePrescriptionsRepo>(() => ActivePrescriptionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<TermsConditionsRepo>(() => TermsConditionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerFactory<TermsConditionsViewModel>(() => TermsConditionsViewModel(termsConditionsRepo: getIt(), errorHandlerService: getIt()));
    getIt.registerLazySingleton<MonthlyReportsRepo>(() => MonthlyReportsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<QrParkingRepo>(() => QrParkingRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<NotificationsRepo>(() => NotificationsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<AskDoctorRepo>(() => AskDoctorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<ServicesPriceListRepo>(() => ServicesPriceListRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<ProfileSettingsRepo>(() => ProfileSettingsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
    getIt.registerLazySingleton<RefundRequestRepo>(() => RefundRequestRepoImp(apiClient: getIt(), loggerService: getIt()));
    getIt.registerLazySingleton<OffersAndDiscountsRepo>(() => OffersAndDiscountsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));

    // ViewModels
    // Global/shared VMs → LazySingleton

    getIt.registerLazySingleton<LabViewModel>(() => LabViewModel(labRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt()));

    getIt.registerLazySingleton<RadiologyViewModel>(
      () => RadiologyViewModel(radiologyRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt()),
    );

    getIt.registerLazySingleton<PrescriptionsViewModel>(
        () => PrescriptionsViewModel(prescriptionsRepo: getIt(), errorHandlerService: getIt(), navServices: getIt()));

    getIt.registerLazySingleton<InsuranceViewModel>(() => InsuranceViewModel(insuranceRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<MyAppointmentsViewModel>(
        () => MyAppointmentsViewModel(myAppointmentsRepo: getIt(), errorHandlerService: getIt(), appState: getIt()));

    getIt.registerLazySingleton<AppointmentRatingViewModel>(
        () => AppointmentRatingViewModel(myAppointmentsRepo: getIt(), errorHandlerService: getIt(), appState: getIt()));

    getIt.registerLazySingleton<PayfortViewModel>(
      () => PayfortViewModel(payfortRepo: getIt(), errorHandlerService: getIt()),
    );

    getIt.registerLazySingleton<HabibWalletViewModel>(
      () => HabibWalletViewModel(habibWalletRepo: getIt(), errorHandlerService: getIt(), refundRequestRepo: getIt()),
    );

    getIt.registerLazySingleton<MedicalFileViewModel>(
      () => MedicalFileViewModel(
        medicalFileRepo: getIt(),
        errorHandlerService: getIt(),
      ),
    );

    getIt.registerLazySingleton<BookAppointmentsViewModel>(
      () => BookAppointmentsViewModel(
          bookAppointmentsRepo: getIt(),
          errorHandlerService: getIt(),
          navigationService: getIt(),
          myAppointmentsViewModel: getIt(),
          locationUtils: getIt(),
          dialogService: getIt()),
    );

    getIt.registerLazySingleton<ImmediateLiveCareViewModel>(
      () => ImmediateLiveCareViewModel(
        immediateLiveCareRepo: getIt(),
        errorHandlerService: getIt(),
        navigationService: getIt(),
        myAppointmentsViewModel: getIt(),
      ),
    );

    getIt.registerLazySingleton<AuthenticationViewModel>(
      () => AuthenticationViewModel(
          authenticationRepo: getIt(),
          cacheService: getIt(),
          navigationService: getIt(),
          dialogService: getIt(),
          appState: getIt(),
          errorHandlerService: getIt(),
          localAuthService: getIt(),
          turnstileService: getIt()),
    );

    getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel(
          cacheService: getIt<CacheService>(),
          profileSettingsRepo: getIt<ProfileSettingsRepo>(),
          errorHandlerService: getIt<ErrorHandlerService>(),
        ));

    getIt.registerLazySingleton<ProfilePictureViewModel>(() => ProfilePictureViewModel(
          appState: getIt<AppState>(),
          profileSettingsViewModel: getIt<ProfileSettingsViewModel>(),
        ));

    getIt.registerLazySingleton<DateRangeSelectorRangeViewModel>(() => DateRangeSelectorRangeViewModel());

    getIt.registerLazySingleton<DoctorFilterViewModel>(() => DoctorFilterViewModel());

    getIt.registerLazySingleton<AppointmentViaRegionViewmodel>(
      () => AppointmentViaRegionViewmodel(navigationService: getIt(), appState: getIt()),
    );

    getIt.registerLazySingleton<EmergencyServicesViewModel>(
      () => EmergencyServicesViewModel(
        locationUtils: getIt(),
        navServices: getIt(),
        emergencyServicesRepo: getIt(),
        appState: getIt(),
        errorHandlerService: getIt(),
        appointmentRepo: getIt(),
        dialogService: getIt(),
      ),
    );

    getIt.registerLazySingleton<LocationViewModel>(
      () => LocationViewModel(locationRepo: getIt(), errorHandlerService: getIt()),
    );

    getIt.registerLazySingleton<ContactUsViewModel>(
      () => ContactUsViewModel(contactUsRepo: getIt(), appState: getIt(), errorHandlerService: getIt()),
    );

    getIt.registerLazySingleton<HealthCalcualtorViewModel>(() => HealthCalcualtorViewModel());

    getIt.registerLazySingleton<TodoSectionViewModel>(() => TodoSectionViewModel(todoSectionRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<SymptomsCheckerViewModel>(
      () => SymptomsCheckerViewModel(
        errorHandlerService: getIt(),
        symptomsCheckerRepo: getIt(),
        appState: getIt(),
      ),
    );

    getIt.registerLazySingleton<HmgServicesViewModel>(
      () => HmgServicesViewModel(
        bookAppointmentsRepo: getIt(),
        hmgServicesRepo: getIt(),
        errorHandlerService: getIt(),
        navigationService: getIt(),
      ),
    );

    getIt.registerLazySingleton<BloodDonationViewModel>(
      () => BloodDonationViewModel(
        bloodDonationRepo: getIt(),
        errorHandlerService: getIt(),
        navigationService: getIt(),
        dialogService: getIt(),
        appState: getIt(),
        navServices: getIt(),
      ),
    );

    getIt.registerLazySingleton<HealthProvider>(() => HealthProvider());

    getIt.registerLazySingleton<WaterMonitorViewModel>(() => WaterMonitorViewModel(waterMonitorRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<WeatherMonitorViewModel>(
        () => WeatherMonitorViewModel(weatherRepo: getIt(), errorHandlerService: getIt(), locationUtils: getIt()));

    //commenting this because its already define there was on run time error because of this.
    getIt.registerLazySingleton<MyInvoicesViewModel>(
        () => MyInvoicesViewModel(myInvoicesRepo: getIt(), errorHandlerService: getIt(), navServices: getIt()));

    getIt.registerLazySingleton<MonthlyReportViewModel>(() => MonthlyReportViewModel(errorHandlerService: getIt(), monthlyReportRepo: getIt()));

    getIt.registerLazySingleton<NotificationsViewModel>(() => NotificationsViewModel(notificationsRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<HealthTrackersViewModel>(() => HealthTrackersViewModel(healthTrackersRepo: getIt(), errorHandlerService: getIt()));
    getIt.registerLazySingleton<ActivePrescriptionsViewModel>(
        () => ActivePrescriptionsViewModel(errorHandlerService: getIt(), activePrescriptionsRepo: getIt()));
    getIt.registerFactory<QrParkingViewModel>(() => QrParkingViewModel(
        qrParkingRepo: getIt<QrParkingRepo>(), errorHandlerService: getIt<ErrorHandlerService>(), cacheService: getIt<CacheService>()));

    getIt.registerLazySingleton<AskDoctorViewModel>(() => AskDoctorViewModel(askDoctorRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<ServicesPriceListViewModel>(
        () => ServicesPriceListViewModel(servicesPriceListRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<OffersAndDiscountsViewModel>(
        () => OffersAndDiscountsViewModel(offersAndDiscountsRepo: getIt(), errorHandlerService: getIt()));

    getIt.registerLazySingleton<DateRangCalenderModel>(
        () => DateRangCalenderModel(appState: getIt(), navigationService: getIt(), dialogService: getIt()));
    getIt.registerLazySingleton<RefundRequestViewModel>(() => RefundRequestViewModel(
          appState: getIt(),
          refundRequestRepo: getIt(),
          errorHandlerService: getIt(),
        ));

    getIt.registerLazySingleton<PayTabsViewModel>(() => PayTabsViewModel(
          appState: getIt(),
          payfortRepo: getIt(),
          errorHandlerService: getIt(),
        ));

    getIt.registerLazySingleton<ClarityService>(
      () => ClarityService(appState: getIt.get<AppState>()),
    );
  }
}
