import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class SessionActivityInterceptor implements NestInterceptor {
  private readonly inactivityMinutes: number;

  constructor(
    @InjectDataSource() private readonly dataSource: DataSource,
    private readonly config: ConfigService,
  ) {
    this.inactivityMinutes = parseInt(this.config.get<string>('SESSION_INACTIVITY_MINUTES') || '30', 10);
  }

  async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();
    const sessionId: string | undefined = request.user?.sessionId;

    if (sessionId) {
      const rows = await this.dataSource.query<Array<{ expiry_time: Date }>>(
        `SELECT expiry_time FROM iam.sessions WHERE id = $1 AND status = 'ACTIVE' LIMIT 1`,
        [sessionId],
      );

      if (rows.length) {
        const minutesLeft = (rows[0].expiry_time.getTime() - Date.now()) / 60000;
        if (minutesLeft < this.inactivityMinutes * 0.2) {
          response.setHeader('X-Session-Expiry-Warning', Math.floor(minutesLeft).toString());
        }

        // Extend session on every authenticated request
        await this.dataSource.query(
          `UPDATE iam.sessions SET expiry_time = NOW() + ($1 * INTERVAL '1 minute') WHERE id = $2 AND status = 'ACTIVE'`,
          [this.inactivityMinutes, sessionId],
        );
      }
    }

    return next.handle().pipe(tap(() => {}));
  }
}
