import type { DashboardOverviewDTO } from '@/lib/types/generated/DashboardOverviewDTO';
import type { DashboardViewData } from '@/lib/view-data/DashboardViewData';
import { DashboardDateDisplay } from '@/lib/display-objects/DashboardDateDisplay';
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
import { DashboardRankDisplay } from '@/lib/display-objects/DashboardRankDisplay';
import { DashboardConsistencyDisplay } from '@/lib/display-objects/DashboardConsistencyDisplay';
import { DashboardCountDisplay } from '@/lib/display-objects/DashboardCountDisplay';
import { DashboardLeaguePositionDisplay } from '@/lib/display-objects/DashboardLeaguePositionDisplay';

/**
 * DashboardViewDataBuilder
 *
 * Transforms DashboardOverviewDTO (API DTO) into DashboardViewData for server-side rendering.
 * Deterministic; side-effect free; no HTTP calls.
 */
export class DashboardViewDataBuilder {
  static build(apiDto: DashboardOverviewDTO): DashboardViewData {
    return {
      currentDriver: {
        name: apiDto.currentDriver?.name || '',
        avatarUrl: apiDto.currentDriver?.avatarUrl || '',
        country: apiDto.currentDriver?.country || '',
        rating: apiDto.currentDriver ? RatingDisplay.format(apiDto.currentDriver.rating ?? 0) : '0.0',
        rank: apiDto.currentDriver ? DashboardRankDisplay.format(apiDto.currentDriver.globalRank ?? 0) : '0',
        totalRaces: apiDto.currentDriver ? DashboardCountDisplay.format(apiDto.currentDriver.totalRaces ?? 0) : '0',
        wins: apiDto.currentDriver ? DashboardCountDisplay.format(apiDto.currentDriver.wins ?? 0) : '0',
        podiums: apiDto.currentDriver ? DashboardCountDisplay.format(apiDto.currentDriver.podiums ?? 0) : '0',
        consistency: apiDto.currentDriver ? DashboardConsistencyDisplay.format(apiDto.currentDriver.consistency ?? 0) : '0%',
      },
      nextRace: apiDto.nextRace ? DashboardViewDataBuilder.buildNextRace(apiDto.nextRace) : null,
      upcomingRaces: apiDto.upcomingRaces.map((race) => DashboardViewDataBuilder.buildRace(race)),
      leagueStandings: apiDto.leagueStandingsSummaries.map((standing) => ({
        leagueId: standing.leagueId,
        leagueName: standing.leagueName,
        position: DashboardLeaguePositionDisplay.format(standing.position),
        points: DashboardCountDisplay.format(standing.points),
        totalDrivers: DashboardCountDisplay.format(standing.totalDrivers),
      })),
      feedItems: apiDto.feedSummary.items.map((item) => ({
        id: item.id,
        type: item.type,
        headline: item.headline,
        body: item.body,
        timestamp: item.timestamp,
        formattedTime: DashboardDateDisplay.format(new Date(item.timestamp)).relative,
        ctaHref: item.ctaHref,
        ctaLabel: item.ctaLabel,
      })),
      friends: apiDto.friends.map((friend) => ({
        id: friend.id,
        name: friend.name,
        avatarUrl: friend.avatarUrl || '',
        country: friend.country,
      })),
      activeLeaguesCount: DashboardCountDisplay.format(apiDto.activeLeaguesCount),
      friendCount: DashboardCountDisplay.format(apiDto.friends.length),
      hasUpcomingRaces: apiDto.upcomingRaces.length > 0,
      hasLeagueStandings: apiDto.leagueStandingsSummaries.length > 0,
      hasFeedItems: apiDto.feedSummary.items.length > 0,
      hasFriends: apiDto.friends.length > 0,
    };
  }

  private static buildNextRace(race: NonNullable<DashboardOverviewDTO['nextRace']>) {
    const dateInfo = DashboardDateDisplay.format(new Date(race.scheduledAt));
    return {
      id: race.id,
      track: race.track,
      car: race.car,
      scheduledAt: race.scheduledAt,
      formattedDate: dateInfo.date,
      formattedTime: dateInfo.time,
      timeUntil: dateInfo.relative,
      isMyLeague: race.isMyLeague,
    };
  }

  private static buildRace(race: DashboardOverviewDTO['upcomingRaces'][number]) {
    const dateInfo = DashboardDateDisplay.format(new Date(race.scheduledAt));
    return {
      id: race.id,
      track: race.track,
      car: race.car,
      scheduledAt: race.scheduledAt,
      formattedDate: dateInfo.date,
      formattedTime: dateInfo.time,
      timeUntil: dateInfo.relative,
      isMyLeague: race.isMyLeague,
    };
  }
}