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 { createUseCases } from '../main/factories/use-cases.factory';
import { seedTokensForNetwork } from './seed-tokens.helper';

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

  const repositories = createRepositories();
  const services = createServices(redisClient);
  const useCases = createUseCases(repositories, services);

  const networks = await repositories.networkRepository.findAll();
  services.logger.info('Seeding tokens for all networks', { totalNetworks: networks.length });

  let totalCreated = 0;
  let totalSkipped = 0;
  let totalFetched = 0;

  for (const network of networks) {
    const existingTokens = await repositories.tokenRepository.findByNetworkId(network.id);
    if (existingTokens.length > 0) {
      services.logger.info('Network already has tokens, skipping', {
        network: network.name,
        existingTokens: existingTokens.length,
      });
      totalSkipped += existingTokens.length;
      continue;
    }

    try {
      const result = await seedTokensForNetwork(
        network,
        useCases,
        repositories.tokenRepository,
        services.coinMarketCapClient,
        services.logger,
      );
      totalCreated += result.created;
      totalSkipped += result.skipped;
      totalFetched += result.fetched;
    } catch (error) {
      services.logger.error('Failed to seed tokens for network', { network: network.name, error });
    }
  }

  services.logger.info('Token seeding complete', {
    created: totalCreated,
    skipped: totalSkipped,
    fetched: totalFetched,
  });

  await redisClient.quit();
  process.exit(0);
};

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