"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("@nestjs/testing");
const typeorm_1 = require("@nestjs/typeorm");
const common_1 = require("@nestjs/common");
const superadmin_service_1 = require("../superadmin.service");
const tenant_entity_1 = require("../../tenants/entities/tenant.entity");
const user_entity_1 = require("../../auth/entities/user.entity");
const subscription_entity_1 = require("../../billing/entities/subscription.entity");
describe('SuperadminService', () => {
    let service;
    let tenantRepository;
    let userRepository;
    let subscriptionRepository;
    const mockTenant = {
        id: 'tenant-123',
        name: 'Test Company',
        slug: 'test-company',
        domain: 'test.example.com',
        logo_url: 'https://example.com/logo.png',
        status: 'active',
        plan_id: 'plan-123',
        trial_ends_at: new Date('2026-02-01'),
        settings: { theme: 'dark' },
        metadata: {},
        created_at: new Date('2026-01-01'),
        updated_at: new Date('2026-01-01'),
    };
    const mockUser = {
        id: 'user-123',
        tenant_id: 'tenant-123',
        email: 'test@example.com',
        first_name: 'John',
        last_name: 'Doe',
        status: 'active',
        created_at: new Date('2026-01-01'),
        updated_at: new Date('2026-01-01'),
    };
    const mockSubscription = {
        id: 'sub-123',
        tenant_id: 'tenant-123',
        plan_id: 'plan-123',
        status: 'active',
        created_at: new Date('2026-01-01'),
        updated_at: new Date('2026-01-01'),
    };
    const mockQueryBuilder = {
        where: jest.fn().mockReturnThis(),
        andWhere: jest.fn().mockReturnThis(),
        leftJoinAndSelect: jest.fn().mockReturnThis(),
        getCount: jest.fn().mockResolvedValue(5),
        getMany: jest.fn().mockResolvedValue([]),
    };
    beforeEach(async () => {
        const module = await testing_1.Test.createTestingModule({
            providers: [
                superadmin_service_1.SuperadminService,
                {
                    provide: (0, typeorm_1.getRepositoryToken)(tenant_entity_1.Tenant),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        findAndCount: jest.fn(),
                        save: jest.fn(),
                        create: jest.fn(),
                        remove: jest.fn(),
                        count: jest.fn(),
                        createQueryBuilder: jest.fn().mockReturnValue(mockQueryBuilder),
                    },
                },
                {
                    provide: (0, typeorm_1.getRepositoryToken)(user_entity_1.User),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        findAndCount: jest.fn(),
                        count: jest.fn(),
                        createQueryBuilder: jest.fn().mockReturnValue(mockQueryBuilder),
                    },
                },
                {
                    provide: (0, typeorm_1.getRepositoryToken)(subscription_entity_1.Subscription),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        createQueryBuilder: jest.fn().mockReturnValue(mockQueryBuilder),
                    },
                },
            ],
        }).compile();
        service = module.get(superadmin_service_1.SuperadminService);
        tenantRepository = module.get((0, typeorm_1.getRepositoryToken)(tenant_entity_1.Tenant));
        userRepository = module.get((0, typeorm_1.getRepositoryToken)(user_entity_1.User));
        subscriptionRepository = module.get((0, typeorm_1.getRepositoryToken)(subscription_entity_1.Subscription));
    });
    afterEach(() => {
        jest.clearAllMocks();
    });
    describe('listTenants', () => {
        it('should return paginated tenants with stats', async () => {
            tenantRepository.findAndCount.mockResolvedValue([[mockTenant], 1]);
            userRepository.count.mockResolvedValue(5);
            subscriptionRepository.findOne.mockResolvedValue(mockSubscription);
            const result = await service.listTenants({ page: 1, limit: 10 });
            expect(result.data).toHaveLength(1);
            expect(result.total).toBe(1);
            expect(result.page).toBe(1);
            expect(result.limit).toBe(10);
            expect(result.totalPages).toBe(1);
            expect(result.data[0].userCount).toBe(5);
        });
        it('should handle search parameter', async () => {
            tenantRepository.findAndCount.mockResolvedValue([[], 0]);
            await service.listTenants({ page: 1, limit: 10, search: 'test' });
            expect(tenantRepository.findAndCount).toHaveBeenCalledWith(expect.objectContaining({
                where: expect.objectContaining({
                    name: expect.anything(),
                }),
            }));
        });
        it('should handle status filter', async () => {
            tenantRepository.findAndCount.mockResolvedValue([[], 0]);
            await service.listTenants({ page: 1, limit: 10, status: 'active' });
            expect(tenantRepository.findAndCount).toHaveBeenCalledWith(expect.objectContaining({
                where: expect.objectContaining({
                    status: 'active',
                }),
            }));
        });
    });
    describe('getTenant', () => {
        it('should return tenant with stats', async () => {
            tenantRepository.findOne.mockResolvedValue(mockTenant);
            userRepository.count.mockResolvedValue(5);
            subscriptionRepository.findOne.mockResolvedValue(mockSubscription);
            const result = await service.getTenant('tenant-123');
            expect(result.id).toBe('tenant-123');
            expect(result.userCount).toBe(5);
            expect(result.subscription).toBeDefined();
        });
        it('should throw NotFoundException if tenant not found', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            await expect(service.getTenant('non-existent')).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('createTenant', () => {
        const createDto = {
            name: 'New Company',
            slug: 'new-company',
            domain: 'new.example.com',
            status: 'trial',
        };
        it('should create a new tenant', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            tenantRepository.create.mockReturnValue({ ...mockTenant, ...createDto });
            tenantRepository.save.mockResolvedValue({ ...mockTenant, ...createDto });
            const result = await service.createTenant(createDto);
            expect(result.name).toBe('New Company');
            expect(tenantRepository.create).toHaveBeenCalled();
            expect(tenantRepository.save).toHaveBeenCalled();
        });
        it('should throw ConflictException if slug exists', async () => {
            tenantRepository.findOne.mockResolvedValue(mockTenant);
            await expect(service.createTenant(createDto)).rejects.toThrow(common_1.ConflictException);
        });
    });
    describe('updateTenant', () => {
        const updateDto = { name: 'Updated Company' };
        it('should update a tenant', async () => {
            const tenantCopy = { ...mockTenant };
            tenantRepository.findOne.mockResolvedValue(tenantCopy);
            tenantRepository.save.mockResolvedValue({ ...tenantCopy, ...updateDto });
            const result = await service.updateTenant('tenant-123', updateDto);
            expect(result.name).toBe('Updated Company');
            expect(tenantRepository.save).toHaveBeenCalled();
        });
        it('should throw NotFoundException if tenant not found', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            await expect(service.updateTenant('non-existent', updateDto)).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('updateTenantStatus', () => {
        it('should update tenant status', async () => {
            const tenantCopy = { ...mockTenant };
            tenantRepository.findOne.mockResolvedValue(tenantCopy);
            tenantRepository.save.mockResolvedValue({ ...tenantCopy, status: 'suspended' });
            const result = await service.updateTenantStatus('tenant-123', {
                status: 'suspended',
                reason: 'Non-payment',
            });
            expect(tenantRepository.save).toHaveBeenCalled();
        });
        it('should throw NotFoundException if tenant not found', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            await expect(service.updateTenantStatus('non-existent', { status: 'suspended' })).rejects.toThrow(common_1.NotFoundException);
        });
        it('should store reason in metadata', async () => {
            const tenantCopy = { ...mockTenant, metadata: {} };
            tenantRepository.findOne.mockResolvedValue(tenantCopy);
            tenantRepository.save.mockImplementation(async (t) => t);
            await service.updateTenantStatus('tenant-123', {
                status: 'suspended',
                reason: 'Policy violation',
            });
            const savedTenant = tenantRepository.save.mock.calls[0][0];
            expect(savedTenant.metadata?.statusChangeReason).toBe('Policy violation');
        });
    });
    describe('deleteTenant', () => {
        it('should delete a tenant without users', async () => {
            tenantRepository.findOne.mockResolvedValue(mockTenant);
            userRepository.count.mockResolvedValue(0);
            tenantRepository.remove.mockResolvedValue(mockTenant);
            await service.deleteTenant('tenant-123');
            expect(tenantRepository.remove).toHaveBeenCalledWith(mockTenant);
        });
        it('should throw NotFoundException if tenant not found', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            await expect(service.deleteTenant('non-existent')).rejects.toThrow(common_1.NotFoundException);
        });
        it('should throw BadRequestException if tenant has users', async () => {
            tenantRepository.findOne.mockResolvedValue(mockTenant);
            userRepository.count.mockResolvedValue(5);
            await expect(service.deleteTenant('tenant-123')).rejects.toThrow(common_1.BadRequestException);
        });
    });
    describe('getTenantUsers', () => {
        it('should return paginated users for a tenant', async () => {
            tenantRepository.findOne.mockResolvedValue(mockTenant);
            userRepository.findAndCount.mockResolvedValue([[mockUser], 1]);
            const result = await service.getTenantUsers('tenant-123', 1, 10);
            expect(result.data).toHaveLength(1);
            expect(result.total).toBe(1);
            expect(result.page).toBe(1);
        });
        it('should throw NotFoundException if tenant not found', async () => {
            tenantRepository.findOne.mockResolvedValue(null);
            await expect(service.getTenantUsers('non-existent')).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('getDashboardStats', () => {
        it('should return dashboard statistics', async () => {
            tenantRepository.count
                .mockResolvedValueOnce(100)
                .mockResolvedValueOnce(80)
                .mockResolvedValueOnce(15)
                .mockResolvedValueOnce(5);
            userRepository.count.mockResolvedValue(500);
            mockQueryBuilder.getCount.mockResolvedValue(10);
            const result = await service.getDashboardStats();
            expect(result.totalTenants).toBe(100);
            expect(result.activeTenants).toBe(80);
            expect(result.trialTenants).toBe(15);
            expect(result.suspendedTenants).toBe(5);
            expect(result.totalUsers).toBe(500);
            expect(result.newTenantsThisMonth).toBe(10);
        });
    });
    describe('getStatusDistribution', () => {
        it('should return status distribution', async () => {
            tenantRepository.count
                .mockResolvedValueOnce(100)
                .mockResolvedValueOnce(60)
                .mockResolvedValueOnce(20)
                .mockResolvedValueOnce(15)
                .mockResolvedValueOnce(5);
            const result = await service.getStatusDistribution();
            expect(result).toHaveLength(4);
            expect(result.find(s => s.status === 'Active')?.count).toBe(60);
        });
        it('should calculate percentages correctly', async () => {
            tenantRepository.count
                .mockResolvedValueOnce(100)
                .mockResolvedValueOnce(50)
                .mockResolvedValueOnce(30)
                .mockResolvedValueOnce(15)
                .mockResolvedValueOnce(5);
            const result = await service.getStatusDistribution();
            expect(result.find(s => s.status === 'Active')?.percentage).toBe(50);
            expect(result.find(s => s.status === 'Trial')?.percentage).toBe(30);
        });
    });
    describe('getTenantGrowth', () => {
        it('should return growth data for specified months', async () => {
            mockQueryBuilder.getCount.mockResolvedValue(10);
            const result = await service.getTenantGrowth(6);
            expect(result).toHaveLength(6);
            expect(result[0]).toHaveProperty('month');
            expect(result[0]).toHaveProperty('count');
        });
    });
    describe('getUserGrowth', () => {
        it('should return user growth data', async () => {
            mockQueryBuilder.getCount.mockResolvedValue(20);
            const result = await service.getUserGrowth(3);
            expect(result).toHaveLength(3);
            expect(result[0]).toHaveProperty('month');
            expect(result[0]).toHaveProperty('count');
        });
    });
});
//# sourceMappingURL=superadmin.service.spec.js.map