import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { LoggerModule } from 'nestjs-pino';
import { APP_GUARD } from '@nestjs/core';
import {
  AcceptLanguageResolver,
  CookieResolver,
  HeaderResolver,
  I18nModule,
  QueryResolver,
} from 'nestjs-i18n';
import * as path from 'path';
import * as Joi from 'joi';
import { UserPreferenceResolver } from './infrastructure/i18n/user-preference.resolver';

// Import feature modules
import { AuthModule } from './application/auth/auth.module';
import { RatesModule } from './application/rates/rates.module';
import { PortsModule } from './application/ports/ports.module';
import { BookingsModule } from './application/bookings/bookings.module';
import { OrganizationsModule } from './application/organizations/organizations.module';
import { UsersModule } from './application/users/users.module';
import { DashboardModule } from './application/dashboard/dashboard.module';
import { AuditModule } from './application/audit/audit.module';
import { NotificationsModule } from './application/notifications/notifications.module';
import { WebhooksModule } from './application/webhooks/webhooks.module';
import { GDPRModule } from './application/gdpr/gdpr.module';
import { CsvBookingsModule } from './application/csv-bookings/csv-bookings.module';
import { AdminModule } from './application/admin/admin.module';
import { BlogModule } from './application/blog/blog.module';
import { LogsModule } from './application/logs/logs.module';
import { SubscriptionsModule } from './application/subscriptions/subscriptions.module';
import { ApiKeysModule } from './application/api-keys/api-keys.module';
import { CacheModule } from './infrastructure/cache/cache.module';
import { CarrierModule } from './infrastructure/carriers/carrier.module';
import { SecurityModule } from './infrastructure/security/security.module';
import { CsvRateModule } from './infrastructure/carriers/csv-loader/csv-rate.module';

// Import global guards
import { ApiKeyOrJwtGuard } from './application/guards/api-key-or-jwt.guard';
import { CustomThrottlerGuard } from './application/guards/throttle.guard';

@Module({
  imports: [
    // Configuration
    ConfigModule.forRoot({
      isGlobal: true,
      validationSchema: Joi.object({
        NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
        PORT: Joi.number().default(4000),
        APP_URL: Joi.string().uri().default('http://localhost:3000'),
        BACKEND_URL: Joi.string().uri().optional(),
        DATABASE_HOST: Joi.string().required(),
        DATABASE_PORT: Joi.number().default(5432),
        DATABASE_USER: Joi.string().required(),
        DATABASE_PASSWORD: Joi.string().required(),
        DATABASE_NAME: Joi.string().required(),
        REDIS_HOST: Joi.string().required(),
        REDIS_PORT: Joi.number().default(6379),
        REDIS_PASSWORD: Joi.string().required(),
        JWT_SECRET: Joi.string().required(),
        JWT_ACCESS_EXPIRATION: Joi.string().default('15m'),
        JWT_REFRESH_EXPIRATION: Joi.string().default('7d'),
        // SMTP Configuration
        SMTP_HOST: Joi.string().required(),
        SMTP_PORT: Joi.number().default(2525),
        SMTP_USER: Joi.string().required(),
        SMTP_PASS: Joi.string().required(),
        SMTP_FROM: Joi.string().email().default('noreply@xpeditis.com'),
        SMTP_SECURE: Joi.boolean().default(false),
        // Stripe Configuration (optional for development)
        STRIPE_SECRET_KEY: Joi.string().optional(),
        STRIPE_WEBHOOK_SECRET: Joi.string().optional(),
        STRIPE_SILVER_MONTHLY_PRICE_ID: Joi.string().optional(),
        STRIPE_SILVER_YEARLY_PRICE_ID: Joi.string().optional(),
        STRIPE_GOLD_MONTHLY_PRICE_ID: Joi.string().optional(),
        STRIPE_GOLD_YEARLY_PRICE_ID: Joi.string().optional(),
        STRIPE_PLATINIUM_MONTHLY_PRICE_ID: Joi.string().optional(),
        STRIPE_PLATINIUM_YEARLY_PRICE_ID: Joi.string().optional(),
        LOG_EXPORTER_URL: Joi.string().uri().default('http://xpeditis-log-exporter:3200'),
      }),
    }),

    // Logging
    LoggerModule.forRootAsync({
      useFactory: (configService: ConfigService) => {
        const isDev = configService.get('NODE_ENV') === 'development';
        // LOG_FORMAT=json forces structured JSON output (e.g. inside Docker + Promtail)
        const forceJson = configService.get('LOG_FORMAT') === 'json';
        const usePretty = isDev && !forceJson;

        return {
          pinoHttp: {
            transport: usePretty
              ? {
                  target: 'pino-pretty',
                  options: {
                    colorize: true,
                    translateTime: 'SYS:standard',
                    ignore: 'pid,hostname',
                  },
                }
              : undefined,
            level: isDev ? 'debug' : 'info',
            // Redact sensitive fields from logs
            redact: {
              paths: [
                'req.headers.authorization',
                'req.headers["x-api-key"]',
                'req.body.password',
                'req.body.currentPassword',
                'req.body.newPassword',
              ],
              censor: '[REDACTED]',
            },
          },
        };
      },
      inject: [ConfigService],
    }),

    // Internationalization (FR / EN)
    // Resolver chain (highest priority first):
    //   1. UserPreferenceResolver — authenticated user's preferredLanguage
    //   2. CookieResolver (NEXT_LOCALE)     — set by frontend switcher
    //   3. HeaderResolver (x-lang / x-locale)
    //   4. QueryResolver  (?lang=xx)
    //   5. AcceptLanguageResolver
    //   6. fallback → 'fr'
    I18nModule.forRoot({
      fallbackLanguage: 'fr',
      loaderOptions: {
        path: path.join(__dirname, '/i18n/'),
        watch: true,
      },
      resolvers: [
        UserPreferenceResolver,
        new CookieResolver(['NEXT_LOCALE', 'lang']),
        new HeaderResolver(['x-lang', 'x-locale']),
        new QueryResolver(['lang', 'locale']),
        AcceptLanguageResolver,
      ],
    }),

    // Database
    TypeOrmModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        type: 'postgres',
        host: configService.get('DATABASE_HOST'),
        port: configService.get('DATABASE_PORT'),
        username: configService.get('DATABASE_USER'),
        password: configService.get('DATABASE_PASSWORD'),
        database: configService.get('DATABASE_NAME'),
        entities: [__dirname + '/**/*.orm-entity{.ts,.js}'],
        synchronize: false, // ✅ Force false - use migrations instead
        logging: configService.get('DATABASE_LOGGING', false),
        autoLoadEntities: true, // Auto-load entities from forFeature()
      }),
      inject: [ConfigService],
    }),

    // Infrastructure modules
    SecurityModule,
    CacheModule,
    CarrierModule,
    CsvRateModule,

    // Feature modules
    AuthModule,
    RatesModule,
    PortsModule,
    BookingsModule,
    CsvBookingsModule,
    OrganizationsModule,
    UsersModule,
    DashboardModule,
    AuditModule,
    NotificationsModule,
    WebhooksModule,
    GDPRModule,
    AdminModule,
    BlogModule,
    SubscriptionsModule,
    ApiKeysModule,
    LogsModule,
  ],
  controllers: [],
  providers: [
    // Global authentication guard — supports both JWT (frontend) and API key (Gold/Platinium)
    // All routes are protected by default, use @Public() to bypass
    {
      provide: APP_GUARD,
      useClass: ApiKeyOrJwtGuard,
    },
    // Global rate limiting guard
    {
      provide: APP_GUARD,
      useClass: CustomThrottlerGuard,
    },
  ],
})
export class AppModule {}
