import { Provider } from '@nestjs/common';
import { PaymentsService } from './PaymentsService';

// Import core interfaces
import type { IPaymentRepository } from '@core/payments/domain/repositories/IPaymentRepository';
import type { IMembershipFeeRepository, IMemberPaymentRepository } from '@core/payments/domain/repositories/IMembershipFeeRepository';
import type { IPrizeRepository } from '@core/payments/domain/repositories/IPrizeRepository';
import type { IWalletRepository, ITransactionRepository } from '@core/payments/domain/repositories/IWalletRepository';
import type { Logger } from '@core/shared/application/Logger';

// Import use cases
import { GetPaymentsUseCase } from '@core/payments/application/use-cases/GetPaymentsUseCase';
import { CreatePaymentUseCase } from '@core/payments/application/use-cases/CreatePaymentUseCase';
import { UpdatePaymentStatusUseCase } from '@core/payments/application/use-cases/UpdatePaymentStatusUseCase';
import { GetMembershipFeesUseCase } from '@core/payments/application/use-cases/GetMembershipFeesUseCase';
import { UpsertMembershipFeeUseCase } from '@core/payments/application/use-cases/UpsertMembershipFeeUseCase';
import { UpdateMemberPaymentUseCase } from '@core/payments/application/use-cases/UpdateMemberPaymentUseCase';
import { GetPrizesUseCase } from '@core/payments/application/use-cases/GetPrizesUseCase';
import { CreatePrizeUseCase } from '@core/payments/application/use-cases/CreatePrizeUseCase';
import { AwardPrizeUseCase } from '@core/payments/application/use-cases/AwardPrizeUseCase';
import { DeletePrizeUseCase } from '@core/payments/application/use-cases/DeletePrizeUseCase';
import { GetWalletUseCase } from '@core/payments/application/use-cases/GetWalletUseCase';
import { ProcessWalletTransactionUseCase } from '@core/payments/application/use-cases/ProcessWalletTransactionUseCase';

// Import concrete in-memory implementations
import { InMemoryPaymentRepository } from '/payments/persistence/inmemory/InMemoryPaymentRepository';
import { InMemoryMembershipFeeRepository, InMemoryMemberPaymentRepository } from '/payments/persistence/inmemory/InMemoryMembershipFeeRepository';
import { InMemoryPrizeRepository } from '/payments/persistence/inmemory/InMemoryPrizeRepository';
import { InMemoryWalletRepository, InMemoryTransactionRepository } from '/payments/persistence/inmemory/InMemoryWalletRepository';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';

// Repository injection tokens
export const PAYMENT_REPOSITORY_TOKEN = 'IPaymentRepository';
export const MEMBERSHIP_FEE_REPOSITORY_TOKEN = 'IMembershipFeeRepository';
export const MEMBER_PAYMENT_REPOSITORY_TOKEN = 'IMemberPaymentRepository';
export const PRIZE_REPOSITORY_TOKEN = 'IPrizeRepository';
export const WALLET_REPOSITORY_TOKEN = 'IWalletRepository';
export const TRANSACTION_REPOSITORY_TOKEN = 'ITransactionRepository';
export const LOGGER_TOKEN = 'Logger';

// Use case injection tokens
export const GET_PAYMENTS_USE_CASE_TOKEN = 'GetPaymentsUseCase';
export const CREATE_PAYMENT_USE_CASE_TOKEN = 'CreatePaymentUseCase';
export const UPDATE_PAYMENT_STATUS_USE_CASE_TOKEN = 'UpdatePaymentStatusUseCase';
export const GET_MEMBERSHIP_FEES_USE_CASE_TOKEN = 'GetMembershipFeesUseCase';
export const UPSERT_MEMBERSHIP_FEE_USE_CASE_TOKEN = 'UpsertMembershipFeeUseCase';
export const UPDATE_MEMBER_PAYMENT_USE_CASE_TOKEN = 'UpdateMemberPaymentUseCase';
export const GET_PRIZES_USE_CASE_TOKEN = 'GetPrizesUseCase';
export const CREATE_PRIZE_USE_CASE_TOKEN = 'CreatePrizeUseCase';
export const AWARD_PRIZE_USE_CASE_TOKEN = 'AwardPrizeUseCase';
export const DELETE_PRIZE_USE_CASE_TOKEN = 'DeletePrizeUseCase';
export const GET_WALLET_USE_CASE_TOKEN = 'GetWalletUseCase';
export const PROCESS_WALLET_TRANSACTION_USE_CASE_TOKEN = 'ProcessWalletTransactionUseCase';

export const PaymentsProviders: Provider[] = [
  PaymentsService,

  // Logger
  {
    provide: LOGGER_TOKEN,
    useClass: ConsoleLogger,
  },

  // Repositories (repositories are injected into use cases, NOT into services)
  {
    provide: PAYMENT_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryPaymentRepository(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: MEMBERSHIP_FEE_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryMembershipFeeRepository(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: MEMBER_PAYMENT_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryMemberPaymentRepository(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: PRIZE_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryPrizeRepository(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: WALLET_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryWalletRepository(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: TRANSACTION_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryTransactionRepository(logger),
    inject: [LOGGER_TOKEN],
  },

  // Use cases (use cases receive repositories, services receive use cases)
  {
    provide: GET_PAYMENTS_USE_CASE_TOKEN,
    useFactory: (paymentRepo: IPaymentRepository) => new GetPaymentsUseCase(paymentRepo),
    inject: [PAYMENT_REPOSITORY_TOKEN],
  },
  {
    provide: CREATE_PAYMENT_USE_CASE_TOKEN,
    useFactory: (paymentRepo: IPaymentRepository) => new CreatePaymentUseCase(paymentRepo),
    inject: [PAYMENT_REPOSITORY_TOKEN],
  },
  {
    provide: UPDATE_PAYMENT_STATUS_USE_CASE_TOKEN,
    useFactory: (paymentRepo: IPaymentRepository) => new UpdatePaymentStatusUseCase(paymentRepo),
    inject: [PAYMENT_REPOSITORY_TOKEN],
  },
  {
    provide: GET_MEMBERSHIP_FEES_USE_CASE_TOKEN,
    useFactory: (membershipFeeRepo: IMembershipFeeRepository, memberPaymentRepo: IMemberPaymentRepository) =>
      new GetMembershipFeesUseCase(membershipFeeRepo, memberPaymentRepo),
    inject: [MEMBERSHIP_FEE_REPOSITORY_TOKEN, MEMBER_PAYMENT_REPOSITORY_TOKEN],
  },
  {
    provide: UPSERT_MEMBERSHIP_FEE_USE_CASE_TOKEN,
    useFactory: (membershipFeeRepo: IMembershipFeeRepository) => new UpsertMembershipFeeUseCase(membershipFeeRepo),
    inject: [MEMBERSHIP_FEE_REPOSITORY_TOKEN],
  },
  {
    provide: UPDATE_MEMBER_PAYMENT_USE_CASE_TOKEN,
    useFactory: (membershipFeeRepo: IMembershipFeeRepository, memberPaymentRepo: IMemberPaymentRepository) =>
      new UpdateMemberPaymentUseCase(membershipFeeRepo, memberPaymentRepo),
    inject: [MEMBERSHIP_FEE_REPOSITORY_TOKEN, MEMBER_PAYMENT_REPOSITORY_TOKEN],
  },
  {
    provide: GET_PRIZES_USE_CASE_TOKEN,
    useFactory: (prizeRepo: IPrizeRepository) => new GetPrizesUseCase(prizeRepo),
    inject: [PRIZE_REPOSITORY_TOKEN],
  },
  {
    provide: CREATE_PRIZE_USE_CASE_TOKEN,
    useFactory: (prizeRepo: IPrizeRepository) => new CreatePrizeUseCase(prizeRepo),
    inject: [PRIZE_REPOSITORY_TOKEN],
  },
  {
    provide: AWARD_PRIZE_USE_CASE_TOKEN,
    useFactory: (prizeRepo: IPrizeRepository) => new AwardPrizeUseCase(prizeRepo),
    inject: [PRIZE_REPOSITORY_TOKEN],
  },
  {
    provide: DELETE_PRIZE_USE_CASE_TOKEN,
    useFactory: (prizeRepo: IPrizeRepository) => new DeletePrizeUseCase(prizeRepo),
    inject: [PRIZE_REPOSITORY_TOKEN],
  },
  {
    provide: GET_WALLET_USE_CASE_TOKEN,
    useFactory: (walletRepo: IWalletRepository, transactionRepo: ITransactionRepository) =>
      new GetWalletUseCase(walletRepo, transactionRepo),
    inject: [WALLET_REPOSITORY_TOKEN, TRANSACTION_REPOSITORY_TOKEN],
  },
  {
    provide: PROCESS_WALLET_TRANSACTION_USE_CASE_TOKEN,
    useFactory: (walletRepo: IWalletRepository, transactionRepo: ITransactionRepository) =>
      new ProcessWalletTransactionUseCase(walletRepo, transactionRepo),
    inject: [WALLET_REPOSITORY_TOKEN, TRANSACTION_REPOSITORY_TOKEN],
  },
];
