import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { FeatureFlagRepository } from './feature-flag.repository';
import { FeatureFlag } from 'src/common/entities';
import { CommonDataService } from 'src/common/services/commonData.service';
import { AppLoggerService } from 'src/common/services/logger.service';
import { CommonStatus } from 'src/common/enum/common-status.enum';

describe('FeatureFlagRepository', () => {
  let repository: FeatureFlagRepository;
  const mockTypeOrmRepo = { findOne: jest.fn() };
  const mockCommonDataService = { get: jest.fn() };
  const mockLogger = { log: jest.fn(), error: jest.fn() };

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

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        FeatureFlagRepository,
        { provide: getRepositoryToken(FeatureFlag), useValue: mockTypeOrmRepo },
        { provide: CommonDataService, useValue: mockCommonDataService },
        { provide: AppLoggerService, useValue: mockLogger },
      ],
    }).compile();

    repository = module.get<FeatureFlagRepository>(FeatureFlagRepository);
  });

  describe('findFlagForProgramType', () => {
    it('returns the program-type-scoped row without checking the global row when one exists', async () => {
      const scopedFlag = { key: 'enableZoomLinksReport', programTypeId: 5, flag: true } as FeatureFlag;
      mockTypeOrmRepo.findOne.mockResolvedValueOnce(scopedFlag);

      const result = await repository.findFlagForProgramType('enableZoomLinksReport', 5);

      expect(result).toBe(scopedFlag);
      expect(mockTypeOrmRepo.findOne).toHaveBeenCalledTimes(1);
      expect(mockTypeOrmRepo.findOne).toHaveBeenCalledWith({
        where: { key: 'enableZoomLinksReport', programTypeId: 5, status: CommonStatus.ACTIVE, deletedAt: expect.anything() },
      });
    });

    it('falls back to the global (programTypeId IS NULL) row when no program-type-scoped row exists', async () => {
      const globalFlag = { key: 'enableZoomLinksReport', programTypeId: null, flag: false } as FeatureFlag;
      mockTypeOrmRepo.findOne
        .mockResolvedValueOnce(null)
        .mockResolvedValueOnce(globalFlag);

      const result = await repository.findFlagForProgramType('enableZoomLinksReport', 5);

      expect(result).toBe(globalFlag);
      expect(mockTypeOrmRepo.findOne).toHaveBeenCalledTimes(2);
    });

    it('returns null when neither a program-type-scoped nor a global row exists', async () => {
      mockTypeOrmRepo.findOne.mockResolvedValue(null);

      const result = await repository.findFlagForProgramType('unknownKey', 5);

      expect(result).toBeNull();
    });
  });
});
