"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuditService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const audit_log_entity_1 = require("../entities/audit-log.entity");
const activity_log_entity_1 = require("../entities/activity-log.entity");
let AuditService = class AuditService {
    constructor(auditLogRepository, activityLogRepository) {
        this.auditLogRepository = auditLogRepository;
        this.activityLogRepository = activityLogRepository;
    }
    async createAuditLog(params) {
        const changedFields = this.detectChangedFields(params.old_values, params.new_values);
        const auditLog = this.auditLogRepository.create({
            ...params,
            changed_fields: changedFields,
        });
        return this.auditLogRepository.save(auditLog);
    }
    async queryAuditLogs(tenantId, query) {
        const { user_id, action, entity_type, entity_id, from_date, to_date, page = 1, limit = 20 } = query;
        const queryBuilder = this.auditLogRepository
            .createQueryBuilder('audit')
            .where('audit.tenant_id = :tenantId', { tenantId });
        if (user_id) {
            queryBuilder.andWhere('audit.user_id = :user_id', { user_id });
        }
        if (action) {
            queryBuilder.andWhere('audit.action = :action', { action });
        }
        if (entity_type) {
            queryBuilder.andWhere('audit.entity_type = :entity_type', { entity_type });
        }
        if (entity_id) {
            queryBuilder.andWhere('audit.entity_id = :entity_id', { entity_id });
        }
        if (from_date && to_date) {
            queryBuilder.andWhere('audit.created_at BETWEEN :from_date AND :to_date', {
                from_date,
                to_date,
            });
        }
        else if (from_date) {
            queryBuilder.andWhere('audit.created_at >= :from_date', { from_date });
        }
        else if (to_date) {
            queryBuilder.andWhere('audit.created_at <= :to_date', { to_date });
        }
        queryBuilder
            .orderBy('audit.created_at', 'DESC')
            .skip((page - 1) * limit)
            .take(limit);
        const [data, total] = await queryBuilder.getManyAndCount();
        return {
            data,
            total,
            page,
            limit,
            totalPages: Math.ceil(total / limit),
        };
    }
    async getAuditLogById(tenantId, id) {
        return this.auditLogRepository.findOne({
            where: { id, tenant_id: tenantId },
        });
    }
    async getEntityAuditHistory(tenantId, entityType, entityId) {
        return this.auditLogRepository.find({
            where: {
                tenant_id: tenantId,
                entity_type: entityType,
                entity_id: entityId,
            },
            order: { created_at: 'DESC' },
        });
    }
    async createActivityLog(tenantId, userId, dto, context) {
        const activityLog = this.activityLogRepository.create({
            tenant_id: tenantId,
            user_id: userId,
            ...dto,
            ip_address: context?.ip_address,
            user_agent: context?.user_agent,
            session_id: context?.session_id,
        });
        return this.activityLogRepository.save(activityLog);
    }
    async queryActivityLogs(tenantId, query) {
        const { user_id, activity_type, resource_type, from_date, to_date, page = 1, limit = 20 } = query;
        const queryBuilder = this.activityLogRepository
            .createQueryBuilder('activity')
            .where('activity.tenant_id = :tenantId', { tenantId });
        if (user_id) {
            queryBuilder.andWhere('activity.user_id = :user_id', { user_id });
        }
        if (activity_type) {
            queryBuilder.andWhere('activity.activity_type = :activity_type', { activity_type });
        }
        if (resource_type) {
            queryBuilder.andWhere('activity.resource_type = :resource_type', { resource_type });
        }
        if (from_date && to_date) {
            queryBuilder.andWhere('activity.created_at BETWEEN :from_date AND :to_date', {
                from_date,
                to_date,
            });
        }
        else if (from_date) {
            queryBuilder.andWhere('activity.created_at >= :from_date', { from_date });
        }
        else if (to_date) {
            queryBuilder.andWhere('activity.created_at <= :to_date', { to_date });
        }
        queryBuilder
            .orderBy('activity.created_at', 'DESC')
            .skip((page - 1) * limit)
            .take(limit);
        const [data, total] = await queryBuilder.getManyAndCount();
        return {
            data,
            total,
            page,
            limit,
            totalPages: Math.ceil(total / limit),
        };
    }
    async getUserActivitySummary(tenantId, userId, days = 30) {
        const fromDate = new Date();
        fromDate.setDate(fromDate.getDate() - days);
        const result = await this.activityLogRepository
            .createQueryBuilder('activity')
            .select('activity.activity_type', 'activity_type')
            .addSelect('COUNT(*)', 'count')
            .where('activity.tenant_id = :tenantId', { tenantId })
            .andWhere('activity.user_id = :userId', { userId })
            .andWhere('activity.created_at >= :fromDate', { fromDate })
            .groupBy('activity.activity_type')
            .getRawMany();
        return result.map((r) => ({
            activity_type: r.activity_type,
            count: parseInt(r.count, 10),
        }));
    }
    async getAuditStats(tenantId, days = 7) {
        const fromDate = new Date();
        fromDate.setDate(fromDate.getDate() - days);
        const [totalActions, actionsByType, topUsers] = await Promise.all([
            this.auditLogRepository.count({
                where: {
                    tenant_id: tenantId,
                    created_at: (0, typeorm_2.MoreThanOrEqual)(fromDate),
                },
            }),
            this.auditLogRepository
                .createQueryBuilder('audit')
                .select('audit.action', 'action')
                .addSelect('COUNT(*)', 'count')
                .where('audit.tenant_id = :tenantId', { tenantId })
                .andWhere('audit.created_at >= :fromDate', { fromDate })
                .groupBy('audit.action')
                .getRawMany(),
            this.auditLogRepository
                .createQueryBuilder('audit')
                .select('audit.user_id', 'user_id')
                .addSelect('COUNT(*)', 'count')
                .where('audit.tenant_id = :tenantId', { tenantId })
                .andWhere('audit.created_at >= :fromDate', { fromDate })
                .andWhere('audit.user_id IS NOT NULL')
                .groupBy('audit.user_id')
                .orderBy('count', 'DESC')
                .limit(10)
                .getRawMany(),
        ]);
        return {
            total_actions: totalActions,
            actions_by_type: actionsByType.map((r) => ({
                action: r.action,
                count: parseInt(r.count, 10),
            })),
            top_users: topUsers.map((r) => ({
                user_id: r.user_id,
                count: parseInt(r.count, 10),
            })),
        };
    }
    detectChangedFields(oldValues, newValues) {
        if (!oldValues || !newValues)
            return [];
        const changedFields = [];
        const allKeys = new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
        for (const key of allKeys) {
            if (JSON.stringify(oldValues[key]) !== JSON.stringify(newValues[key])) {
                changedFields.push(key);
            }
        }
        return changedFields;
    }
};
exports.AuditService = AuditService;
exports.AuditService = AuditService = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(audit_log_entity_1.AuditLog)),
    __param(1, (0, typeorm_1.InjectRepository)(activity_log_entity_1.ActivityLog)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository])
], AuditService);
//# sourceMappingURL=audit.service.js.map