import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { CommunicationMergeDataService } from './communication-merge-data.service';
import { SESSION_GUIDELINES_PDF_SERVICE } from './session-guidelines-pdf.types';
import { CommunicationTemplatesRepository } from '../repositories/communication-templates.repository';
import { MergeInfoAnswerLocationMap } from 'src/common/entities';
import { CommunicationTemplateAccessKeyEnum } from 'src/common/enum/communication-template-access-key.enum';
import { CommunicationTypeEnum } from 'src/common/enum/communication-type.enum';

describe('CommunicationMergeDataService — rev 11 native send gate (attached_steps)', () => {
  let service: CommunicationMergeDataService;
  let templatesRepo: {
    findByProgramAndAccessKey: jest.Mock;
    getTemplateIdBasedOnEnvironment: jest.Mock;
  };
  let mergeInfoRepo: { find: jest.Mock };

  const accessKey = Object.values(CommunicationTemplateAccessKeyEnum)[0] as CommunicationTemplateAccessKeyEnum;

  const clone = (over: Record<string, any> = {}) => ({
    id: 1,
    templateId: 'tpl-1',
    templateKey: 'KEY',
    templateType: CommunicationTypeEnum.EMAIL,
    step: 'BLESSED',
    masterTemplateId: 17,
    attachedSteps: ['BLESSED'],
    ...over,
  });

  beforeEach(async () => {
    templatesRepo = {
      findByProgramAndAccessKey: jest.fn(),
      getTemplateIdBasedOnEnvironment: jest.fn().mockReturnValue('tpl-1'),
    };
    mergeInfoRepo = { find: jest.fn().mockResolvedValue([]) };

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        CommunicationMergeDataService,
        { provide: CommunicationTemplatesRepository, useValue: templatesRepo },
        { provide: getRepositoryToken(MergeInfoAnswerLocationMap), useValue: mergeInfoRepo },
        { provide: DataSource, useValue: { manager: {} } },
        {
          provide: SESSION_GUIDELINES_PDF_SERVICE,
          useValue: { resolveProgramPdfUrl: jest.fn(), resolveSessionPdfUrl: jest.fn() },
        },
      ],
    }).compile();

    service = module.get(CommunicationMergeDataService);
  });

  it('skips (null) when the native step is missing from attached_steps', async () => {
    templatesRepo.findByProgramAndAccessKey.mockResolvedValue(
      clone({ attachedSteps: ['INVOICE'] }), // attached only as cross-step elsewhere
    );

    const result = await service.getTemplateWithMergeInfo(100, accessKey, CommunicationTypeEnum.EMAIL);

    expect(result).toBeNull();
    expect(mergeInfoRepo.find).not.toHaveBeenCalled();
  });

  it('fires when the native step is present in attached_steps', async () => {
    templatesRepo.findByProgramAndAccessKey.mockResolvedValue(
      clone({ attachedSteps: ['BLESSED', 'REGISTRATION_COMPLETED'] }),
    );

    const result = await service.getTemplateWithMergeInfo(100, accessKey, CommunicationTypeEnum.EMAIL);

    expect(result).not.toBeNull();
    expect(mergeInfoRepo.find).toHaveBeenCalled();
  });

  it('skips when attached_steps is empty', async () => {
    templatesRepo.findByProgramAndAccessKey.mockResolvedValue(
      clone({ attachedSteps: [] }),
    );

    const result = await service.getTemplateWithMergeInfo(100, accessKey, CommunicationTypeEnum.EMAIL);

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

  it('allows legacy clones with no master/step mapping (back-compat)', async () => {
    templatesRepo.findByProgramAndAccessKey.mockResolvedValue(
      clone({ masterTemplateId: null, step: null, attachedSteps: [] }),
    );

    const result = await service.getTemplateWithMergeInfo(100, accessKey, CommunicationTypeEnum.EMAIL);

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