import { Test, TestingModule } from '@nestjs/testing';
import { RecordPageViewUseCase } from './RecordPageViewUseCase';
import type { IPageViewRepository } from '@core/analytics/application/repositories/IPageViewRepository';
import type { Logger } from '@core/shared/application';

describe('RecordPageViewUseCase', () => {
  let useCase: RecordPageViewUseCase;
  let pageViewRepository: jest.Mocked<IPageViewRepository>;
  let logger: jest.Mocked<Logger>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        RecordPageViewUseCase,
        {
          provide: 'IPageViewRepository_TOKEN',
          useValue: {
            save: jest.fn(),
          },
        },
        {
          provide: 'Logger_TOKEN',
          useValue: {
            debug: jest.fn(),
            info: jest.fn(),
            error: jest.fn(),
          },
        },
      ],
    }).compile();

    useCase = module.get<RecordPageViewUseCase>(RecordPageViewUseCase);
    pageViewRepository = module.get('IPageViewRepository_TOKEN');
    logger = module.get('Logger_TOKEN');
  });

  describe('execute', () => {
    it('should save the page view and return the pageViewId', async () => {
      const input = {
        entityType: 'race' as any,
        entityId: 'race-123',
        visitorType: 'anonymous' as any,
        sessionId: 'session-456',
        visitorId: 'visitor-789',
        referrer: 'https://example.com',
        userAgent: 'Mozilla/5.0',
        country: 'US',
      };

      pageViewRepository.save.mockResolvedValue(undefined);

      const result = await useCase.execute(input);

      expect(logger.debug).toHaveBeenCalledWith('Executing RecordPageViewUseCase', { input });
      expect(pageViewRepository.save).toHaveBeenCalledTimes(1);
      expect(logger.info).toHaveBeenCalledWith('Page view recorded successfully', expect.objectContaining({ pageViewId: expect.any(String), input }));
      expect(result).toHaveProperty('pageViewId');
      expect(typeof result.pageViewId).toBe('string');
    });

    it('should handle errors and throw them', async () => {
      const input = {
        entityType: 'race' as any,
        entityId: 'race-123',
        visitorType: 'anonymous' as any,
        sessionId: 'session-456',
      };

      const error = new Error('Save failed');
      pageViewRepository.save.mockRejectedValue(error);

      await expect(useCase.execute(input)).rejects.toThrow('Save failed');
      expect(logger.error).toHaveBeenCalledWith('Error recording page view', error, { input });
    });
  });
});