import path from 'path';
import { Redis } from 'ioredis';
import { PinoLogger } from '../../infrastructure/logging/pino-logger';
import { RedisCacheService } from '../../infrastructure/cache/redis-cache-service';
import { AesGcmEncryptionService } from '../../infrastructure/security/aes-gcm-encryption-service';
import { CoinMarketCapClient } from '../../infrastructure/external/coinmarketcap-client';
import { DeterministicAddressGenerator } from '../../infrastructure/external/deterministic-address-generator';
import { ExternalApiKeyRotationService } from '../../infrastructure/external/external-api-key-rotation.service';
import { NetworkRpcClient } from '../../infrastructure/external/network-rpc-client';
import { SeedPhraseService } from '../../application/services/seed-phrase.service';
import { WalletBalanceService } from '../../domain/services/wallet-balance.service';
import { ILogger } from '../../application/ports/logger';
import { ICacheService } from '../../application/ports/cache-service';
import { IEncryptionService } from '../../application/ports/encryption-service';
import { IAddressGenerator } from '../../application/ports/address-generator';
import { IImageStorage } from '../../application/ports/image-storage';
import { IThumbnailResolver } from '../../application/ports/thumbnail-resolver';
import { IDomainEventPublisher } from '../../application/ports/domain-event-publisher';
import { INetworkRpcClient } from '../../application/ports/network-rpc-client';
import { InMemoryDomainEventPublisher } from '../../infrastructure/events/in-memory-event-publisher';
import { FileImageStorageService } from '../../infrastructure/storage/file-image-storage.service';
import { CoinMarketCapThumbnailResolver } from '../../infrastructure/external/coinmarketcap-thumbnail-resolver';
import { env } from '../config/env';

export interface Services {
  logger: ILogger;
  cacheService: ICacheService;
  encryptionService: IEncryptionService;
  addressGenerator: IAddressGenerator;
  seedPhraseService: SeedPhraseService;
  balanceService: WalletBalanceService;
  coinMarketCapClient: CoinMarketCapClient;
  networkRpcClient: INetworkRpcClient;
  imageStorage: IImageStorage;
  thumbnailResolver: IThumbnailResolver;
  eventPublisher: IDomainEventPublisher;
}

export const createServices = (redisClient: Redis): Services => {
  const logger = new PinoLogger();
  const cacheService = new RedisCacheService(redisClient);
  const encryptionService = new AesGcmEncryptionService();
  const addressGenerator = new DeterministicAddressGenerator(encryptionService);
  const seedPhraseService = new SeedPhraseService();
  const balanceService = new WalletBalanceService();
  const externalApiKeyRotationService = new ExternalApiKeyRotationService(redisClient, logger);
  const coinMarketCapClient = new CoinMarketCapClient(
    cacheService,
    externalApiKeyRotationService,
    logger,
  );
  const thumbnailResolver = new CoinMarketCapThumbnailResolver(coinMarketCapClient);
  const imageStorage = new FileImageStorageService(
    env.PUBLIC_BASE_URL,
    path.resolve(process.cwd(), env.IMAGES_DIR),
    thumbnailResolver,
  );
  const networkRpcClient = new NetworkRpcClient();
  const eventPublisher = new InMemoryDomainEventPublisher();

  return {
    logger,
    cacheService,
    encryptionService,
    addressGenerator,
    seedPhraseService,
    balanceService,
    coinMarketCapClient,
    networkRpcClient,
    imageStorage,
    thumbnailResolver,
    eventPublisher,
  };
};
