import { Injectable, Inject, Optional } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { PrismaService } from './prisma.service';

@Injectable()
export class AuditService {
  constructor(
    private prisma: PrismaService,
    @Optional() @Inject(REQUEST) private request?: any,
  ) {}

  async log(input: {
    userId?: string;
    action: 'CREATE' | 'UPDATE' | 'DELETE' | 'LOGIN' | 'LOGOUT' | 'VERIFY' | string;
    entityType: string;
    entityId?: string;
    oldData?: any;
    newData?: any;
  }) {
    try {
      const ipAddress = this.getIpAddress();
      const userAgent = this.getUserAgent();

      await this.prisma.auditLog.create({
        data: {
          userId: input.userId,
          action: input.action,
          entityType: input.entityType,
          entityId: input.entityId,
          oldData: input.oldData,
          newData: input.newData,
          ipAddress,
          userAgent,
        },
      });
    } catch (error) {
      console.error('Failed to log audit event:', error);
      // Don't throw - audit logging should not break main operations
    }
  }

  private getIpAddress(): string {
    if (!this.request) return '';
    
    return (
      this.request.headers['x-forwarded-for']?.split(',')[0].trim() ||
      this.request.headers['x-real-ip'] ||
      this.request.connection?.remoteAddress ||
      this.request.socket?.remoteAddress ||
      this.request.ip ||
      ''
    );
  }

  private getUserAgent(): string {
    return this.request?.headers?.['user-agent'] || '';
  }

  async getLogs(filters: any = {}) {
    const where: any = {};

    if (filters.search) {
      where.OR = [
        { entityId: { contains: filters.search, mode: 'insensitive' } },
        { user: { email: { contains: filters.search, mode: 'insensitive' } } },
        { user: { fullName: { contains: filters.search, mode: 'insensitive' } } },
      ];
    }

    if (filters.action) {
      where.action = filters.action;
    }

    if (filters.entityType) {
      where.entityType = filters.entityType;
    }

    return this.prisma.auditLog.findMany({
      where,
      include: { user: true },
      orderBy: { createdAt: 'desc' },
      take: 500, // Limit to last 500 logs
    });
  }

  async getLog(id: string) {
    return this.prisma.auditLog.findUnique({
      where: { id },
      include: { user: true },
    });
  }
}
