"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("@nestjs/testing");
const typeorm_1 = require("@nestjs/typeorm");
const audit_service_1 = require("../services/audit.service");
const audit_log_entity_1 = require("../entities/audit-log.entity");
const activity_log_entity_1 = require("../entities/activity-log.entity");
describe('AuditService', () => {
    let service;
    let auditLogRepo;
    let activityLogRepo;
    const mockTenantId = '550e8400-e29b-41d4-a716-446655440001';
    const mockUserId = '550e8400-e29b-41d4-a716-446655440002';
    const mockAuditLog = {
        id: 'audit-001',
        tenant_id: mockTenantId,
        user_id: mockUserId,
        action: audit_log_entity_1.AuditAction.CREATE,
        entity_type: 'user',
        entity_id: 'user-001',
        new_values: { email: 'test@example.com' },
        changed_fields: ['email'],
        ip_address: '192.168.1.1',
        created_at: new Date(),
    };
    const mockActivityLog = {
        id: 'activity-001',
        tenant_id: mockTenantId,
        user_id: mockUserId,
        activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW,
        resource_type: 'dashboard',
        description: 'Viewed dashboard',
        ip_address: '192.168.1.1',
        created_at: new Date(),
    };
    beforeEach(async () => {
        const mockAuditLogRepo = {
            create: jest.fn(),
            save: jest.fn(),
            findOne: jest.fn(),
            find: jest.fn(),
            count: jest.fn(),
            createQueryBuilder: jest.fn(),
        };
        const mockActivityLogRepo = {
            create: jest.fn(),
            save: jest.fn(),
            findOne: jest.fn(),
            find: jest.fn(),
            createQueryBuilder: jest.fn(),
        };
        const module = await testing_1.Test.createTestingModule({
            providers: [
                audit_service_1.AuditService,
                { provide: (0, typeorm_1.getRepositoryToken)(audit_log_entity_1.AuditLog), useValue: mockAuditLogRepo },
                { provide: (0, typeorm_1.getRepositoryToken)(activity_log_entity_1.ActivityLog), useValue: mockActivityLogRepo },
            ],
        }).compile();
        service = module.get(audit_service_1.AuditService);
        auditLogRepo = module.get((0, typeorm_1.getRepositoryToken)(audit_log_entity_1.AuditLog));
        activityLogRepo = module.get((0, typeorm_1.getRepositoryToken)(activity_log_entity_1.ActivityLog));
    });
    afterEach(() => {
        jest.clearAllMocks();
    });
    describe('createAuditLog', () => {
        it('should create audit log successfully', async () => {
            auditLogRepo.create.mockReturnValue(mockAuditLog);
            auditLogRepo.save.mockResolvedValue(mockAuditLog);
            const result = await service.createAuditLog({
                tenant_id: mockTenantId,
                user_id: mockUserId,
                action: audit_log_entity_1.AuditAction.CREATE,
                entity_type: 'user',
                entity_id: 'user-001',
                new_values: { email: 'test@example.com' },
            });
            expect(result).toEqual(mockAuditLog);
            expect(auditLogRepo.create).toHaveBeenCalled();
            expect(auditLogRepo.save).toHaveBeenCalled();
        });
        it('should detect changed fields', async () => {
            auditLogRepo.create.mockReturnValue(mockAuditLog);
            auditLogRepo.save.mockResolvedValue(mockAuditLog);
            await service.createAuditLog({
                tenant_id: mockTenantId,
                user_id: mockUserId,
                action: audit_log_entity_1.AuditAction.UPDATE,
                entity_type: 'user',
                entity_id: 'user-001',
                old_values: { email: 'old@example.com', name: 'Old Name' },
                new_values: { email: 'new@example.com', name: 'Old Name' },
            });
            expect(auditLogRepo.create).toHaveBeenCalledWith(expect.objectContaining({
                changed_fields: ['email'],
            }));
        });
        it('should handle null old/new values', async () => {
            auditLogRepo.create.mockReturnValue(mockAuditLog);
            auditLogRepo.save.mockResolvedValue(mockAuditLog);
            await service.createAuditLog({
                tenant_id: mockTenantId,
                action: audit_log_entity_1.AuditAction.DELETE,
                entity_type: 'user',
                entity_id: 'user-001',
            });
            expect(auditLogRepo.create).toHaveBeenCalledWith(expect.objectContaining({
                changed_fields: [],
            }));
        });
        it('should include request metadata', async () => {
            auditLogRepo.create.mockReturnValue(mockAuditLog);
            auditLogRepo.save.mockResolvedValue(mockAuditLog);
            await service.createAuditLog({
                tenant_id: mockTenantId,
                user_id: mockUserId,
                action: audit_log_entity_1.AuditAction.READ,
                entity_type: 'document',
                ip_address: '192.168.1.1',
                user_agent: 'Mozilla/5.0',
                endpoint: '/api/documents/1',
                http_method: 'GET',
                response_status: 200,
                duration_ms: 150,
            });
            expect(auditLogRepo.create).toHaveBeenCalledWith(expect.objectContaining({
                ip_address: '192.168.1.1',
                endpoint: '/api/documents/1',
                duration_ms: 150,
            }));
        });
    });
    describe('queryAuditLogs', () => {
        it('should return paginated audit logs', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[mockAuditLog], 1]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            const result = await service.queryAuditLogs(mockTenantId, {});
            expect(result.data).toHaveLength(1);
            expect(result.total).toBe(1);
            expect(result.page).toBe(1);
            expect(result.limit).toBe(20);
        });
        it('should filter by user_id', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.queryAuditLogs(mockTenantId, { user_id: mockUserId });
            expect(qb.andWhere).toHaveBeenCalledWith('audit.user_id = :user_id', {
                user_id: mockUserId,
            });
        });
        it('should filter by action', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.queryAuditLogs(mockTenantId, { action: audit_log_entity_1.AuditAction.CREATE });
            expect(qb.andWhere).toHaveBeenCalledWith('audit.action = :action', {
                action: audit_log_entity_1.AuditAction.CREATE,
            });
        });
        it('should filter by entity_type', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.queryAuditLogs(mockTenantId, { entity_type: 'user' });
            expect(qb.andWhere).toHaveBeenCalledWith('audit.entity_type = :entity_type', {
                entity_type: 'user',
            });
        });
        it('should filter by date range', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            const from_date = '2026-01-01';
            const to_date = '2026-01-31';
            await service.queryAuditLogs(mockTenantId, { from_date, to_date });
            expect(qb.andWhere).toHaveBeenCalledWith('audit.created_at BETWEEN :from_date AND :to_date', { from_date, to_date });
        });
        it('should handle pagination correctly', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 100]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            const result = await service.queryAuditLogs(mockTenantId, {
                page: 3,
                limit: 10,
            });
            expect(qb.skip).toHaveBeenCalledWith(20);
            expect(qb.take).toHaveBeenCalledWith(10);
            expect(result.totalPages).toBe(10);
        });
    });
    describe('getAuditLogById', () => {
        it('should return audit log by id', async () => {
            auditLogRepo.findOne.mockResolvedValue(mockAuditLog);
            const result = await service.getAuditLogById(mockTenantId, 'audit-001');
            expect(result).toEqual(mockAuditLog);
            expect(auditLogRepo.findOne).toHaveBeenCalledWith({
                where: { id: 'audit-001', tenant_id: mockTenantId },
            });
        });
        it('should return null when not found', async () => {
            auditLogRepo.findOne.mockResolvedValue(null);
            const result = await service.getAuditLogById(mockTenantId, 'invalid');
            expect(result).toBeNull();
        });
    });
    describe('getEntityAuditHistory', () => {
        it('should return audit history for entity', async () => {
            auditLogRepo.find.mockResolvedValue([mockAuditLog]);
            const result = await service.getEntityAuditHistory(mockTenantId, 'user', 'user-001');
            expect(result).toHaveLength(1);
            expect(auditLogRepo.find).toHaveBeenCalledWith({
                where: {
                    tenant_id: mockTenantId,
                    entity_type: 'user',
                    entity_id: 'user-001',
                },
                order: { created_at: 'DESC' },
            });
        });
        it('should return empty array for no history', async () => {
            auditLogRepo.find.mockResolvedValue([]);
            const result = await service.getEntityAuditHistory(mockTenantId, 'document', 'doc-999');
            expect(result).toHaveLength(0);
        });
    });
    describe('createActivityLog', () => {
        it('should create activity log successfully', async () => {
            activityLogRepo.create.mockReturnValue(mockActivityLog);
            activityLogRepo.save.mockResolvedValue(mockActivityLog);
            const result = await service.createActivityLog(mockTenantId, mockUserId, {
                activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW,
                resource_type: 'dashboard',
                description: 'Viewed dashboard',
            }, { ip_address: '192.168.1.1' });
            expect(result).toEqual(mockActivityLog);
            expect(activityLogRepo.create).toHaveBeenCalled();
        });
        it('should include session context', async () => {
            activityLogRepo.create.mockReturnValue(mockActivityLog);
            activityLogRepo.save.mockResolvedValue(mockActivityLog);
            await service.createActivityLog(mockTenantId, mockUserId, {
                activity_type: activity_log_entity_1.ActivityType.FEATURE_USE,
                description: 'Used export feature',
            }, {
                ip_address: '192.168.1.1',
                user_agent: 'Mozilla/5.0',
                session_id: 'session-001',
            });
            expect(activityLogRepo.create).toHaveBeenCalledWith(expect.objectContaining({
                session_id: 'session-001',
            }));
        });
    });
    describe('queryActivityLogs', () => {
        it('should return paginated activity logs', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest
                    .fn()
                    .mockResolvedValue([[mockActivityLog], 1]),
            };
            activityLogRepo.createQueryBuilder.mockReturnValue(qb);
            const result = await service.queryActivityLogs(mockTenantId, {});
            expect(result.data).toHaveLength(1);
            expect(result.total).toBe(1);
        });
        it('should filter by activity_type', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            activityLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.queryActivityLogs(mockTenantId, {
                activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW,
            });
            expect(qb.andWhere).toHaveBeenCalledWith('activity.activity_type = :activity_type', { activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW });
        });
        it('should filter by resource_type', async () => {
            const qb = {
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                skip: jest.fn().mockReturnThis(),
                take: jest.fn().mockReturnThis(),
                getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
            };
            activityLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.queryActivityLogs(mockTenantId, { resource_type: 'document' });
            expect(qb.andWhere).toHaveBeenCalledWith('activity.resource_type = :resource_type', { resource_type: 'document' });
        });
    });
    describe('getUserActivitySummary', () => {
        it('should return activity summary by type', async () => {
            const qb = {
                select: jest.fn().mockReturnThis(),
                addSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                getRawMany: jest.fn().mockResolvedValue([
                    { activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW, count: '50' },
                    { activity_type: activity_log_entity_1.ActivityType.FEATURE_USE, count: '25' },
                ]),
            };
            activityLogRepo.createQueryBuilder.mockReturnValue(qb);
            const result = await service.getUserActivitySummary(mockTenantId, mockUserId, 30);
            expect(result).toHaveLength(2);
            expect(result[0]).toEqual({
                activity_type: activity_log_entity_1.ActivityType.PAGE_VIEW,
                count: 50,
            });
        });
        it('should use default 30 days', async () => {
            const qb = {
                select: jest.fn().mockReturnThis(),
                addSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                getRawMany: jest.fn().mockResolvedValue([]),
            };
            activityLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.getUserActivitySummary(mockTenantId, mockUserId);
            expect(qb.andWhere).toHaveBeenCalledWith('activity.created_at >= :fromDate', expect.any(Object));
        });
    });
    describe('getAuditStats', () => {
        it('should return audit statistics', async () => {
            auditLogRepo.count.mockResolvedValue(100);
            const actionsByTypeQb = {
                select: jest.fn().mockReturnThis(),
                addSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                getRawMany: jest.fn().mockResolvedValue([
                    { action: audit_log_entity_1.AuditAction.CREATE, count: '30' },
                    { action: audit_log_entity_1.AuditAction.UPDATE, count: '50' },
                    { action: audit_log_entity_1.AuditAction.DELETE, count: '20' },
                ]),
            };
            const topUsersQb = {
                select: jest.fn().mockReturnThis(),
                addSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                limit: jest.fn().mockReturnThis(),
                getRawMany: jest.fn().mockResolvedValue([
                    { user_id: mockUserId, count: '45' },
                    { user_id: 'user-002', count: '30' },
                ]),
            };
            auditLogRepo.createQueryBuilder
                .mockReturnValueOnce(actionsByTypeQb)
                .mockReturnValueOnce(topUsersQb);
            const result = await service.getAuditStats(mockTenantId, 7);
            expect(result.total_actions).toBe(100);
            expect(result.actions_by_type).toHaveLength(3);
            expect(result.top_users).toHaveLength(2);
        });
        it('should use default 7 days', async () => {
            auditLogRepo.count.mockResolvedValue(0);
            const qb = {
                select: jest.fn().mockReturnThis(),
                addSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                andWhere: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                orderBy: jest.fn().mockReturnThis(),
                limit: jest.fn().mockReturnThis(),
                getRawMany: jest.fn().mockResolvedValue([]),
            };
            auditLogRepo.createQueryBuilder.mockReturnValue(qb);
            await service.getAuditStats(mockTenantId);
            expect(auditLogRepo.count).toHaveBeenCalled();
        });
    });
});
//# sourceMappingURL=audit.service.spec.js.map