import { injectable, unmanaged } from 'inversify';
import { Result } from '@/lib/contracts/Result';
import { Service, type DomainError } from '@/lib/contracts/services/Service';
import { type LeagueSettingsApiDto } from '@/lib/types/tbd/LeagueSettingsApiDto';
import { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';
import { DriversApiClient } from '@/lib/api/drivers/DriversApiClient';
import { LeagueSettingsViewModel } from '@/lib/view-models/LeagueSettingsViewModel';

@injectable()
export class LeagueSettingsService implements Service {
  private static cachedMemberships = new Map<string, unknown[]>();

  constructor(
    @unmanaged() private readonly leaguesApiClient?: LeaguesApiClient,
    @unmanaged() private readonly driversApiClient?: DriversApiClient,
  ) {}

  async getLeagueSettings(leagueId: string): Promise<LeagueSettingsViewModel | null> {
    if (!this.leaguesApiClient || !this.driversApiClient) {
      return null;
    }

    try {
      const [leaguesRes, configRes, presetsRes, leaderboardRes, membershipsRes] = await Promise.all([
        this.leaguesApiClient.getAllWithCapacity(),
        this.leaguesApiClient.getLeagueConfig(leagueId),
        this.leaguesApiClient.getScoringPresets(),
        this.driversApiClient.getLeaderboard(),
        this.leaguesApiClient.getMemberships(leagueId),
      ]);

      const leaguesData = (leaguesRes as any).value || leaguesRes;
      const configData = (configRes as any).value || configRes;
      const presetsData = (presetsRes as any).value || presetsRes;
      const leaderboardData = (leaderboardRes as any).value || leaderboardRes;
      const membershipsData = (membershipsRes as any).value || membershipsRes;

      const league = leaguesData.leagues.find((l: any) => l.id === leagueId);
      if (!league) return null;

      const ownerRes = await this.driversApiClient.getDriver(league.ownerId);
      const owner = (ownerRes as any).value || ownerRes;

      return new LeagueSettingsViewModel({
        league,
        config: configData.config || configData,
        presets: presetsData.presets,
        owner,
        members: membershipsData.members,
        drivers: leaderboardData.drivers,
      } as any);
    } catch (error) {
      return null;
    }
  }

  async transferOwnership(leagueId: string, currentOwnerId: string, newOwnerId: string): Promise<boolean> {
    if (!this.leaguesApiClient) throw new Error('API client not initialized');
    const res = await this.leaguesApiClient.transferOwnership(leagueId, currentOwnerId, newOwnerId);
    const data = (res as any).value || res;
    return data.success;
  }

  async getSettingsData(leagueId: string): Promise<Result<LeagueSettingsApiDto, DomainError>> {
    // Mock data since backend not implemented
    const mockData: LeagueSettingsApiDto = {
      leagueId,
      league: {
        id: leagueId,
        name: 'Mock League',
        description: 'A mock league for demonstration',
        visibility: 'public',
        ownerId: 'owner-123',
        createdAt: '2024-01-01T00:00:00Z',
        updatedAt: '2024-01-01T00:00:00Z',
      },
      config: {
        maxDrivers: 20,
        scoringPresetId: 'preset-1',
        allowLateJoin: true,
        requireApproval: false,
      },
    };
    return Result.ok(mockData);
  }

  static getCachedMembershipsIterator(): IterableIterator<[string, unknown[]]> {
    return this.cachedMemberships.entries();
  }

  static getMembership(leagueId: string, driverId: string): unknown | null {
    const members = this.cachedMemberships.get(leagueId);
    if (!members) return null;
    return members.find((m: any) => m.driverId === driverId) || null;
  }
}
