import type { Logger } from '@core/shared/application';
import type { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
import { SeedRacingData, type RacingSeedDependencies } from '../../../../../adapters/bootstrap/SeedRacingData';
import { Inject, Module, OnModuleInit } from '@nestjs/common';
import { getApiPersistence, getEnableBootstrap, getForceReseed } from '../../env';
import { RacingPersistenceModule } from '../../persistence/racing/RacingPersistenceModule';
import { SocialPersistenceModule } from '../../persistence/social/SocialPersistenceModule';
import { AchievementPersistenceModule } from '../../persistence/achievement/AchievementPersistenceModule';
import { IdentityPersistenceModule } from '../../persistence/identity/IdentityPersistenceModule';
import { BootstrapProviders, ENSURE_INITIAL_DATA_TOKEN } from './BootstrapProviders';

@Module({
  imports: [RacingPersistenceModule, SocialPersistenceModule, AchievementPersistenceModule, IdentityPersistenceModule],
  providers: BootstrapProviders,
})
export class BootstrapModule implements OnModuleInit {
  constructor(
    @Inject(ENSURE_INITIAL_DATA_TOKEN) private readonly ensureInitialData: EnsureInitialData,
    @Inject('Logger') private readonly logger: Logger,
    @Inject('RacingSeedDependencies') private readonly seedDeps: RacingSeedDependencies,
  ) {}

  async onModuleInit() {
    console.log('[Bootstrap] Initializing application data...');
    try {
      if (!getEnableBootstrap()) {
        this.logger.info('[Bootstrap] Bootstrap disabled via GRIDPILOT_API_BOOTSTRAP; skipping initialization');
        return;
      }

      await this.ensureInitialData.execute();

      if (await this.shouldSeedRacingData()) {
        await new SeedRacingData(this.logger, this.seedDeps).execute();
      }

      console.log('[Bootstrap] Application data initialized successfully');
    } catch (error) {
      console.error('[Bootstrap] Failed to initialize application data:', error);
      throw error;
    }
  }

  private async shouldSeedRacingData(): Promise<boolean> {
    const persistence = getApiPersistence();

    if (persistence === 'inmemory') return true;
    if (persistence !== 'postgres') return false;
    if (process.env.NODE_ENV === 'production') return false;

    // Check for force reseed flag
    const forceReseed = getForceReseed();
    if (forceReseed) {
      this.logger.info('[Bootstrap] Force reseed enabled via GRIDPILOT_API_FORCE_RESEED');
      return true;
    }

    // Check if database is empty
    const isEmpty = await this.isRacingDatabaseEmpty();
    if (!isEmpty) {
      // Database has data, check if it needs reseeding
      return await this.needsReseed();
    }

    return true;
  }

  private async isRacingDatabaseEmpty(): Promise<boolean> {
    const count = await this.seedDeps.leagueRepository.countAll?.();
    if (typeof count === 'number') return count === 0;

    const leagues = await this.seedDeps.leagueRepository.findAll();
    return leagues.length === 0;
  }

  private async needsReseed(): Promise<boolean> {
    // Check if entity counts are below expected thresholds
    // This is conflict-proof: only checks durable entity presence, not transient media state
    try {
      // Expected counts based on seed data configuration
      const EXPECTED_DRIVERS = 150;
      const EXPECTED_TEAMS = 50; // Based on RacingTeamFactory logic
      const EXPECTED_LEAGUES = 120; // Based on RacingLeagueFactory logic
      
      // Check driver count
      const drivers = await this.seedDeps.driverRepository.findAll();
      const driverCount = drivers.length;
      if (driverCount < EXPECTED_DRIVERS) {
        this.logger.info(`[Bootstrap] Found ${driverCount} drivers (expected ${EXPECTED_DRIVERS}), triggering reseed`);
        return true;
      }
      
      // Check team count
      const teams = await this.seedDeps.teamRepository.findAll();
      const teamCount = teams.length;
      if (teamCount < EXPECTED_TEAMS) {
        this.logger.info(`[Bootstrap] Found ${teamCount} teams (expected ${EXPECTED_TEAMS}), triggering reseed`);
        return true;
      }
      
      // Check league count
      const leagues = await this.seedDeps.leagueRepository.findAll();
      const leagueCount = leagues.length;
      if (leagueCount < EXPECTED_LEAGUES) {
        this.logger.info(`[Bootstrap] Found ${leagueCount} leagues (expected ${EXPECTED_LEAGUES}), triggering reseed`);
        return true;
      }
      
      // All entity counts are sufficient - no reseed needed
      this.logger.info(`[Bootstrap] Entity counts sufficient: ${driverCount} drivers, ${teamCount} teams, ${leagueCount} leagues`);
      return false;
    } catch (error) {
      this.logger.warn('[Bootstrap] Error checking for reseed:', error);
      return false;
    }
  }
}