import { GetPaymentsPresenter } from './GetPaymentsPresenter';
import { GetPaymentsOutput } from '../dtos/PaymentsDto';

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

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

  describe('present', () => {
    it('should map result to response model', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel).toEqual({
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      });
    });

    it('should include seasonId when provided', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            seasonId: 'season-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments[0].seasonId).toBe('season-123');
    });

    it('should include completedAt when provided', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'completed',
            createdAt: new Date('2024-01-01'),
            completedAt: new Date('2024-01-02'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments[0].completedAt).toEqual(new Date('2024-01-02'));
    });

    it('should not include seasonId when not provided', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments[0].seasonId).toBeUndefined();
    });

    it('should not include completedAt when not provided', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments[0].completedAt).toBeUndefined();
    });

    it('should handle empty payments list', () => {
      const result = {
        payments: [],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments).toEqual([]);
    });

    it('should handle multiple payments', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
          {
            id: 'payment-456',
            type: 'membership',
            amount: 200,
            platformFee: 10,
            netAmount: 190,
            payerId: 'user-456',
            payerType: 'driver',
            leagueId: 'league-456',
            status: 'completed',
            createdAt: new Date('2024-01-02'),
            completedAt: new Date('2024-01-03'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments).toHaveLength(2);
      expect(responseModel.payments[0].id).toBe('payment-123');
      expect(responseModel.payments[1].id).toBe('payment-456');
    });
  });

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

    it('should return model after present()', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      presenter.present(result);

      const responseModel = presenter.getResponseModel();
      expect(responseModel).toBeDefined();
      expect(responseModel.payments[0].id).toBe('payment-123');
    });
  });

  describe('reset', () => {
    it('should clear the response model', () => {
      const result = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

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

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

    it('should allow presenting again after reset', () => {
      const firstResult = {
        payments: [
          {
            id: 'payment-123',
            type: 'membership',
            amount: 100,
            platformFee: 5,
            netAmount: 95,
            payerId: 'user-123',
            payerType: 'driver',
            leagueId: 'league-123',
            status: 'pending',
            createdAt: new Date('2024-01-01'),
          },
        ],
      };

      const secondResult = {
        payments: [
          {
            id: 'payment-456',
            type: 'membership',
            amount: 200,
            platformFee: 10,
            netAmount: 190,
            payerId: 'user-456',
            payerType: 'driver',
            leagueId: 'league-456',
            status: 'pending',
            createdAt: new Date('2024-01-02'),
          },
        ],
      };

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

      const responseModel = presenter.getResponseModel();
      expect(responseModel.payments[0].id).toBe('payment-456');
    });
  });
});
