import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { ClsModule } from 'nestjs-cls';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { ScheduleModule } from '@nestjs/schedule';
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 { MailerModule } from './modules/mailer/mailer.module';
import { StorageModule } from './common/storage/storage.module';
import { MediaModule } from './common/media/media.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 { AgentCostModule } from './modules/agent-cost/agent-cost.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 { SupplierCostPriceModule } from './modules/supplier-cost-price/supplier-cost-price.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 { BankModule } from './modules/bank/bank.module';
import { BankAccountModule } from './modules/bank-account/bank-account.module';
import { DestinationVehicleTypeModule } from './modules/destination-vehicle-type/destination-vehicle-type.module';
import { PaymentSettlementModule } from './modules/payment-settlement/payment-settlement.module';
import { ServicePaymentCollectionModule } from './modules/service-payment-collection/service-payment-collection.module';
import { AccountingModule } from './modules/accounting/accounting.module';
import { CommunicationTemplateModule } from './modules/communication-template/communication-template.module';
import { QueryModule } from './modules/query/query.module';
import { BookingModule } from './modules/booking/booking.module';
import { ActivityTicketModule } from './modules/activity-ticket/activity-ticket.module';
import { ChangeRequestModule } from './modules/change-request/change-request.module';
import { NotificationModule } from './modules/notification/notification.module';
import { AuditModule } from './modules/audit/audit.module';
import { DashboardModule } from './modules/dashboard/dashboard.module';
import { PermissionsModule } from './common/permissions/permissions.module';
import { DevTenantMiddleware } from './common/middleware/tenant.middleware';
import { GlobalExceptionFilter } from './common/filters/http-exception.filter';
import { ReadOnlyInterceptor } from './common/interceptors/read-only.interceptor';

/**
 * 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 — global ceiling per IP. Sensitive routes (login,
    // refresh, password reset, uploads) carry tighter per-route limits
    // via @Throttle on their controllers — see security.md A04. The
    // global value is the fallback for everything else.
    //
    // 300/min lands at ~5 req/sec average, comfortably above realistic
    // user activity (a typical page load fires 8-12 reads; navigating
    // briskly stacks them). Original 60/min was tripping on normal
    // multi-page browsing once the Phase 3d Movement Chart map started
    // batching per-supplier cost fetches. Keep below 1000/min so a
    // runaway client loop still trips eventually.
    ThrottlerModule.forRoot([{ ttl: 60000, limit: 300 }]),
    ScheduleModule.forRoot(),
    AppConfigModule,
    DatabaseModule,
    RedisModule,
    PermissionsModule, // @Global — field-level gating usable from any service
    MailerModule, // @Global — Brevo-backed transactional email
    StorageModule, // @Global — local-disk file storage
    MediaModule, // @Global — per-module photo / video tables
    AuthModule,
    UserModule,
    RoleModule,
    TenantModule,
    SettingsModule,
    UploadModule,
    TagModule,
    DestinationModule,
    ServiceTypeModule,
    TaxTypeModule,
    AgentCostModule,
    TripSourceModule,
    HotelModule,
    TransportServiceModule,
    ActivityModule,
    SupplierModule,
    SupplierCostPriceModule,
    DriverModule,
    VehicleModule,
    CurrencyModule,
    ExchangeRateModule,
    SeasonModule,
    TransportPricingModule,
    ActivityPricingModule,
    VehicleTypeModule,
    BankModule,
    BankAccountModule,
    DestinationVehicleTypeModule,
    QueryModule,
    AuditModule,
    DashboardModule,
    BookingModule,
    ActivityTicketModule,
    ChangeRequestModule,
    PaymentSettlementModule,
    ServicePaymentCollectionModule,
    AccountingModule,
    CommunicationTemplateModule,
    NotificationModule,
  ],
  providers: [
    { provide: APP_GUARD, useClass: ThrottlerGuard },
    // Registered here rather than main.ts so the filter can inject
    // ErrorAlertService and email the dev team on 5xx.
    { provide: APP_FILTER, useClass: GlobalExceptionFilter },
    // Hard read-only wall for "View as user" impersonation — blocks every
    // write while a view-as session is active (CLS_READ_ONLY). Runs after
    // the auth guard so the flag is populated.
    { provide: APP_INTERCEPTOR, useClass: ReadOnlyInterceptor },
  ],
})
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('*');
  }
}
