import { type DynamicModule, Module, type MiddlewareConsumer, type NestModule } from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import { ToolRegistryService } from '../../core/agent-tools/tool-registry.service';
import { AuthService } from '../auth/auth.service';
import { AuditService } from '../audit/audit.service';
import { KeyRateLimiter, readRateLimitConfig, readIpRateLimitConfig } from './mcp-rate-limit';
import { mountMcpServer } from './mcp.server';

export interface McpModuleOptions {
  basePath?: string;
  serverInfo?: { name: string; version: string };
}

// Module-level options store: set by forRoot(), read by configure().
// Safe because configure() runs after DI resolution (i.e., after forRoot() has been called).
let _moduleOptions: McpModuleOptions = {};

@Module({})
export class McpModule implements NestModule {
  constructor(
    private readonly registry: ToolRegistryService,
    private readonly authService: AuthService,
    private readonly httpAdapterHost: HttpAdapterHost,
    // AuditModule is @Global(), so AuditService is injectable here without an explicit import.
    private readonly auditService: AuditService,
  ) {}

  static forRoot(options: McpModuleOptions = {}): DynamicModule {
    _moduleOptions = options;
    return {
      module: McpModule,
      global: false,
      providers: [],
      exports: [],
    };
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  configure(_consumer: MiddlewareConsumer): void {
    const httpAdapter = this.httpAdapterHost.httpAdapter;
    if (!httpAdapter) {
      throw new Error('McpModule: HttpAdapterHost.httpAdapter is not available.');
    }
    const { basePath, serverInfo } = _moduleOptions;
    const { max, windowMs } = readRateLimitConfig();
    const rateLimiter = new KeyRateLimiter(max, windowMs);
    const ipCfg = readIpRateLimitConfig();
    const ipRateLimiter = new KeyRateLimiter(ipCfg.max, ipCfg.windowMs);
    mountMcpServer(
      httpAdapter,
      this.registry,
      this.authService,
      rateLimiter,
      ipRateLimiter,
      { basePath, serverInfo },
      this.auditService,
    );
  }
}
