import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';

interface AuditLogFilter {
    page: number;
    limit: number;
    entityType?: string;
    action?: string;
}

@Injectable()
export class AuditService {
    constructor(private prisma: PrismaService) { }

    /**
     * Record an audit log entry
     */
    async log(data: {
        userId: string;
        userName: string;
        entityType: string;
        entityId: string;
        action: string;
        changes?: Record<string, unknown>;
        ipAddress?: string;
    }) {
        return this.prisma.$executeRaw`
            INSERT INTO audit_logs (id, user_id, user_name, entity_type, entity_id, action, changes, ip_address, created_at)
            VALUES (
                gen_random_uuid(),
                ${data.userId}::uuid,
                ${data.userName},
                ${data.entityType},
                ${data.entityId},
                ${data.action},
                ${JSON.stringify(data.changes || {})}::jsonb,
                ${data.ipAddress || null},
                NOW()
            )
        `;
    }

    /**
     * Get audit logs with pagination and filters
     */
    async getLogs(filter: AuditLogFilter) {
        const offset = (filter.page - 1) * filter.limit;

        let whereClause = '';
        const conditions: string[] = [];

        if (filter.entityType) {
            conditions.push(`entity_type = '${filter.entityType}'`);
        }
        if (filter.action) {
            conditions.push(`action = '${filter.action}'`);
        }

        if (conditions.length > 0) {
            whereClause = `WHERE ${conditions.join(' AND ')}`;
        }

        const logs = await this.prisma.$queryRawUnsafe<any[]>(`
            SELECT id, user_id, user_name, entity_type, entity_id, action, changes, ip_address, created_at
            FROM audit_logs
            ${whereClause}
            ORDER BY created_at DESC
            LIMIT ${filter.limit} OFFSET ${offset}
        `);

        const countResult = await this.prisma.$queryRawUnsafe<[{ count: bigint }]>(`
            SELECT COUNT(*) as count FROM audit_logs ${whereClause}
        `);

        return {
            logs,
            total: Number(countResult[0]?.count || 0),
            page: filter.page,
            limit: filter.limit,
        };
    }
}
