import { Module, OnApplicationBootstrap } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { TypeOrmModule, TypeOrmModuleOptions } from "@nestjs/typeorm";
import { ScheduleModule } from "@nestjs/schedule";
import { DataSource, DataSourceOptions } from "typeorm";
import { ensurePostgresSchemas } from "./config/ensure-postgres-schemas";
import { IamModule, DataSeeder } from "@tria-plc/iamapi-common";
import { SharedAuthModule } from "@tria-plc/api-common/modules/auth/shared-auth.module";

import appConfig from "./config/app.config";
import databaseConfig from "./config/database.config";
import telebirrConfig from "./config/telebirr.config";
import rabbitmqConfig from "./config/rabbitmq.config";

import { BookingsModule } from "./modules/bookings/bookings.module";
import { BookingOrdersModule } from "./modules/booking-orders/booking-orders.module";
import { SignaturesModule } from "./modules/signatures/signatures.module";
import { FilesModule } from "./modules/files/files.module";
import { ConsignmentsModule } from "./modules/consignments/consignments.module";

// import { TrainsModule } from "./modules/trains/trains.module";
import { LocomotivesModule } from "./modules/locomotives/locomotives.module";
import { WagonTypesModule } from "./modules/wagon-types/wagon-types.module";
import { TrainSetsModule } from "./modules/train-sets/train-sets.module";
import { TrainSchedulesModule } from "./modules/train-schedules/train-schedules.module";
import { TrainSchedulingModule } from "./modules/train-scheduling/train-scheduling.module";
import { SchedulingRescheduleModule } from "./modules/scheduling-reschedule/scheduling-reschedule.module";
import { CompaniesModule } from "./modules/companies/companies.module";
import { TrackingModule } from "./modules/tracking/tracking.module";
import { BillingModule } from "./modules/billing/billing.module";
import { NotificationsModule } from "./modules/notifications/notifications.module";
import { FileUploadSettingsModule } from "./modules/file-upload-settings/file-upload-settings.module";
import { DropdownSettingsModule } from "./modules/dropdown-settings/dropdown-settings.module";
import { OtpModule } from "./modules/otp/otp.module";
import { RuleEngineModule } from "./modules/rule-engine/rule-engine.module";
import { BackofficeModule } from "./modules/backoffice/backoffice.module";
import { DemoPermissionsModule } from "./modules/demo-permissions/demo-permissions.module";
import { FreightAuthModule } from "./modules/auth/freight-auth.module";
import {
  EDR_FREIGHT_APPLICATION,
  EDR_FREIGHT_PERMISSIONS,
} from "./seed/edr-freight.seed";
import { EdrOrgSeeder } from "./seed/edr-org.seeder";
import { DemoUsersSeeder } from "./seed/demo-users.seeder";
import { FreightStaffUsersSeeder } from "./seed/freight-staff-users.seeder";
import { PaymentModule } from "./modules/payment/payment.module";
import { PricingDataSeeder } from "./seed/pricing-data.seeder";
import { FileUploadSettingsSeeder } from "./seed/file-upload-settings.seeder";
import { IndodeFacilitySeeder } from "./seed/indode-facility.seeder";
import { Batch14TestDataSeeder } from "./seed/batch1-4-test-data.seeder";
import { Batch5TestDataSeeder } from "./seed/batch5-test-data.seeder";
import { Batch7TestDataSeeder } from "./seed/batch7-test-data.seeder";
import { Batch8TestDataSeeder } from "./seed/batch8-test-data.seeder";
import { WarehouseDemoSeeder } from "./seed/warehouse-demo.seeder";
import { FreightPermissionKeyMigrationSeeder } from "./seed/freight-permission-key-migration.seeder";
import { DemoFreightDataSeeder } from "./seed/demo-freight-data.seeder";
//New Trains, Wagons, Container and Cargo management modules
import { TrainsModule } from "./modules/trains/trains.module";
import { WagonsModule } from './modules/wagons/wagons.module';
import { ContainersModule } from './modules/container-management/containers.module';
import { CargoesModule } from './modules/cargoes/cargoes.module';
import { RoutesModule } from './modules/routes/routes.module';
import { WarehousesModule } from './modules/warehouses/warehouses.module';
import { FacilitiesModule } from './modules/facilities/facilities.module';
import { OverviewModule } from './modules/overview/overview.module';
import { VehiclesModule } from './modules/vehicles/vehicles.module';
import { DriversModule } from './modules/drivers/drivers.module';
import { FirstMileModule } from './modules/first-mile/first-mile.module';
import { LastMileModule } from './modules/last-mile/last-mile.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [appConfig, databaseConfig, telebirrConfig, rabbitmqConfig],
    }),
    ScheduleModule.forRoot(),
    // EventEmitterModule.forRoot(),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService): TypeOrmModuleOptions =>
        config.get<TypeOrmModuleOptions>("database")!,
      dataSourceFactory: async (options) => {
        if (!options) {
          throw new Error("Missing TypeORM DataSource options");
        }
        await ensurePostgresSchemas(options as DataSourceOptions);
        const dataSource = new DataSource(options as DataSourceOptions);
        return dataSource.initialize();
      },
    }),
    SharedAuthModule,
    IamModule.forRoot({
      applications: [EDR_FREIGHT_APPLICATION],
      permissions: EDR_FREIGHT_PERMISSIONS,
    }),
    BookingsModule,
    BookingOrdersModule,
    SignaturesModule,
    FilesModule,
    ConsignmentsModule,
    LocomotivesModule,
    WagonTypesModule,
    TrainSetsModule,
    TrainSchedulesModule,
    TrainSchedulingModule,
    SchedulingRescheduleModule,
    CompaniesModule,
    TrackingModule,
    BillingModule,
    NotificationsModule,
    FileUploadSettingsModule,
    DropdownSettingsModule,
    OtpModule,
    RuleEngineModule,
    BackofficeModule,
    DemoPermissionsModule,
    FreightAuthModule,
    PaymentModule,
    //New Modules
    TrainsModule,
    WagonsModule,
    ContainersModule,
    CargoesModule,
    RoutesModule,
    FacilitiesModule,
    WarehousesModule,
    OverviewModule,
    VehiclesModule,
    DriversModule,
    FirstMileModule,
    LastMileModule,
  ],
  providers: [
    EdrOrgSeeder,
    DemoUsersSeeder,
    FreightStaffUsersSeeder,
    PricingDataSeeder,
    FileUploadSettingsSeeder,
    FreightPermissionKeyMigrationSeeder,
    DemoFreightDataSeeder,
    IndodeFacilitySeeder,
    Batch14TestDataSeeder,
    Batch5TestDataSeeder,
    Batch7TestDataSeeder,
    Batch8TestDataSeeder,
    WarehouseDemoSeeder,
  ],
})
export class AppModule implements OnApplicationBootstrap {
  constructor(
    private readonly seeder: DataSeeder,
    private readonly edrOrgSeeder: EdrOrgSeeder,
    private readonly demoUsersSeeder: DemoUsersSeeder,
    private readonly freightStaffUsersSeeder: FreightStaffUsersSeeder,
    private readonly pricingDataSeeder: PricingDataSeeder,
    private readonly fileUploadSettingsSeeder: FileUploadSettingsSeeder,
    private readonly indodeFacilitySeeder: IndodeFacilitySeeder,
    private readonly batch14TestDataSeeder: Batch14TestDataSeeder,
    private readonly batch5TestDataSeeder: Batch5TestDataSeeder,
    private readonly batch7TestDataSeeder: Batch7TestDataSeeder,
    private readonly batch8TestDataSeeder: Batch8TestDataSeeder,
    private readonly warehouseDemoSeeder: WarehouseDemoSeeder,
    private readonly freightPermissionKeyMigrationSeeder: FreightPermissionKeyMigrationSeeder,
    private readonly demoFreightDataSeeder: DemoFreightDataSeeder,
  ) { }

  async onApplicationBootstrap() {
    await this.freightPermissionKeyMigrationSeeder.run();
    await this.seeder.run();
    await this.edrOrgSeeder.run();
    await this.demoUsersSeeder.run();
    await this.freightStaffUsersSeeder.run();
    await this.pricingDataSeeder.run();
    await this.fileUploadSettingsSeeder.run();
    await this.indodeFacilitySeeder.run();
    await this.batch14TestDataSeeder.run();
    await this.batch5TestDataSeeder.run();
    await this.batch7TestDataSeeder.run();
    await this.batch8TestDataSeeder.run();
    await this.warehouseDemoSeeder.run();
    // Idempotent demo data: ≥100 wagons/type, approval chains, 4 staff users.
    // Each block self-guards on an empty-table check, so this is safe every boot.
    // Demo data seeds (DemoBookingsSeeder, PricingDataSeeder,
    // FileUploadSettingsSeeder) are intentionally disabled — they stay
    // registered as providers but are not run. Re-inject + call .run() to enable.
    // demoFreightDataSeeder now seeds ONLY the 4 staff users (wagons + approval
    // rules are disabled inside the seeder). Kept running for the staff users.
    await this.demoFreightDataSeeder.run();
  }
}
