import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/common/dio_error_handler.dart';
import 'package:rasadyar_chicken/data/data_source/local/chicken_local.dart';
import 'package:rasadyar_chicken/data/data_source/local/chicken_local_imp.dart';
import 'package:rasadyar_chicken/data/data_source/remote/auth/auth_remote.dart';
import 'package:rasadyar_chicken/data/data_source/remote/auth/auth_remote_imp.dart';
import 'package:rasadyar_chicken/data/data_source/remote/chicken/chicken_remote.dart';
import 'package:rasadyar_chicken/data/data_source/remote/chicken/chicken_remote_imp.dart';
import 'package:rasadyar_chicken/data/data_source/remote/poultry_science/poultry_science_remote.dart';
import 'package:rasadyar_chicken/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart';
import 'package:rasadyar_chicken/data/repositories/auth/auth_repository.dart';
import 'package:rasadyar_chicken/data/repositories/auth/auth_repository_imp.dart';
import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository.dart';
import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository_imp.dart';
import 'package:rasadyar_chicken/data/repositories/poultry_science/poultry_science_repository.dart';
import 'package:rasadyar_chicken/data/repositories/poultry_science/poultry_science_repository_imp.dart';
import 'package:rasadyar_core/core.dart';

GetIt diChicken = GetIt.asNewInstance();

Future<void> setupChickenDI() async {
  if (diChicken.isRegistered<DioErrorHandler>()) {
    await diChicken.unregister<DioErrorHandler>();
  }
  diChicken.registerSingleton(DioErrorHandler());

  var tokenService = Get.find<TokenStorageService>();
  tokenService.getBaseUrl(Module.chicken);

  diChicken.registerLazySingleton<AppInterceptor>(
    () => AppInterceptor(
      // سامانه مرغ فعلاً رفرش توکن ندارد
      refreshTokenCallback: () async => null,
      saveTokenCallback: (String newToken) async {
        await tokenService.saveAccessToken(Module.chicken, newToken);
      },
      clearTokenCallback: () async {
        await tokenService.deleteModuleTokens(Module.chicken);
        Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken);
      },
    ),
    instanceName: 'chickenInterceptor',
  );

  var baseUrl = tokenService.baseurl.value;

  diChicken.registerLazySingleton<DioRemote>(
    () => DioRemote(
      baseUrl: baseUrl,
      interceptors: diChicken.get<AppInterceptor>(instanceName: 'chickenInterceptor'),
    ),
  );

  final dioRemote = diChicken.get<DioRemote>();
  await dioRemote.init();

  diChicken.registerLazySingleton<AuthRemoteDataSource>(() => AuthRemoteDataSourceImp(dioRemote));

  diChicken.registerLazySingleton<AuthRepository>(
    () => AuthRepositoryImpl(diChicken.get<AuthRemoteDataSource>()),
  );

  diChicken.registerLazySingleton<ChickenRemoteDatasource>(
    () => ChickenRemoteDatasourceImp(diChicken.get<DioRemote>()),
  );

  diChicken.registerLazySingleton<ChickenLocalDataSource>(() => ChickenLocalDataSourceImp());

  diChicken.registerLazySingleton<ChickenRepository>(
    () => ChickenRepositoryImp(
      remote: diChicken.get<ChickenRemoteDatasource>(),
      local: diChicken.get<ChickenLocalDataSource>(),
    ),
  );

  diChicken.registerLazySingleton<PoultryScienceRemoteDatasource>(
    () => PoultryScienceRemoteDatasourceImp(diChicken.get<DioRemote>()),
  );

  diChicken.registerLazySingleton<PoultryScienceRepository>(
    () => PoultryScienceRepositoryImp(diChicken.get<PoultryScienceRemoteDatasource>()),
  );
}

Future<void> newSetupAuthDI(String newUrl) async {
  var tokenService = Get.find<TokenStorageService>();

  // همیشه baseUrl جدید رو ذخیره کن
  await tokenService.saveBaseUrl(Module.chicken, newUrl);

  // Re-register AppInterceptor
  if (diChicken.isRegistered<AppInterceptor>(instanceName: 'chickenInterceptor')) {
    await diChicken.unregister<AppInterceptor>(instanceName: 'chickenInterceptor');
  }
  diChicken.registerLazySingleton<AppInterceptor>(
    () => AppInterceptor(
      refreshTokenCallback: () async => null,
      saveTokenCallback: (String newToken) async {
        //  await tokenService.saveAccessToken(newToken);
      },
      clearTokenCallback: () async {
        await tokenService.deleteModuleTokens(Module.chicken);
        Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken);
      },
    ),
    instanceName: 'chickenInterceptor',
  );

  // Re-register DioRemote
  if (diChicken.isRegistered<DioRemote>()) {
    await diChicken.unregister<DioRemote>();
  }
  diChicken.registerLazySingleton<DioRemote>(
    () => DioRemote(
      baseUrl: newUrl,
      interceptors: diChicken.get<AppInterceptor>(instanceName: 'chickenInterceptor'),
    ),
  );
  final dioRemote = diChicken.get<DioRemote>();
  await dioRemote.init();

  // Re-register dependent layers
  await reRegister<AuthRemoteDataSource>(() => AuthRemoteDataSourceImp(dioRemote));
  await reRegister<AuthRepository>(() => AuthRepositoryImpl(diChicken.get<AuthRemoteDataSource>()));
  await reRegister<ChickenRemoteDatasource>(() => ChickenRemoteDatasourceImp(dioRemote));
  await reRegister<ChickenLocalDataSource>(() => ChickenLocalDataSourceImp());
  await reRegister<ChickenRepository>(
    () => ChickenRepositoryImp(
      remote: diChicken.get<ChickenRemoteDatasource>(),
      local: diChicken.get<ChickenLocalDataSource>(),
    ),
  );

  await reRegister<PoultryScienceRemoteDatasource>(
    () => PoultryScienceRemoteDatasourceImp(dioRemote),
  );
  await reRegister<PoultryScienceRepository>(
    () => PoultryScienceRepositoryImp(diChicken.get<PoultryScienceRemoteDatasource>()),
  );
}

Future<void> reRegister<T extends Object>(T Function() factory) async {
  if (diChicken.isRegistered<T>()) {
    await diChicken.unregister<T>();
  }
  diChicken.registerLazySingleton<T>(factory);
}

Future<void> removeChickenDI() async {
  await diChicken.resetScope();
}
