import { injectable, unmanaged } from 'inversify';
import { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
import { Result } from '@/lib/contracts/Result';
import { Service, type DomainError } from '@/lib/contracts/services/Service';
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
import { isProductionEnvironment } from '@/lib/config/env';
import { LeagueMemberViewModel } from '@/lib/view-models/LeagueMemberViewModel';
import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';
import type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';

export interface LeagueRosterAdminData {
  leagueId: string;
  members: LeagueRosterMemberDTO[];
  joinRequests: LeagueRosterJoinRequestDTO[];
}

@injectable()
export class LeagueMembershipService implements Service {
  private apiClient: LeaguesApiClient;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private static cachedMemberships = new Map<string, any[]>();

  constructor(@unmanaged() apiClient?: LeaguesApiClient) {
    if (apiClient) {
      this.apiClient = apiClient;
    } else {
      const baseUrl = getWebsiteApiBaseUrl();
      const logger = new ConsoleLogger();
      const errorReporter = new EnhancedErrorReporter(logger, {
        showUserNotifications: false,
        logToConsole: true,
        reportToExternal: isProductionEnvironment(),
      });
      this.apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);
    }
  }

  async getLeagueMemberships(leagueId: string, currentUserId: string): Promise<any[]> {
    const res = await this.apiClient.getMemberships(leagueId);
    const members = (res as any).members || res;
    return members.map((m: any) => new LeagueMemberViewModel({ ...m, currentUserId }, currentUserId as any));
  }

  async removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<any> {
    const res = await this.apiClient.removeMember(leagueId, performerDriverId, targetDriverId);
    return (res as any).value || res;
  }

  async removeRosterMember(leagueId: string, targetDriverId: string): Promise<Result<{ success: boolean }, DomainError>> {
    try {
      const res = await this.apiClient.removeRosterMember(leagueId, targetDriverId);
      const dto = (res as any).value || res;
      return Result.ok({ success: dto.success });
    } catch (error: unknown) {
      return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to remove member' });
    }
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  static getMembership(leagueId: string, driverId: string): any | null {
    const members = this.cachedMemberships.get(leagueId);
    if (!members) return null;
    return members.find(m => m.driverId === driverId) || null;
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  static getLeagueMembers(leagueId: string): any[] {
    return this.cachedMemberships.get(leagueId) || [];
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  static getAllMembershipsForDriver(driverId: string): any[] {
    const allMemberships: any[] = [];
    for (const [leagueId, members] of this.cachedMemberships.entries()) {
      const membership = members.find(m => m.driverId === driverId);
      if (membership) {
        allMemberships.push({ ...membership, leagueId });
      }
    }
    return allMemberships;
  }

  async fetchLeagueMemberships(leagueId: string): Promise<void> {
    try {
      const members = await this.apiClient.getMemberships(leagueId);
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      LeagueMembershipService.cachedMemberships.set(leagueId, (members as any).members || []);
    } catch (error) {
      console.error('Failed to fetch memberships', error);
    }
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getMembership(leagueId: string, driverId: string): any | null {
    return LeagueMembershipService.getMembership(leagueId, driverId);
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getLeagueMembers(leagueId: string): any[] {
    return LeagueMembershipService.getLeagueMembers(leagueId);
  }

  async joinLeague(_: string, __: string): Promise<Result<void, DomainError>> {
    return Result.err({ type: 'notImplemented', message: 'joinLeague' });
  }

  async leaveLeague(_: string, __: string): Promise<Result<void, DomainError>> {
    return Result.err({ type: 'notImplemented', message: 'leaveLeague' });
  }

  async getRosterAdminData(leagueId: string): Promise<Result<LeagueRosterAdminData, DomainError>> {
    try {
      const [members, joinRequests] = await Promise.all([
        this.apiClient.getAdminRosterMembers(leagueId),
        this.apiClient.getAdminRosterJoinRequests(leagueId),
      ]);

      return Result.ok({
        leagueId,
        members,
        joinRequests,
      });
    } catch (error: unknown) {
      console.error('LeagueMembershipService.getRosterAdminData failed:', error);
      return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to fetch roster data' });
    }
  }

  async approveJoinRequest(leagueId: string, joinRequestId: string): Promise<Result<{ success: boolean }, DomainError>> {
    try {
      const res = await this.apiClient.approveRosterJoinRequest(leagueId, joinRequestId);
      const dto = (res as any).value || res;
      return Result.ok({ success: dto.success });
    } catch (error: unknown) {
      return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to approve join request' });
    }
  }

  async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise<Result<{ success: boolean }, DomainError>> {
    try {
      const res = await this.apiClient.rejectRosterJoinRequest(leagueId, joinRequestId);
      const dto = (res as any).value || res;
      return Result.ok({ success: dto.success });
    } catch (error: unknown) {
      return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to reject join request' });
    }
  }
}
