import { GetPrizesPresenter } from './GetPrizesPresenter';
import { GetPrizesResultDTO } from '../dtos/GetPrizesDTO';
import { PrizeType } from '../dtos/PrizeType';

describe('GetPrizesPresenter', () => {
  let presenter: GetPrizesPresenter;

  beforeEach(() => {
    presenter = new GetPrizesPresenter();
  });

  describe('present', () => {
    it('should store the result', () => {
      const result: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      presenter.present(result);

      expect(presenter.getResponseModel()).toEqual(result);
    });

    it('should overwrite previous result', () => {
      const firstResult: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      const secondResult: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-456',
            name: 'Test Prize 2',
            description: 'Test Description 2',
            type: PrizeType.MERCHANDISE,
            amount: 200,
            leagueId: 'league-456',
          },
        ],
      };

      presenter.present(firstResult);
      presenter.present(secondResult);

      expect(presenter.getResponseModel()).toEqual(secondResult);
    });
  });

  describe('getResponseModel', () => {
    it('should return null when not presented', () => {
      expect(presenter.getResponseModel()).toBeNull();
    });

    it('should return the result after present()', () => {
      const result: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      presenter.present(result);

      expect(presenter.getResponseModel()).toEqual(result);
    });
  });

  describe('reset', () => {
    it('should clear the result', () => {
      const result: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      presenter.present(result);
      presenter.reset();

      expect(presenter.getResponseModel()).toBeNull();
    });

    it('should allow presenting again after reset', () => {
      const firstResult: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      const secondResult: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-456',
            name: 'Test Prize 2',
            description: 'Test Description 2',
            type: PrizeType.MERCHANDISE,
            amount: 200,
            leagueId: 'league-456',
          },
        ],
      };

      presenter.present(firstResult);
      presenter.reset();
      presenter.present(secondResult);

      expect(presenter.getResponseModel()).toEqual(secondResult);
    });
  });

  describe('viewModel', () => {
    it('should return the result', () => {
      const result: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      presenter.present(result);

      expect(presenter.viewModel).toEqual(result);
    });

    it('should throw error when accessed before present()', () => {
      expect(() => presenter.viewModel).toThrow('Presenter not presented');
    });

    it('should throw error after reset', () => {
      const result: GetPrizesResultDTO = {
        prizes: [
          {
            id: 'prize-123',
            name: 'Test Prize',
            description: 'Test Description',
            type: PrizeType.CASH,
            amount: 100,
            leagueId: 'league-123',
          },
        ],
      };

      presenter.present(result);
      presenter.reset();

      expect(() => presenter.viewModel).toThrow('Presenter not presented');
    });
  });
});
