import { ApiClient } from '@/lib/api';
import type { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
import { LeagueMemberViewModel } from '@/lib/view-models/LeagueMemberViewModel';
import type { LeagueMemberDTO } from '@/lib/types/generated/LeagueMemberDTO';
import type { LeagueMembership } from '@/lib/types/LeagueMembership';

let cachedLeaguesApiClient: LeaguesApiClient | undefined;

function getDefaultLeaguesApiClient(): LeaguesApiClient {
  if (cachedLeaguesApiClient) return cachedLeaguesApiClient;

  const api = new ApiClient(getWebsiteApiBaseUrl());
  cachedLeaguesApiClient = (api as any).leagues as LeaguesApiClient;
  return cachedLeaguesApiClient;
}

export class LeagueMembershipService {
  // In-memory cache for memberships (populated via API calls)
  private static leagueMemberships = new Map<string, LeagueMembership[]>();

  constructor(private readonly leaguesApiClient?: LeaguesApiClient) {}

  private getClient(): LeaguesApiClient {
    return this.leaguesApiClient ?? getDefaultLeaguesApiClient();
  }

  async getLeagueMemberships(leagueId: string, currentUserId: string): Promise<LeagueMemberViewModel[]> {
    const dto = await this.getClient().getMemberships(leagueId);
    const members: LeagueMemberDTO[] = ((dto as any)?.members ?? (dto as any)?.memberships ?? []) as LeagueMemberDTO[];
    return members.map((m) => new LeagueMemberViewModel(m, currentUserId));
  }

  async removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<{ success: boolean }> {
    return this.getClient().removeMember(leagueId, performerDriverId, targetDriverId) as unknown as { success: boolean };
  }

  /**
   * Get a specific membership from cache.
   */
  static getMembership(leagueId: string, driverId: string): LeagueMembership | null {
    const list = this.leagueMemberships.get(leagueId);
    if (!list) return null;
    return list.find((m) => m.driverId === driverId) ?? null;
  }

  /**
   * Get all members of a league from cache.
   */
  static getLeagueMembers(leagueId: string): LeagueMembership[] {
    return [...(this.leagueMemberships.get(leagueId) ?? [])];
  }

  /**
   * Fetch and cache memberships for a league via API.
   */
  static async fetchLeagueMemberships(leagueId: string): Promise<LeagueMembership[]> {
    try {
      const result = await getDefaultLeaguesApiClient().getMemberships(leagueId);
      const memberships: LeagueMembership[] = ((result as any)?.members ?? []).map((member: any) => ({
        id: `${member.driverId}-${leagueId}`, // Generate ID since API doesn't provide it
        leagueId,
        driverId: member.driverId,
        role: member.role,
        status: 'active', // Assume active since API returns current members
        joinedAt: member.joinedAt,
      }));
      this.setLeagueMemberships(leagueId, memberships);
      return memberships;
    } catch (error) {
      console.error('Failed to fetch league memberships:', error);
      return [];
    }
  }

  /**
   * Join a league.
   *
   * NOTE: The API currently exposes membership mutations via league member management endpoints.
   * For now we keep the website decoupled by consuming only the API through this service.
   */
  async joinLeague(leagueId: string, driverId: string): Promise<void> {
    // Temporary: no join endpoint exposed yet in API.
    // Keep behavior predictable for UI.
    throw new Error('Joining leagues is not available in this build.');
  }

  /**
   * Leave a league.
   */
  async leaveLeague(leagueId: string, driverId: string): Promise<void> {
    // Temporary: no leave endpoint exposed yet in API.
    throw new Error('Leaving leagues is not available in this build.');
  }

  /**
   * Set memberships in cache (for use after API calls).
   */
  static setLeagueMemberships(leagueId: string, memberships: LeagueMembership[]): void {
    this.leagueMemberships.set(leagueId, memberships);
  }

  /**
   * Clear cached memberships for a league.
   */
  static clearLeagueMemberships(leagueId: string): void {
    this.leagueMemberships.delete(leagueId);
  }

  /**
   * Get iterator for cached memberships (for utility functions).
   */
  static getCachedMembershipsIterator(): IterableIterator<[string, LeagueMembership[]]> {
    return this.leagueMemberships.entries();
  }

  /**
   * Get all memberships for a specific driver across all leagues.
   */
  static getAllMembershipsForDriver(driverId: string): LeagueMembership[] {
    const allMemberships: LeagueMembership[] = [];
    for (const [leagueId, memberships] of this.leagueMemberships.entries()) {
      const driverMembership = memberships.find((m) => m.driverId === driverId);
      if (driverMembership) {
        allMemberships.push(driverMembership);
      }
    }
    return allMemberships;
  }

  // Instance methods that delegate to static methods for consistency with service pattern

  /**
   * Get a specific membership from cache.
   */
  getMembership(leagueId: string, driverId: string): LeagueMembership | null {
    return LeagueMembershipService.getMembership(leagueId, driverId);
  }

  /**
   * Get all members of a league from cache.
   */
  getLeagueMembers(leagueId: string): LeagueMembership[] {
    return LeagueMembershipService.getLeagueMembers(leagueId);
  }

  /**
   * Fetch and cache memberships for a league via API.
   */
  async fetchLeagueMemberships(leagueId: string): Promise<LeagueMembership[]> {
    return LeagueMembershipService.fetchLeagueMemberships(leagueId);
  }

  /**
   * Set memberships in cache (for use after API calls).
   */
  setLeagueMemberships(leagueId: string, memberships: LeagueMembership[]): void {
    LeagueMembershipService.setLeagueMemberships(leagueId, memberships);
  }

  /**
   * Clear cached memberships for a league.
   */
  clearLeagueMemberships(leagueId: string): void {
    LeagueMembershipService.clearLeagueMemberships(leagueId);
  }
}
