import {
  MiddlewareConsumer,
  Module,
  NestModule,
  DynamicModule,
} from "@nestjs/common";
import { TerminusModule } from "@nestjs/terminus";
import { HttpModule } from "@nestjs/axios";
import { HealthController } from "./health.controller";
import { HealthService } from "./health.service";
import { MetricsService } from "./metrics.service";
import { RequestLoggerMiddleware } from "./request-logger.middleware";

// Define a unique token for the module options
export const MODULE_OPTIONS_TOKEN = "HEALTH_MODULE_OPTIONS";

export interface HealthModuleOptions {
  /**
   * Enable memory monitoring health checks
   * @default true
   */
  enableMemoryMonitoring?: boolean;

  /**
   * Enable disk monitoring health checks
   * @default false
   */
  enableDiskMonitoring?: boolean;

  /**
   * Path to monitor for disk space
   * @default '/'
   */
  diskPath?: string;

  /**
   * Disk usage threshold percentage (0-100)
   * @default 75
   */
  diskThresholdPercent?: number;

  /**
   * Route prefix for health endpoints
   * @default 'health'
   */
  routePrefix?: string;

  /**
   * Enable password protection for health endpoints
   * @default false
   */
  passwordProtected?: boolean;

  /**
   * Password for accessing health endpoints (required if passwordProtected is true)
   */
  password?: string;
}

@Module({
  imports: [TerminusModule, HttpModule],
  controllers: [HealthController],
  providers: [HealthService, MetricsService],
  exports: [HealthService, MetricsService],
})
export class HealthModule implements NestModule {
  /**
   * Register the health module with custom options
   * @param options Module configuration options
   * @returns Dynamic module definition
   */
  static register(options: HealthModuleOptions = {}): DynamicModule {
    const defaultOptions: HealthModuleOptions = {
      enableMemoryMonitoring: true,
      enableDiskMonitoring: false,
      diskPath: "/",
      diskThresholdPercent: 75,
      routePrefix: "health",
      passwordProtected: false,
      password: "",
    };

    // Merge default options with user-provided options
    const moduleOptions = {
      ...defaultOptions,
      ...options,
    };

    // Validate password if passwordProtected is true
    if (moduleOptions.passwordProtected && !moduleOptions.password) {
      throw new Error("Password is required when passwordProtected is true");
    }

    return {
      module: HealthModule,
      imports: [TerminusModule, HttpModule],
      providers: [
        HealthService,
        MetricsService,
        {
          provide: MODULE_OPTIONS_TOKEN,
          useValue: moduleOptions,
        },
      ],
      controllers: [HealthController],
      exports: [HealthService, MetricsService],
    };
  }

  /**
   * Configure middleware for the module
   * @param consumer Middleware consumer
   */
  configure(consumer: MiddlewareConsumer): void {
    consumer.apply(RequestLoggerMiddleware).forRoutes("*");
  }
}
