import type { GetSponsorDashboardResult } from '@core/racing/application/use-cases/GetSponsorDashboardUseCase';
import { Money } from '@core/racing/domain/value-objects/Money';
import { beforeEach, describe, expect, it } from 'vitest';
import { GetSponsorDashboardPresenter } from './GetSponsorDashboardPresenter';

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

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

  describe('reset', () => {
    it('should reset the result to null', () => {
      const mockResult: GetSponsorDashboardResult = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: Money.create(0, 'USD'),
          costPerThousandViews: 0,
        },
      };
      presenter.present(mockResult);
      
      const expectedViewModel = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: 0,
          costPerThousandViews: 0,
        },
        sponsorships: {
          leagues: [],
          teams: [],
          drivers: [],
          races: [],
          platform: [],
        },
        recentActivity: [],
        upcomingRenewals: [],
      };
      expect(presenter.viewModel).toEqual(expectedViewModel);

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

  describe('present', () => {
    it('should store the result', () => {
      const mockResult: GetSponsorDashboardResult = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: Money.create(0, 'USD'),
          costPerThousandViews: 0,
        },
      };

      presenter.present(mockResult);

      const expectedViewModel = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: 0,
          costPerThousandViews: 0,
        },
        sponsorships: {
          leagues: [],
          teams: [],
          drivers: [],
          races: [],
          platform: [],
        },
        recentActivity: [],
        upcomingRenewals: [],
      };
      expect(presenter.viewModel).toEqual(expectedViewModel);
    });
  });

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

    it('should return the result when presented', () => {
      const mockResult: GetSponsorDashboardResult = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: Money.create(0, 'USD'),
          costPerThousandViews: 0,
        },
      };
      presenter.present(mockResult);

      const expectedViewModel = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: 0,
          costPerThousandViews: 0,
        },
        sponsorships: {
          leagues: [],
          teams: [],
          drivers: [],
          races: [],
          platform: [],
        },
        recentActivity: [],
        upcomingRenewals: [],
      };
      expect(presenter.getViewModel()).toEqual(expectedViewModel);
    });
  });

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

    it('should return the result when presented', () => {
      const mockResult: GetSponsorDashboardResult = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: Money.create(0, 'USD'),
          costPerThousandViews: 0,
        },
      };
      presenter.present(mockResult);

      const expectedViewModel = {
        sponsorId: 'sponsor-1',
        sponsorName: 'Test Sponsor',
        metrics: {
          impressions: 1000,
          impressionsChange: 0,
          uniqueViewers: 700,
          viewersChange: 0,
          races: 5,
          drivers: 10,
          exposure: 50,
          exposureChange: 0,
        },
        sponsoredLeagues: [],
        investment: {
          activeSponsorships: 0,
          totalInvestment: 0,
          costPerThousandViews: 0,
        },
        sponsorships: {
          leagues: [],
          teams: [],
          drivers: [],
          races: [],
          platform: [],
        },
        recentActivity: [],
        upcomingRenewals: [],
      };
      expect(presenter.viewModel).toEqual(expectedViewModel);
    });
  });
});