import 'package:coda_project/data/datasources/attendance_remote_data_source.dart';
import 'package:coda_project/data/repositories/attendance_repository_impl.dart';
import 'package:coda_project/domain/repositories/attendance_repository.dart';
import 'package:coda_project/domain/usecases/get_attendance_records_usecase.dart';
import 'package:coda_project/presentation/bloc/finance_bloc.dart';
import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../network/api_client.dart';
import '../../data/datasources/auth_remote_data_source.dart';
import '../../data/datasources/user_local_data_source.dart';
import '../../data/datasources/vacation_remote_data_source.dart';
import '../../data/datasources/advance_remote_data_source.dart';
import '../../data/repositories/auth_repository_impl.dart';
import '../../data/repositories/vacation_repository_impl.dart';
import '../../data/repositories/advance_repository_impl.dart';
import '../../domain/repositories/auth_repository.dart';
import '../../domain/repositories/vacation_repository.dart';
import '../../domain/repositories/advance_repository.dart';
import '../../domain/usecases/login_usecase.dart';
import '../../domain/usecases/attendance_login_usecase.dart';
import '../../domain/usecases/attendance_logout_usecase.dart';
import '../../domain/usecases/create_vacation_usecase.dart';
import '../../domain/usecases/get_vacation_types_usecase.dart';
import '../../domain/usecases/get_vacations_usecase.dart';
import '../../domain/usecases/create_advance_usecase.dart';
import '../../domain/usecases/get_advances_usecase.dart';
import '../../domain/usecases/get_extra_hours_usecase.dart';
import '../../domain/usecases/get_rewards_usecase.dart';
import '../../domain/usecases/get_punishments_usecase.dart';
import '../../domain/usecases/get_salary_summary_usecase.dart';
import '../../domain/usecases/change_password_usecase.dart';
import '../../presentation/blocs/login/login_bloc.dart';
import '../../presentation/blocs/change_password/change_password_bloc.dart';

final sl = GetIt.instance;

Future<void> initializeDependencies() async {
  // External
  sl.registerLazySingleton<Dio>(() => Dio());

  // SharedPreferences
  final sharedPreferences = await SharedPreferences.getInstance();
  sl.registerLazySingleton<SharedPreferences>(() => sharedPreferences);

  // Core
  sl.registerLazySingleton<ApiClient>(
    () => ApiClient(dio: sl(), sharedPreferences: sl()),
  );

  // Data sources
  sl.registerLazySingleton<AuthRemoteDataSource>(
    () => AuthRemoteDataSourceImpl(apiClient: sl()),
  );

  sl.registerLazySingleton<UserLocalDataSource>(
    () => UserLocalDataSourceImpl(sharedPreferences: sl()),
  );

  // Repositories
  sl.registerLazySingleton<AuthRepository>(
    () => AuthRepositoryImpl(remoteDataSource: sl(), localDataSource: sl()),
  );

  // Use cases
  sl.registerLazySingleton(() => LoginUseCase(repository: sl()));
  sl.registerLazySingleton(() => ChangePasswordUseCase(repository: sl()));

  // Blocs
  sl.registerFactory(() => LoginBloc(loginUseCase: sl()));
  sl.registerFactory(() => ChangePasswordBloc(changePasswordUseCase: sl()));

  //Attendence
  sl.registerLazySingleton<AttendanceRemoteDataSource>(
    () => AttendanceRemoteDataSourceImpl(apiClient: sl()),
  );

  sl.registerLazySingleton<AttendanceRepository>(
    () => AttendanceRepositoryImpl(remoteDataSource: sl()),
  );

  sl.registerLazySingleton(() => AttendanceLoginUsecase(repository: sl()));

  sl.registerLazySingleton(() => AttendanceLogoutUseCase(repository: sl()));

  sl.registerLazySingleton(() => GetAttendanceRecordsUseCase(sl()));
  sl.registerLazySingleton(() => GetExtraHoursUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetRewardsUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetPunishmentsUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetSalarySummaryUseCase(sl()));

  // Finance
  sl.registerFactory(
    () => FinanceBloc(
      getAttendanceRecordsUseCase: sl(),
      getExtraHoursUseCase: sl(),
      getRewardsUseCase: sl(),
      getPunishmentsUseCase: sl(),
      getSalarySummaryUseCase: sl(),
    ),
  );

  // Vacation
  sl.registerLazySingleton<VacationRemoteDataSource>(
    () => VacationRemoteDataSourceImpl(apiClient: sl()),
  );

  sl.registerLazySingleton<VacationRepository>(
    () => VacationRepositoryImpl(remoteDataSource: sl()),
  );

  sl.registerLazySingleton(() => CreateVacationUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetVacationTypesUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetVacationsUseCase(repository: sl()));

  // Advance
  sl.registerLazySingleton<AdvanceRemoteDataSource>(
    () => AdvanceRemoteDataSourceImpl(apiClient: sl()),
  );

  sl.registerLazySingleton<AdvanceRepository>(
    () => AdvanceRepositoryImpl(remoteDataSource: sl()),
  );

  sl.registerLazySingleton(() => CreateAdvanceUseCase(repository: sl()));
  sl.registerLazySingleton(() => GetAdvancesUseCase(repository: sl()));
}
