import { Test, TestingModule } from '@nestjs/testing';
import { OnlineSessionService } from './online-session.service';
import { OnlineSessionProviderRegistry } from './online-session-provider.registry';
import { OnlineSessionRepository } from '../repositories/online-session.repository';
import { AppLoggerService } from 'src/common/services/logger.service';
import { JoinLinkSchedulerService } from 'src/join-link-scheduler/join-link-scheduler.service';
import { ProgramRepository } from 'src/program/program.repository';
import { FeatureFlagService } from 'src/feature-flag/feature-flag.service';
import { FEATURE_FLAG_KEYS } from 'src/common/constants/constants';

describe('OnlineSessionService — report feature flags', () => {
  let service: OnlineSessionService;
  const mockRegistry = { resolve: jest.fn() };
  const mockRepository = { findById: jest.fn() };
  const mockLogger = { log: jest.fn(), error: jest.fn() };
  const mockLinkScheduler = {};
  const mockProgramRepository = { findOneById: jest.fn() };
  const mockFeatureFlagService = { isFeatureEnabledForProgramType: jest.fn() };

  beforeEach(async () => {
    jest.clearAllMocks();

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        OnlineSessionService,
        { provide: OnlineSessionProviderRegistry, useValue: mockRegistry },
        { provide: OnlineSessionRepository, useValue: mockRepository },
        { provide: AppLoggerService, useValue: mockLogger },
        { provide: JoinLinkSchedulerService, useValue: mockLinkScheduler },
        { provide: ProgramRepository, useValue: mockProgramRepository },
        { provide: FeatureFlagService, useValue: mockFeatureFlagService },
      ],
    }).compile();

    service = module.get<OnlineSessionService>(OnlineSessionService);
  });

  describe('isEligibleRegistrationsReportEnabled', () => {
    it('resolves the program then checks ENABLE_ELIGIBLE_REGISTRATIONS_REPORT for its type', async () => {
      mockProgramRepository.findOneById.mockResolvedValue({ id: 1, typeId: 7 });
      mockFeatureFlagService.isFeatureEnabledForProgramType.mockResolvedValue(true);

      const result = await service.isEligibleRegistrationsReportEnabled(1);

      expect(result).toBe(true);
      expect(mockFeatureFlagService.isFeatureEnabledForProgramType).toHaveBeenCalledWith(
        FEATURE_FLAG_KEYS.ENABLE_ELIGIBLE_REGISTRATIONS_REPORT, 7,
      );
    });

    it('returns false without checking any flag when the program does not exist', async () => {
      mockProgramRepository.findOneById.mockResolvedValue(null);

      const result = await service.isEligibleRegistrationsReportEnabled(999);

      expect(result).toBe(false);
      expect(mockFeatureFlagService.isFeatureEnabledForProgramType).not.toHaveBeenCalled();
    });
  });

  describe('isZoomLinksReportEnabledForSession', () => {
    it('resolves the session -> its programId -> program type, then checks ENABLE_ZOOM_LINKS_REPORT', async () => {
      mockRepository.findById.mockResolvedValue({ id: 66, programId: 45 });
      mockProgramRepository.findOneById.mockResolvedValue({ id: 45, typeId: 7 });
      mockFeatureFlagService.isFeatureEnabledForProgramType.mockResolvedValue(false);

      const result = await service.isZoomLinksReportEnabledForSession(66);

      expect(result).toBe(false);
      expect(mockProgramRepository.findOneById).toHaveBeenCalledWith(45);
      expect(mockFeatureFlagService.isFeatureEnabledForProgramType).toHaveBeenCalledWith(
        FEATURE_FLAG_KEYS.ENABLE_ZOOM_LINKS_REPORT, 7,
      );
    });

    it('returns false without resolving the program when the session does not exist', async () => {
      mockRepository.findById.mockResolvedValue(null);

      const result = await service.isZoomLinksReportEnabledForSession(999);

      expect(result).toBe(false);
      expect(mockProgramRepository.findOneById).not.toHaveBeenCalled();
    });
  });

  describe('isSessionReportEnabled', () => {
    it('checks the ENABLE_SINGLE_SESSION_REPORT umbrella for the program\'s type', async () => {
      mockProgramRepository.findOneById.mockResolvedValue({ id: 45, typeId: 7 });
      mockFeatureFlagService.isFeatureEnabledForProgramType.mockResolvedValue(true);

      const result = await service.isSessionReportEnabled(45);

      expect(result).toBe(true);
      expect(mockFeatureFlagService.isFeatureEnabledForProgramType).toHaveBeenCalledWith(
        FEATURE_FLAG_KEYS.ENABLE_SINGLE_SESSION_REPORT, 7,
      );
    });
  });
});
