/**
 * AnalyticsInterceptor - Automatic request tracking
 *
 * Tracks all HTTP requests with timing, status, and context.
 */

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Inject,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';

import { BackendAnalyticsClient } from '@analytics/client';
import { ANALYTICS_CLIENT } from './analytics.module';

interface RequestContext {
  sessionId: string;
  userId?: string;
  ip: string;
  userAgent: string;
}

@Injectable()
export class AnalyticsInterceptor implements NestInterceptor {
  constructor(
    @Inject(ANALYTICS_CLIENT)
    private readonly analytics: BackendAnalyticsClient,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();
    const startTime = Date.now();

    const ctx = this.extractContext(request);

    return next.handle().pipe(
      tap(() => {
        this.trackRequest(request, response, ctx, startTime, 'success');
      }),
      catchError((error) => {
        this.trackRequest(request, response, ctx, startTime, 'error', error);
        throw error;
      }),
    );
  }

  private extractContext(request: any): RequestContext {
    return {
      // Session ID from client header
      sessionId: request.headers['x-session-id'] || this.generateSessionId(),
      // User ID from auth middleware (if authenticated)
      userId: request.user?.id || request.user?.userId,
      // IP for geolocation
      ip: this.extractIp(request),
      // User agent for device detection
      userAgent: request.headers['user-agent'] || 'unknown',
    };
  }

  private extractIp(request: any): string {
    return (
      request.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
      request.headers['x-real-ip'] ||
      request.ip ||
      '0.0.0.0'
    );
  }

  private generateSessionId(): string {
    return `srv_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
  }

  private trackRequest(
    request: any,
    response: any,
    ctx: RequestContext,
    startTime: number,
    outcome: 'success' | 'error',
    error?: Error,
  ): void {
    const duration = Date.now() - startTime;
    const method = request.method;
    const path = request.route?.path || request.url;
    const statusCode = response.statusCode;

    // Track as engagement event
    this.analytics.trackEngagement({
      sessionId: ctx.sessionId,
      userId: ctx.userId,
      type: 'api_request',
      action: `${method} ${path}`,
      metadata: {
        method,
        path,
        statusCode,
        durationMs: duration,
        outcome,
        errorMessage: error?.message,
        ip: ctx.ip,
        userAgent: ctx.userAgent,
      },
    });
  }
}

/**
 * Usage: Register globally in your AppModule
 *
 * ```ts
 * import { APP_INTERCEPTOR } from '@nestjs/core';
 *
 * @Module({
 *   providers: [
 *     {
 *       provide: APP_INTERCEPTOR,
 *       useClass: AnalyticsInterceptor,
 *     },
 *   ],
 * })
 * export class AppModule {}
 * ```
 *
 * Or use on specific controllers:
 *
 * ```ts
 * @Controller('users')
 * @UseInterceptors(AnalyticsInterceptor)
 * export class UserController { }
 * ```
 */
