import { logger } from '@goodgo/logger';
import { PrismaClient } from '@prisma/client';
import { Request } from 'express';

import { getPrismaClient } from '../../config/database.config';

/**
 * EN: Audit Service for event sourcing and audit logging
 * VI: Service Audit cho event sourcing và audit logging
 */
export class AuditService {
  private prisma: PrismaClient;

  constructor() {
    this.prisma = getPrismaClient();
  }

  /**
   * EN: Log authentication event
   * VI: Ghi log sự kiện xác thực
   */
  async logAuthEvent(
    eventType: string,
    data: {
      userId?: string;
      success: boolean;
      errorMessage?: string;
      ipAddress?: string;
      userAgent?: string;
      metadata?: any;
      // EN: Additional fields for specific event types
      // VI: Các trường bổ sung cho các loại sự kiện cụ thể
      requestId?: string;
      reviewId?: string;
      itemId?: string;
      reportId?: string;
      templateId?: string;
      policyId?: string;
      groupId?: string;
      score?: number;
      [key: string]: any;
    }
  ): Promise<void> {
    try {
      await this.prisma.authEvent.create({
        data: {
          userId: data.userId || null,
          eventType,
          eventData: data.metadata || {},
          ipAddress: data.ipAddress,
          userAgent: data.userAgent,
          success: data.success,
          errorMessage: data.errorMessage,
        },
      });
    } catch (error) {
      // Don't fail the request if audit logging fails
      logger.error('Audit logging failed', { error, eventType, data });
    }
  }

  /**
   * EN: Log event from request
   * VI: Ghi log sự kiện từ request
   */
  async logFromRequest(
    req: Request,
    eventType: string,
    data: {
      userId?: string;
      success: boolean;
      errorMessage?: string;
      metadata?: any;
      // EN: Additional fields for specific event types
      // VI: Các trường bổ sung cho các loại sự kiện cụ thể
      requestId?: string;
      reviewId?: string;
      itemId?: string;
      reportId?: string;
      templateId?: string;
      policyId?: string;
      groupId?: string;
      score?: number;
      [key: string]: any;
    }
  ): Promise<void> {
    await this.logAuthEvent(eventType, {
      ...data,
      ipAddress: req.ip || req.socket.remoteAddress || undefined,
      userAgent: req.headers['user-agent'] || undefined,
    });
  }

  /**
   * EN: Get audit events for user
   * VI: Lấy audit events cho người dùng
   */
  async getUserEvents(
    userId: string,
    options?: {
      limit?: number;
      offset?: number;
      eventType?: string;
    }
  ): Promise<any[]> {
    return this.prisma.authEvent.findMany({
      where: {
        userId,
        ...(options?.eventType && { eventType: options.eventType }),
      },
      orderBy: { timestamp: 'desc' },
      take: options?.limit || 100,
      skip: options?.offset || 0,
    });
  }
}

export const auditService = new AuditService();
