import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
import { ThrottlerModule, ThrottlerGuard } from "@nestjs/throttler";
import { CacheModule } from "@nestjs/cache-manager";
import { ScheduleModule } from "@nestjs/schedule";
import { redisStore } from "cache-manager-redis-yet";
import { LoggerModule } from "nestjs-pino";
import {
  I18nModule,
  AcceptLanguageResolver,
  HeaderResolver,
  QueryResolver,
} from "nestjs-i18n";
import { ServeStaticModule } from "@nestjs/serve-static";
import * as path from "path";

// Config
import {
  appConfig,
  databaseConfig,
  jwtConfig,
  redisConfig,
  i18nConfig,
  featuresConfig,
  throttleConfig,
} from "./config/configuration";
import { geminiConfig } from "./modules/gemini/gemini.config";
import { validateEnv } from "./config/env.validation";

// Common
import { GlobalExceptionFilter } from "./common/filters/global-exception.filter";
import { ResponseInterceptor } from "./common/interceptors/response.interceptor";

// Database
import { DatabaseModule } from "./database/database.module";

// Core Modules
import { AuthModule } from "./modules/auth/auth.module";
import { UsersModule } from "./modules/users/users.module";
import { AdminModule } from "./modules/admin/admin.module";
import { HealthModule } from "./modules/health/health.module";
import { GeminiModule } from "./modules/gemini/gemini.module";
import { SocialPosterModule } from "./modules/social-poster/social-poster.module";

// Sports Domain Modules
import { MatchesModule } from "./modules/matches/matches.module";
import { PredictionsModule } from "./modules/predictions/predictions.module";
import { ValueBoardModule } from "./modules/value-board/value-board.module";
import { LeaguesModule } from "./modules/leagues/leagues.module";
import { AnalysisModule } from "./modules/analysis/analysis.module";
import { CouponsModule } from "./modules/coupons/coupons.module";
import { SporTotoModule } from "./modules/spor-toto/spor-toto.module";
import { AiProxyModule } from "./modules/ai-proxy/ai-proxy.module";
import { SubscriptionsModule } from "./modules/subscriptions/subscriptions.module";

// Services and Tasks
import { ServicesModule } from "./services/services.module";
import { TasksModule } from "./tasks/tasks.module";

// Feeder Module (Historical Data Scraping)
import { FeederModule } from "./modules/feeder/feeder.module";

// Guards
import {
  JwtAuthGuard,
  RolesGuard,
  PermissionsGuard,
} from "./modules/auth/guards";

// Queue
import { QueueModule } from "./common/queues/queue.module";

const redisEnabled = process.env.REDIS_ENABLED === "true";
const historicalFeederMode = process.env.FEEDER_MODE === "historical";

@Module({
  imports: [
    // Configuration
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: [".env.local", ".env"],
      validate: validateEnv,
      load: [
        appConfig,
        databaseConfig,
        jwtConfig,
        redisConfig,
        i18nConfig,
        featuresConfig,
        throttleConfig,
        geminiConfig,
      ],
    }),

    // Global Queue Configuration (optional)
    ...(redisEnabled ? [QueueModule] : []),

    // Static Assets (Images, Uploads)
    ServeStaticModule.forRoot({
      rootPath: path.join(__dirname, "..", "public"),
      serveRoot: "/", // This means public/uploads/x.png -> /uploads/x.png
    }),

    // Logger (Structured Logging with Pino)
    LoggerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => {
        return {
          pinoHttp: {
            level: configService.get("app.isDevelopment") ? "debug" : "info",
            transport: configService.get("app.isDevelopment")
              ? {
                  target: "pino-pretty",
                  options: {
                    singleLine: true,
                  },
                }
              : undefined,
          },
        };
      },
    }),

    // i18n
    I18nModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        fallbackLanguage: configService.get("i18n.fallbackLanguage", "en"),
        loaderOptions: {
          path: path.join(__dirname, "../i18n/"),
          watch: configService.get("app.isDevelopment", true),
        },
      }),
      resolvers: [
        new HeaderResolver(["x-lang"]),
        new QueryResolver(["lang"]),
        AcceptLanguageResolver,
      ],
      inject: [ConfigService],
    }),

    // Throttling
    ThrottlerModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => [
        {
          ttl: configService.get("throttle.ttl", 60000),
          limit: configService.get("throttle.limit", 100),
        },
      ],
    }),

    // Caching (Redis with in-memory fallback)
    CacheModule.registerAsync({
      isGlobal: true,
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => {
        // FORCE DISABLE REDIS if user doesn't want it
        const useRedis = configService.get("redis.enabled", false);

        if (useRedis) {
          try {
            const store = await redisStore({
              socket: {
                host: configService.get("redis.host", "localhost"),
                port: configService.get("redis.port", 6379),
              },
              ttl: 60 * 1000, // 1 minute default
            });
            console.log("✅ Redis cache connected");
            return {
              store: store as unknown as any,
              ttl: 60 * 1000,
            };
          } catch {
            console.warn("⚠️ Redis connection failed, using in-memory cache");
          }
        }

        // Fallback to in-memory cache
        console.log("📦 Using in-memory cache");
        return {
          ttl: 60 * 1000,
        };
      },
      inject: [ConfigService],
    }),

    // Database
    DatabaseModule,

    // Scheduling (for cron jobs)
    ...(historicalFeederMode ? [] : [ScheduleModule.forRoot()]),

    // Core Modules
    AuthModule,
    UsersModule,
    AdminModule,

    // Sports Domain Modules
    MatchesModule,
    PredictionsModule,
    ValueBoardModule,
    LeaguesModule,
    AnalysisModule,
    CouponsModule,
    SporTotoModule,
    AiProxyModule,
    SubscriptionsModule,

    // Services and Scheduled Tasks
    ServicesModule,
    ...(historicalFeederMode ? [] : [TasksModule]),

    // Optional Modules (controlled by env variables)
    GeminiModule,
    HealthModule,
    SocialPosterModule,

    // Feeder Module (Historical Data Scraping)
    FeederModule,
  ],
  providers: [
    // Global Exception Filter
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter,
    },

    // Global Response Interceptor
    {
      provide: APP_INTERCEPTOR,
      useClass: ResponseInterceptor,
    },

    // Global Rate Limiting
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },

    // Global JWT Auth Guard
    {
      provide: APP_GUARD,
      useClass: JwtAuthGuard,
    },

    // Global Roles Guard
    {
      provide: APP_GUARD,
      useClass: RolesGuard,
    },

    // Global Permissions Guard
    {
      provide: APP_GUARD,
      useClass: PermissionsGuard,
    },
  ],
})
export class AppModule {}
