import 'dotenv/config';
import 'reflect-metadata';
import { initializeDatabase } from '../infrastructure/persistence/data-source';
import { redisClient } from '../infrastructure/cache/redis-client';
import { createRepositories } from '../main/factories/repositories.factory';
import { createServices } from '../main/factories/services.factory';
import { Network } from '../domain/entities/network';

const NETWORKS_LIST_CACHE_KEY = 'networks:list';

const run = async (): Promise<void> => {
  await initializeDatabase();

  const repositories = createRepositories();
  const services = createServices(redisClient);
  const { logger, coinMarketCapClient, cacheService } = services;

  logger.info('Starting network market-cap seeding');

  const networks = await repositories.networkRepository.findAll();
  const marketCaps = await coinMarketCapClient.getNetworkMarketCapsByName(
    networks.map((network) => ({ name: network.name, symbol: network.code })),
  );

  let updated = 0;
  let skipped = 0;
  let failed = 0;

  for (const network of networks) {
    const mcap = marketCaps.get(network.name) ?? null;

    if (mcap == null) {
      logger.warn('No market cap found for network, skipping', {
        id: network.id,
        name: network.name,
        symbol: network.code,
      });
      skipped++;
      continue;
    }

    if (network.mcap === mcap) {
      skipped++;
      continue;
    }

    try {
      const updatedNetwork = new Network(
        network.id,
        network.name,
        network.code,
        network.addressType,
        network.thumbnail,
        network.explorer,
        network.chainId,
        network.status,
        mcap,
        network.createdAt,
        new Date(),
      );
      await repositories.networkRepository.update(updatedNetwork);
      logger.info('Updated network market cap', {
        id: network.id,
        name: network.name,
        symbol: network.code,
        mcap,
      });
      updated++;
    } catch (error) {
      logger.error('Failed to update network market cap', {
        id: network.id,
        name: network.name,
        symbol: network.code,
        error,
      });
      failed++;
    }
  }

  await cacheService.delete(NETWORKS_LIST_CACHE_KEY);

  logger.info('Network market-cap seeding complete', {
    total: networks.length,
    updated,
    skipped,
    failed,
  });

  await redisClient.quit();
  process.exit(failed > 0 ? 1 : 0);
};

run().catch((error) => {
  // eslint-disable-next-line no-console
  console.error('Network market-cap seeding failed', error);
  process.exit(1);
});
