import { describe, it, expect } from 'vitest';
import { LeagueDetailPageViewModel, type SponsorInfo } from './LeagueDetailPageViewModel';
import type { LeagueWithCapacityDTO } from '../types/generated/LeagueWithCapacityDTO';
import type { LeagueStatsDTO } from '../types/generated/LeagueStatsDTO';
import type { GetDriverOutputDTO } from '../types/generated/GetDriverOutputDTO';
import type { LeagueMembershipsDTO } from '../types/generated/LeagueMembershipsDTO';
import type { LeagueScheduleDTO } from '../types/generated/LeagueScheduleDTO';
import { RaceViewModel } from './RaceViewModel';

describe('LeagueDetailPageViewModel', () => {
  const league: LeagueWithCapacityDTO = {
    id: 'league-1',
    name: 'Pro Series',
    // extra fields used by view-model but not in generated type yet
    description: 'Top tier competition',
    ownerId: 'owner-1',
    createdAt: '2025-01-01T00:00:00Z',
    maxDrivers: 40,
    socialLinks: {
      discordUrl: 'https://discord.gg/example',
      youtubeUrl: 'https://youtube.com/example',
      websiteUrl: 'https://example.com',
    },
  } as any;

  const owner: GetDriverOutputDTO = {
    id: 'owner-1',
    iracingId: '100',
    name: 'Owner Driver',
    country: 'US',
    joinedAt: '2024-01-01T00:00:00Z',
  };

  const drivers: GetDriverOutputDTO[] = [
    owner,
    {
      id: 'driver-2',
      iracingId: '101',
      name: 'Second Driver',
      country: 'DE',
      joinedAt: '2024-02-01T00:00:00Z',
    },
  ];

  const memberships: LeagueMembershipsDTO = {
    memberships: [
      {
        driverId: 'owner-1',
        role: 'owner',
        status: 'active',
        joinedAt: '2024-01-01T00:00:00Z',
      },
      {
        driverId: 'driver-2',
        role: 'admin',
        status: 'active',
        joinedAt: '2024-02-01T00:00:00Z',
      },
      {
        driverId: 'driver-3',
        role: 'steward',
        status: 'inactive',
        joinedAt: '2024-03-01T00:00:00Z',
      },
    ],
  } as any;

  const schedule: LeagueScheduleDTO = {
    races: [
      { id: 'race-1', name: 'Round 1', date: '2025-01-10T20:00:00Z' },
      { id: 'race-2', name: 'Round 2', date: '2025-01-17T20:00:00Z' },
    ],
  } as any;

  const allRaces: RaceViewModel[] = schedule.races.map(r => new RaceViewModel({ ...r, views: 12000, status: 'completed' }));

  const leagueStats: LeagueStatsDTO = {
    totalMembers: 2,
    totalRaces: 10,
    averageRating: 3_200,
    // view-model also expects averageSOF and completedRaces
    averageSOF: 3200,
    completedRaces: 4,
  } as any;

  const sponsors: SponsorInfo[] = [
    { id: 's1', name: 'Main Sponsor', tier: 'main', logoUrl: '/logo-main.png', tagline: 'Primary partner' },
    { id: 's2', name: 'Secondary Sponsor', tier: 'secondary', logoUrl: '/logo-sec.png' },
  ];

  it('maps core league, owner, drivers, memberships and races', () => {
    const vm = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      leagueStats,
      sponsors,
    );

    expect(vm.id).toBe(league.id);
    expect(vm.name).toBe(league.name);
    expect(vm.description).toBe(league.description);
    expect(vm.ownerId).toBe(league.ownerId);
    expect(vm.settings.maxDrivers).toBe(league.maxDrivers);
    expect(vm.socialLinks?.discordUrl).toBe(league.socialLinks?.discordUrl);

    expect(vm.owner).toEqual(owner);
    expect(vm.scoringConfig).toBeNull();

    expect(vm.drivers).toHaveLength(drivers.length);
    expect(vm.memberships).toHaveLength(memberships.memberships.length);

    expect(vm.allRaces).toHaveLength(allRaces.length);
    expect(vm.runningRaces.every(r => r.status === 'running')).toBe(true);
  });

  it('computes sponsor insights from member count and stats', () => {
    const vm = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      leagueStats,
      sponsors,
    );

    const memberCount = memberships.memberships.length;
    const mainSponsorTaken = sponsors.some(s => s.tier === 'main');
    const secondaryTaken = sponsors.filter(s => s.tier === 'secondary').length;

    expect(vm.sponsorInsights.avgViewsPerRace).toBe(5400 + memberCount * 50);
    expect(vm.sponsorInsights.totalImpressions).toBe(45000 + memberCount * 500);
    expect(vm.sponsorInsights.engagementRate).toBe((3.5 + memberCount / 50).toFixed(1));
    expect(vm.sponsorInsights.estimatedReach).toBe(memberCount * 150);
    expect(vm.sponsorInsights.mainSponsorAvailable).toBe(!mainSponsorTaken);
    expect(vm.sponsorInsights.secondarySlotsAvailable).toBe(Math.max(0, 2 - secondaryTaken));
    expect(vm.sponsorInsights.mainSponsorPrice).toBe(800 + Math.floor(memberCount * 10));
    expect(vm.sponsorInsights.secondaryPrice).toBe(250 + Math.floor(memberCount * 3));
    expect(vm.sponsorInsights.discordMembers).toBe(memberCount * 3);
    expect(vm.sponsorInsights.monthlyActivity).toBe(Math.min(100, 40 + (leagueStats as any).completedRaces * 2));
  });

  it('derives sponsor tier and trustScore from averageSOF and completedRaces', () => {
    const highSofStats = { ...leagueStats, averageSOF: 3500 } as any;
    const vmHigh = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      highSofStats,
      sponsors,
    );

    expect(vmHigh.sponsorInsights.tier).toBe('premium');

    const midSofStats = { ...leagueStats, averageSOF: 2500 } as any;
    const vmMid = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      midSofStats,
      sponsors,
    );

    expect(vmMid.sponsorInsights.tier).toBe('standard');

    const lowSofStats = { ...leagueStats, averageSOF: 1500 } as any;
    const vmLow = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      lowSofStats,
      sponsors,
    );

    expect(vmLow.sponsorInsights.tier).toBe('starter');

    expect(vmHigh.sponsorInsights.trustScore).toBe(
      Math.min(100, 60 + memberships.memberships.length + (leagueStats as any).completedRaces),
    );
  });

  it('builds owner, admin and steward summaries from memberships', () => {
    const vm = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      leagueStats,
      sponsors,
    );

    expect(vm.ownerSummary?.driver.id).toBe('owner-1');
    expect(vm.ownerSummary?.rating).toBeNull();
    expect(vm.ownerSummary?.rank).toBeNull();

    expect(vm.adminSummaries.length).toBeGreaterThanOrEqual(1);
    expect(vm.adminSummaries[0].driver.id).toBe('driver-2');

    expect(Array.isArray(vm.stewardSummaries)).toBe(true);
  });

  it('returns falsey sponsor/membership helpers by default', () => {
    const vm = new LeagueDetailPageViewModel(
      league,
      owner,
      null,
      drivers,
      memberships,
      allRaces,
      leagueStats,
      sponsors,
    );

    expect(vm.isSponsorMode).toBe(false);
    expect(vm.currentUserMembership).toBeNull();
    expect(vm.canEndRaces).toBe(false);
  });
});
