import 'reflect-metadata';
import { Container } from 'inversify';

// Module imports
import { ApiModule } from './modules/api.module';
import { AuthModule } from './modules/auth.module';
import { CoreModule } from './modules/core.module';
import { DriverModule } from './modules/driver.module';
import { LeagueModule } from './modules/league.module';
import { TeamModule } from './modules/team.module';
import { RaceModule } from './modules/race.module';
import { LandingModule } from './modules/landing.module';
import { PolicyModule } from './modules/policy.module';
import { SponsorModule } from './modules/sponsor.module';
import { AnalyticsModule } from './modules/analytics.module';

/**
 * Creates and configures the root DI container
 */
export function createContainer(): Container {
  const container = new Container();

  // Load all modules
  container.load(
    CoreModule,
    ApiModule,
    AuthModule,
    LeagueModule,
    DriverModule,
    TeamModule,
    RaceModule,
    LandingModule,
    PolicyModule,
    SponsorModule,
    AnalyticsModule
  );

  return container;
}

/**
 * Creates a container for testing with mock overrides
 */
export async function createTestContainer(overrides: Map<symbol, any> = new Map()): Promise<Container> {
  const container = createContainer();
  
  // Apply mock overrides using rebind
  const promises = Array.from(overrides.entries()).map(([token, mockInstance]) => {
    return container.rebind(token).then(bind => bind.toConstantValue(mockInstance));
  });
  
  await Promise.all(promises);
  
  return container;
}

/**
 * Container lifecycle management
 */
export class ContainerManager {
  private static instance: ContainerManager | null = null;
  private container: Container | null = null;

  private constructor() {}

  static getInstance(): ContainerManager {
    if (!ContainerManager.instance) {
      ContainerManager.instance = new ContainerManager();
    }
    return ContainerManager.instance;
  }

  getContainer(): Container {
    if (!this.container) {
      this.container = createContainer();
    }
    return this.container;
  }

  createScopedContainer(): Container {
    // In this version, we create a new container
    return new Container();
  }

  dispose(): void {
    if (this.container) {
      this.container.unbindAll();
      this.container = null;
    }
  }
}