// ignore_for_file: public_member_api_docs

import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';

import 'core/network/api_client.dart';
import 'core/network/api_error.dart';
import 'core/network/interceptors/auth_interceptor.dart';
import 'core/services/token_storage.dart';
import 'features/approvals/data/repositories/approval_draft_repository_remote.dart';
import 'features/approvals/data/repositories/approval_repository_remote.dart';
import 'features/approvals/data/repositories/approval_template_repository_remote.dart';
import 'features/approvals/domain/repositories/approval_draft_repository.dart';
import 'features/approvals/domain/repositories/approval_repository.dart';
import 'features/approvals/domain/repositories/approval_template_repository.dart';
import 'features/approvals/domain/usecases/apply_approval_template_use_case.dart';
import 'features/approvals/domain/usecases/approve_approval_use_case.dart';
import 'features/approvals/domain/usecases/delete_approval_draft_use_case.dart';
import 'features/approvals/domain/usecases/get_approval_draft_use_case.dart';
import 'features/approvals/domain/usecases/list_approval_drafts_use_case.dart';
import 'features/approvals/domain/usecases/recall_approval_use_case.dart';
import 'features/approvals/domain/usecases/reject_approval_use_case.dart';
import 'features/approvals/domain/usecases/resubmit_approval_use_case.dart';
import 'features/approvals/domain/usecases/save_approval_draft_use_case.dart';
import 'features/approvals/domain/usecases/save_approval_template_use_case.dart';
import 'features/approvals/domain/usecases/submit_approval_use_case.dart';
import 'features/approvals/history/data/repositories/approval_history_repository_remote.dart';
import 'features/approvals/history/domain/repositories/approval_history_repository.dart';
import 'features/approvals/shared/data/repositories/approval_approver_repository_remote.dart';
import 'features/approvals/shared/domain/repositories/approval_approver_repository.dart';
import 'features/approvals/step/data/repositories/approval_step_repository_remote.dart';
import 'features/approvals/step/domain/repositories/approval_step_repository.dart';
import 'features/auth/application/auth_service.dart';
import 'features/auth/data/repositories/auth_repository_remote.dart';
import 'features/auth/domain/repositories/auth_repository.dart';
import 'features/dashboard/data/repositories/dashboard_repository_remote.dart';
import 'features/dashboard/domain/repositories/dashboard_repository.dart';
import 'features/inventory/lookups/data/repositories/inventory_lookup_repository_remote.dart';
import 'features/inventory/lookups/domain/repositories/inventory_lookup_repository.dart';
import 'features/inventory/summary/application/inventory_service.dart';
import 'features/inventory/summary/data/repositories/inventory_repository_remote.dart';
import 'features/inventory/summary/domain/repositories/inventory_repository.dart';
import 'features/inventory/transactions/data/repositories/stock_transaction_repository_remote.dart';
import 'features/inventory/transactions/data/repositories/transaction_customer_repository_remote.dart';
import 'features/inventory/transactions/data/repositories/transaction_line_repository_remote.dart';
import 'features/inventory/transactions/domain/repositories/stock_transaction_repository.dart';
import 'features/masters/customer/data/repositories/customer_repository_remote.dart';
import 'features/masters/customer/domain/repositories/customer_repository.dart';
import 'features/masters/group/data/repositories/group_repository_remote.dart';
import 'features/masters/group/domain/repositories/group_repository.dart';
import 'features/masters/group_permission/data/repositories/group_permission_repository_remote.dart';
import 'features/masters/group_permission/domain/repositories/group_permission_repository.dart';
import 'features/masters/menu/data/repositories/menu_repository_remote.dart';
import 'features/masters/menu/domain/repositories/menu_repository.dart';
import 'features/masters/product/data/repositories/product_repository_remote.dart';
import 'features/masters/product/domain/repositories/product_repository.dart';
import 'features/masters/uom/data/repositories/uom_repository_remote.dart';
import 'features/masters/uom/domain/repositories/uom_repository.dart';
import 'features/masters/user/data/repositories/user_repository_remote.dart';
import 'features/masters/user/domain/repositories/user_repository.dart';
import 'features/masters/vendor/data/repositories/vendor_repository_remote.dart';
import 'features/masters/vendor/domain/repositories/vendor_repository.dart';
import 'features/masters/warehouse/data/repositories/warehouse_repository_remote.dart';
import 'features/masters/warehouse/domain/repositories/warehouse_repository.dart';
import 'features/reporting/data/repositories/reporting_repository_remote.dart';
import 'features/reporting/domain/repositories/reporting_repository.dart';
import 'features/util/postal_search/data/repositories/postal_search_repository_remote.dart';
import 'features/util/postal_search/domain/repositories/postal_search_repository.dart';

/// 전역 DI 컨테이너
final GetIt sl = GetIt.instance;

/// 의존성 등록(스켈레톤)
/// - Environment.initialize() 이후 호출하여 baseUrl/타임아웃 등을 주입한다.
Future<void> initInjection({
  required String baseUrl,
  Duration? connectTimeout,
  Duration? receiveTimeout,
}) async {
  // Dio 기본 옵션 설정
  final options = BaseOptions(
    baseUrl: baseUrl,
    connectTimeout: connectTimeout ?? const Duration(seconds: 15),
    receiveTimeout: receiveTimeout ?? const Duration(seconds: 30),
    headers: const {'Accept': 'application/json'},
  );

  final dio = Dio(options);

  final tokenStorage = createTokenStorage();
  sl
    ..registerSingleton<TokenStorage>(tokenStorage)
    ..registerLazySingleton<ApiErrorMapper>(ApiErrorMapper.new);

  // 인터셉터 등록 (Auth 등)

  final authInterceptor = AuthInterceptor(
    tokenStorage: tokenStorage,
    dio: dio,
    onRefresh: () {
      if (!sl.isRegistered<AuthService>()) {
        return Future<TokenPair?>.value(null);
      }
      return sl<AuthService>().refreshForInterceptor();
    },
  );
  dio.interceptors.add(authInterceptor);

  // 개발용 로거는 필요 시 추가 (pretty_dio_logger 등)
  // if (!kReleaseMode) { dio.interceptors.add(PrettyDioLogger(...)); }

  sl.registerSingleton<Dio>(dio);

  // ApiClient 등록
  sl.registerLazySingleton<ApiClient>(
    () => ApiClient(dio: sl<Dio>(), errorMapper: sl<ApiErrorMapper>()),
  );

  _registerAuthDependencies();
  _registerDashboardDependencies();
  _registerMasterDependencies();
  _registerApprovalDependencies();
  _registerInventoryDependencies();
  _registerUtilityDependencies();
  _registerReportingDependencies();
}

void _registerAuthDependencies() {
  sl
    ..registerLazySingleton<AuthRepository>(
      () => AuthRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<AuthService>(
      () => AuthService(
        repository: sl<AuthRepository>(),
        tokenStorage: sl<TokenStorage>(),
      ),
    );
}

void _registerDashboardDependencies() {
  sl.registerLazySingleton<DashboardRepository>(
    () => DashboardRepositoryRemote(apiClient: sl<ApiClient>()),
  );
}

void _registerMasterDependencies() {
  sl
    ..registerLazySingleton<VendorRepository>(
      () => VendorRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ProductRepository>(
      () => ProductRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<WarehouseRepository>(
      () => WarehouseRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<UomRepository>(
      () => UomRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<CustomerRepository>(
      () => CustomerRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<GroupRepository>(
      () => GroupRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<UserRepository>(
      () => UserRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<MenuRepository>(
      () => MenuRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<GroupPermissionRepository>(
      () => GroupPermissionRepositoryRemote(apiClient: sl<ApiClient>()),
    );
}

void _registerApprovalDependencies() {
  sl
    ..registerLazySingleton<ApprovalRepository>(
      () => ApprovalRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ApprovalTemplateRepository>(
      () => ApprovalTemplateRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ApprovalStepRepository>(
      () => ApprovalStepRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ApprovalHistoryRepository>(
      () => ApprovalHistoryRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ApprovalDraftRepository>(
      () => ApprovalDraftRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<ApprovalApproverRepository>(
      () => ApprovalApproverRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<SubmitApprovalUseCase>(
      () => SubmitApprovalUseCase(repository: sl<ApprovalRepository>()),
    )
    ..registerLazySingleton<ApproveApprovalUseCase>(
      () => ApproveApprovalUseCase(repository: sl<ApprovalRepository>()),
    )
    ..registerLazySingleton<RejectApprovalUseCase>(
      () => RejectApprovalUseCase(repository: sl<ApprovalRepository>()),
    )
    ..registerLazySingleton<RecallApprovalUseCase>(
      () => RecallApprovalUseCase(repository: sl<ApprovalRepository>()),
    )
    ..registerLazySingleton<ResubmitApprovalUseCase>(
      () => ResubmitApprovalUseCase(repository: sl<ApprovalRepository>()),
    )
    ..registerLazySingleton<SaveApprovalTemplateUseCase>(
      () => SaveApprovalTemplateUseCase(
        repository: sl<ApprovalTemplateRepository>(),
      ),
    )
    ..registerLazySingleton<SaveApprovalDraftUseCase>(
      () => SaveApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
    )
    ..registerLazySingleton<GetApprovalDraftUseCase>(
      () => GetApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
    )
    ..registerLazySingleton<ListApprovalDraftsUseCase>(
      () =>
          ListApprovalDraftsUseCase(repository: sl<ApprovalDraftRepository>()),
    )
    ..registerLazySingleton<DeleteApprovalDraftUseCase>(
      () =>
          DeleteApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
    )
    ..registerLazySingleton<ApplyApprovalTemplateUseCase>(
      () => ApplyApprovalTemplateUseCase(
        templateRepository: sl<ApprovalTemplateRepository>(),
        approvalRepository: sl<ApprovalRepository>(),
      ),
    );
}

void _registerInventoryDependencies() {
  sl
    ..registerLazySingleton<InventoryRepository>(
      () => InventoryRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<InventoryService>(
      () => InventoryService(repository: sl<InventoryRepository>()),
    )
    ..registerLazySingleton<InventoryLookupRepository>(
      () => InventoryLookupRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<StockTransactionRepository>(
      () => StockTransactionRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<TransactionLineRepository>(
      () => TransactionLineRepositoryRemote(apiClient: sl<ApiClient>()),
    )
    ..registerLazySingleton<TransactionCustomerRepository>(
      () => TransactionCustomerRepositoryRemote(apiClient: sl<ApiClient>()),
    );
}

void _registerUtilityDependencies() {
  sl.registerLazySingleton<PostalSearchRepository>(
    () => PostalSearchRepositoryRemote(apiClient: sl<ApiClient>()),
  );
}

void _registerReportingDependencies() {
  sl.registerLazySingleton<ReportingRepository>(
    () => ReportingRepositoryRemote(apiClient: sl<ApiClient>()),
  );
}
