import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { ClsModule } from 'nestjs-cls';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { AppConfigModule } from './config/config.module';
import { DatabaseModule } from './database/database.module';
import { RedisModule } from './redis/redis.module';
import { AuthModule } from './auth/auth.module';
import { UserModule } from './modules/user/user.module';
import { RoleModule } from './modules/role/role.module';
import { TenantModule } from './modules/tenant/tenant.module';
import { SettingsModule } from './modules/settings/settings.module';
import { UploadModule } from './modules/upload/upload.module';
import { TagModule } from './modules/tag/tag.module';
import { DestinationModule } from './modules/destination/destination.module';
import { ServiceTypeModule } from './modules/service-type/service-type.module';
import { TaxTypeModule } from './modules/tax-type/tax-type.module';
import { TripSourceModule } from './modules/trip-source/trip-source.module';
import { HotelModule } from './modules/hotel/hotel.module';
import { TransportServiceModule } from './modules/transport-service/transport-service.module';
import { ActivityModule } from './modules/activity/activity.module';
import { SupplierModule } from './modules/supplier/supplier.module';
import { DriverModule } from './modules/driver/driver.module';
import { VehicleModule } from './modules/vehicle/vehicle.module';
import { CurrencyModule } from './modules/currency/currency.module';
import { ExchangeRateModule } from './modules/exchange-rate/exchange-rate.module';
import { SeasonModule } from './modules/season/season.module';
import { TransportPricingModule } from './modules/transport-pricing/transport-pricing.module';
import { ActivityPricingModule } from './modules/activity-pricing/activity-pricing.module';
import { VehicleTypeModule } from './modules/vehicle-type/vehicle-type.module';
import { QueryModule } from './modules/query/query.module';
import { BookingModule } from './modules/booking/booking.module';
import { AuditModule } from './modules/audit/audit.module';
import { DashboardModule } from './modules/dashboard/dashboard.module';
import {
  TenantMiddleware,
  DevTenantMiddleware,
} from './common/middleware/tenant.middleware';

/**
 * AppModule — root module.
 *
 * Per CLAUDE.md:
 * - ClsModule provides async context for tenant_id + user_id propagation
 * - TenantInterceptor REMOVED — CLS replaces it entirely
 * - No setTenantId() calls anywhere
 */
@Module({
  imports: [
    // CLS must be first — provides async context for all downstream modules
    ClsModule.forRoot({
      global: true,
      middleware: {
        mount: true, // Auto-mounts CLS middleware for every request
      },
    }),
    // Rate limiting — 60 requests per minute per IP
    ThrottlerModule.forRoot([{ ttl: 60000, limit: 60 }]),
    AppConfigModule,
    DatabaseModule,
    RedisModule,
    AuthModule,
    UserModule,
    RoleModule,
    TenantModule,
    SettingsModule,
    UploadModule,
    TagModule,
    DestinationModule,
    ServiceTypeModule,
    TaxTypeModule,
    TripSourceModule,
    HotelModule,
    TransportServiceModule,
    ActivityModule,
    SupplierModule,
    DriverModule,
    VehicleModule,
    CurrencyModule,
    ExchangeRateModule,
    SeasonModule,
    TransportPricingModule,
    ActivityPricingModule,
    VehicleTypeModule,
    QueryModule,
    AuditModule,
    DashboardModule,
    BookingModule,
  ],
  providers: [
    { provide: APP_GUARD, useClass: ThrottlerGuard },
  ],
})
export class AppModule implements NestModule {
  constructor(private readonly configService: ConfigService) {}

  configure(consumer: MiddlewareConsumer): void {
    // Phase 1: always use header-based tenant resolution (no subdomain middleware yet)
    const middleware = DevTenantMiddleware;

    // Apply tenant middleware to all routes EXCEPT tenant onboarding
    consumer
      .apply(middleware)
      .exclude({ path: 'tenants/onboard', method: RequestMethod.POST })
      .forRoutes('*');
  }
}
