import {
  BeforeApplicationShutdown,
  Injectable,
  OnApplicationShutdown,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { setTimeout as delay } from 'timers/promises';
import { AppLoggerService } from '../logging/app-logger.service';

export type ApplicationLifecycleState = 'running' | 'draining' | 'stopped';

@Injectable()
export class ShutdownCoordinatorService
  implements BeforeApplicationShutdown, OnApplicationShutdown
{
  private state: ApplicationLifecycleState = 'running';
  private activeRequests = 0;

  constructor(
    private readonly configService: ConfigService,
    private readonly logger: AppLoggerService,
  ) {}

  getState(): ApplicationLifecycleState {
    return this.state;
  }

  isDraining(): boolean {
    return this.state !== 'running';
  }

  getActiveRequests(): number {
    return this.activeRequests;
  }

  beginRequest(): boolean {
    if (this.state !== 'running') {
      return false;
    }
    this.activeRequests += 1;
    return true;
  }

  endRequest(): void {
    this.activeRequests = Math.max(0, this.activeRequests - 1);
  }

  async beforeApplicationShutdown(signal?: string): Promise<void> {
    this.state = 'draining';
    const gracePeriodMs =
      this.configService.get<number>('reliability.shutdownGracePeriodMs', { infer: true }) ??
      30_000;
    const deadline = Date.now() + gracePeriodMs;

    this.logger.warn(
      `Shutdown initiated${signal ? ` by ${signal}` : ''}; draining ${this.activeRequests} active request(s) for up to ${gracePeriodMs}ms`,
      'ShutdownCoordinator',
    );

    while (this.activeRequests > 0 && Date.now() < deadline) {
      await delay(Math.min(50, Math.max(1, deadline - Date.now())));
    }

    if (this.activeRequests > 0) {
      this.logger.warn(
        `Grace period elapsed with ${this.activeRequests} active request(s) still running`,
        'ShutdownCoordinator',
      );
    }
  }

  onApplicationShutdown(signal?: string): void {
    this.state = 'stopped';
    this.logger.log(
      `Shutdown complete${signal ? ` (${signal})` : ''}`,
      'ShutdownCoordinator',
    );
  }
}
