import type { LeagueWithCapacityAndScoringDTO } from '@/lib/types/generated/LeagueWithCapacityAndScoringDTO';
import type { LeagueMembershipsDTO } from '@/lib/types/generated/LeagueMembershipsDTO';
import type { RaceDTO } from '@/lib/types/generated/RaceDTO';
import type { GetDriverOutputDTO } from '@/lib/types/generated/GetDriverOutputDTO';
import type { LeagueScoringConfigDTO } from '@/lib/types/generated/LeagueScoringConfigDTO';
import type { LeagueDetailViewData, LeagueInfoData, LiveRaceData, DriverSummaryData, SponsorInfo, NextRaceInfo, SeasonProgress, RecentResult } from '@/lib/view-data/LeagueDetailViewData';

/**
 * LeagueDetailViewDataBuilder
 *
 * Transforms API DTOs into LeagueDetailViewData for server-side rendering.
 * Deterministic; side-effect free; no HTTP calls.
 */
export class LeagueDetailViewDataBuilder {
  static build(input: {
    league: LeagueWithCapacityAndScoringDTO;
    owner: GetDriverOutputDTO | null;
    scoringConfig: LeagueScoringConfigDTO | null;
    memberships: LeagueMembershipsDTO;
    races: RaceDTO[];
    sponsors: any[];
  }): LeagueDetailViewData {
    const { league, owner, scoringConfig, memberships, races, sponsors } = input;
    
    // Calculate running races - using available fields from RaceDTO
    const runningRaces: LiveRaceData[] = races
      .filter(r => r.name.includes('Running')) // Placeholder filter
      .map(r => ({
        id: r.id,
        name: r.name,
        date: r.date,
        registeredCount: 0,
        strengthOfField: 0,
      }));
    
    // Calculate info data
    const membersCount = Array.isArray(memberships.members) ? memberships.members.length : 0;

    // League overview wants total races, not just completed.
    // (In seed/demo data many races are `status: running`, which should still count.)
    const racesCount = races.length;

    // Compute real avgSOF from races
    const racesWithSOF = races.filter(r => {
      const sof = (r as any).strengthOfField;
      return typeof sof === 'number' && sof > 0;
    });
    const avgSOF = racesWithSOF.length > 0
      ? Math.round(racesWithSOF.reduce((sum, r) => sum + ((r as any).strengthOfField || 0), 0) / racesWithSOF.length)
      : null;

    if (process.env.NODE_ENV !== 'production') {
      const race0 = races.length > 0 ? races[0] : null;
      console.info(
        '[LeagueDetailViewDataBuilder] leagueId=%s members=%d races=%d racesWithSOF=%d avgSOF=%s race0=%o',
        league.id,
        membersCount,
        racesCount,
        racesWithSOF.length,
        String(avgSOF),
        race0,
      );
    }
    
    const info: LeagueInfoData = {
      name: league.name,
      description: league.description || '',
      membersCount,
      racesCount,
      avgSOF,
      structure: `Solo • ${league.settings?.maxDrivers ?? 32} max`,
      scoring: scoringConfig?.scoringPresetId || 'Standard',
      createdAt: league.createdAt,
      discordUrl: league.socialLinks?.discordUrl,
      youtubeUrl: league.socialLinks?.youtubeUrl,
      websiteUrl: league.socialLinks?.websiteUrl,
    };
    
    // Convert owner to driver summary
    const ownerSummary: DriverSummaryData | null = owner ? {
      driverId: owner.id,
      driverName: owner.name,
      avatarUrl: owner.avatarUrl || null,
      rating: null,
      rank: null,
      roleBadgeText: 'Owner',
      roleBadgeClasses: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30',
      profileUrl: `/drivers/${owner.id}`,
    } : null;
    
    // Convert sponsors
    const sponsorInfo: SponsorInfo[] = sponsors.map(s => ({
      id: s.id,
      name: s.name,
      tier: s.tier,
      logoUrl: s.logoUrl,
      websiteUrl: s.websiteUrl,
      tagline: s.tagline,
    }));
    
    // Convert memberships to summaries
    const adminSummaries: DriverSummaryData[] = (memberships.members || [])
      .filter(m => m.role === 'admin')
      .map(m => ({
        driverId: m.driverId,
        driverName: m.driver.name,
        avatarUrl: (m.driver as any).avatarUrl || null,
        rating: null,
        rank: null,
        roleBadgeText: 'Admin',
        roleBadgeClasses: 'bg-blue-500/10 text-blue-500 border-blue-500/30',
        profileUrl: `/drivers/${m.driverId}`,
      }));

    const stewardSummaries: DriverSummaryData[] = (memberships.members || [])
      .filter(m => m.role === 'steward')
      .map(m => ({
        driverId: m.driverId,
        driverName: m.driver.name,
        avatarUrl: (m.driver as any).avatarUrl || null,
        rating: null,
        rank: null,
        roleBadgeText: 'Steward',
        roleBadgeClasses: 'bg-purple-500/10 text-purple-500 border-purple-500/30',
        profileUrl: `/drivers/${m.driverId}`,
      }));

    const memberSummaries: DriverSummaryData[] = (memberships.members || [])
      .filter(m => m.role === 'member')
      .map(m => ({
        driverId: m.driverId,
        driverName: m.driver.name,
        avatarUrl: (m.driver as any).avatarUrl || null,
        rating: null,
        rank: null,
        roleBadgeText: 'Member',
        roleBadgeClasses: 'bg-zinc-500/10 text-zinc-500 border-zinc-500/30',
        profileUrl: `/drivers/${m.driverId}`,
      }));

    // Calculate next race (first upcoming race)
    const now = new Date();
    const nextRace: NextRaceInfo | undefined = races
      .filter(r => new Date(r.date) > now)
      .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
      .map(r => ({
        id: r.id,
        name: r.name,
        date: r.date,
        track: (r as any).track,
        car: (r as any).car,
      }))[0];

    // Calculate season progress (completed races vs total races)
    const completedRaces = races.filter(r => {
      const raceDate = new Date(r.date);
      return raceDate < now;
    }).length;
    const totalRaces = races.length;
    const percentage = totalRaces > 0 ? Math.round((completedRaces / totalRaces) * 100) : 0;
    const seasonProgress: SeasonProgress = {
      completedRaces,
      totalRaces,
      percentage,
    };

    // Get recent results (top 3 from last completed race)
    const recentResults: RecentResult[] = races
      .filter(r => new Date(r.date) < now)
      .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
      .slice(0, 3)
      .map(r => ({
        raceId: r.id,
        raceName: r.name,
        position: (r as any).position || 0,
        points: (r as any).points || 0,
        finishedAt: r.date,
      }));

    return {
      leagueId: league.id,
      name: league.name,
      description: league.description || '',
      logoUrl: league.logoUrl,
      info,
      runningRaces,
      sponsors: sponsorInfo,
      ownerSummary,
      adminSummaries,
      stewardSummaries,
      memberSummaries,
      sponsorInsights: null, // Only for sponsor mode
      nextRace,
      seasonProgress,
      recentResults,
      walletBalance: league.walletBalance,
      pendingProtestsCount: league.pendingProtestsCount,
      pendingJoinRequestsCount: league.pendingJoinRequestsCount,
    };
  }
}