import {
  Injectable, NestInterceptor,
  ExecutionContext, CallHandler
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { AuditLog } from '../../audit/entities/audit-log.entity';

// Actions à tracer automatiquement
const AUDIT_METHODS: Record<string, string> = {
  POST:   'CREATE',
  PUT:    'UPDATE',
  DELETE: 'DELETE',
};

// Routes à exclure du traçage automatique
const EXCLUDED_ROUTES = [
  '/auth/login',
  '/notifications',
  '/audit',
];

@Injectable()
export class AuditInterceptor implements NestInterceptor {
  constructor(
    @InjectRepository(AuditLog)
    private readonly auditLogRepo: Repository<AuditLog>,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const method  = request.method as string;
    const url     = request.url as string;
    const user    = request.user;

    // Ignorer les méthodes GET et les routes exclues
    if (
      method === 'GET' ||
      !AUDIT_METHODS[method] ||
      EXCLUDED_ROUTES.some(r => url.startsWith(r))
    ) {
      return next.handle();
    }

    return next.handle().pipe(
      tap(async (responseData) => {
        try {
          if (!user) return;

          // Extraire le type d'entité depuis l'URL
          const urlParts   = url.split('/').filter(Boolean);
          const entityType = urlParts[0] ?? 'unknown';
          const entityId   = urlParts[1] ? +urlParts[1] : responseData?.id ?? 0;
          const action     = `${AUDIT_METHODS[method]}_${entityType.toUpperCase()}`;

          await this.auditLogRepo.save(
            this.auditLogRepo.create({
              user,
              action,
              entity_type: entityType,
              entity_id:   isNaN(entityId) ? 0 : entityId,
              new_value:   responseData
                ? { summary: JSON.stringify(responseData).substring(0, 200) }
                : undefined,
              ip_address: request.ip,
            }),
          );
        } catch {
          // Ne jamais bloquer la requête à cause de l'audit
        }
      }),
    );
  }
}