/**
 * Infrastructure Adapter: InMemoryTeamMembershipRepository
 *
 * In-memory implementation of ITeamMembershipRepository.
 * Stores memberships and join requests in Map structures.
 */

import type {
  TeamMembership,
  TeamJoinRequest,
} from '@core/racing/domain/types/TeamMembership';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import type { Logger } from '@core/shared/application';

export class InMemoryTeamMembershipRepository implements ITeamMembershipRepository {
  private membershipsByTeam: Map<string, TeamMembership[]>;
  private joinRequestsByTeam: Map<string, TeamJoinRequest[]>;
  private readonly logger: Logger;

  constructor(logger: Logger) {
    this.logger = logger;
    this.logger.info('InMemoryTeamMembershipRepository initialized.');
    this.membershipsByTeam = new Map();
    this.joinRequestsByTeam = new Map();
  }

  private getMembershipList(teamId: string): TeamMembership[] {
    let list = this.membershipsByTeam.get(teamId);
    if (!list) {
      list = [];
      this.membershipsByTeam.set(teamId, list);
      this.logger.debug(`Created new membership list for team: ${teamId}`);
    }
    return list;
  }

  private getJoinRequestList(teamId: string): TeamJoinRequest[] {
    let list = this.joinRequestsByTeam.get(teamId);
    if (!list) {
      list = [];
      this.joinRequestsByTeam.set(teamId, list);
      this.logger.debug(`Created new join request list for team: ${teamId}`);
    }
    return list;
  }

async getMembership(teamId: string, driverId: string): Promise<TeamMembership | null> {
    this.logger.debug(`[getMembership] Entry - teamId: ${teamId}, driverId: ${driverId}`);
    try {
      const list = this.membershipsByTeam.get(teamId);
      if (!list) {
        this.logger.warn(`[getMembership] No membership list found for team: ${teamId}. Returning null.`);
        return null;
      }
      const membership = list.find((m) => m.driverId === driverId) ?? null;
      if (membership) {
        this.logger.info(`[getMembership] Success - found membership for team: ${teamId}, driver: ${driverId}.`);
      } else {
        this.logger.info(`[getMembership] Not found - membership for team: ${teamId}, driver: ${driverId}.`);
      }
      return membership;
    } catch (error) {
      this.logger.error(`[getMembership] Error getting membership for team ${teamId}, driver ${driverId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async getActiveMembershipForDriver(driverId: string): Promise<TeamMembership | null> {
    this.logger.debug(`[getActiveMembershipForDriver] Entry - driverId: ${driverId}`);
    try {
      for (const list of this.membershipsByTeam.values()) {
        const membership = list.find(
          (m) => m.driverId === driverId && m.status === 'active',
        );
        if (membership) {
          this.logger.info(`[getActiveMembershipForDriver] Success - found active membership for driver: ${driverId}, team: ${membership.teamId}.`);
          return membership;
        }
      }
      this.logger.info(`[getActiveMembershipForDriver] Not found - no active membership for driver: ${driverId}.`);
      return null;
    } catch (error) {
      this.logger.error(`[getActiveMembershipForDriver] Error getting active membership for driver ${driverId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async getTeamMembers(teamId: string): Promise<TeamMembership[]> {
    this.logger.debug(`[getTeamMembers] Entry - teamId: ${teamId}`);
    try {
      const members = [...(this.membershipsByTeam.get(teamId) ?? [])];
      this.logger.info(`[getTeamMembers] Success - found ${members.length} members for team: ${teamId}.`);
      return members;
    } catch (error) {
      this.logger.error(`[getTeamMembers] Error getting team members for team ${teamId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async countByTeamId(teamId: string): Promise<number> {
    this.logger.debug(`[countByTeamId] Entry - teamId: ${teamId}`);
    try {
      const list = this.membershipsByTeam.get(teamId) ?? [];
      const count = list.filter((m) => m.status === 'active').length;
      this.logger.info(`[countByTeamId] Success - counted ${count} active members for team: ${teamId}.`);
      return count;
    } catch (error) {
      this.logger.error(`[countByTeamId] Error counting members for team ${teamId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async saveMembership(membership: TeamMembership): Promise<TeamMembership> {
    this.logger.debug(`[saveMembership] Entry - teamId: ${membership.teamId}, driverId: ${membership.driverId}`);
    try {
      const list = this.getMembershipList(membership.teamId);
      const existingIndex = list.findIndex(
        (m) => m.teamId === membership.teamId && m.driverId === membership.driverId,
      );

      if (existingIndex >= 0) {
        list[existingIndex] = membership;
        this.logger.info(`[saveMembership] Success - updated existing membership for team: ${membership.teamId}, driver: ${membership.driverId}.`);
      } else {
        list.push(membership);
        this.logger.info(`[saveMembership] Success - created new membership for team: ${membership.teamId}, driver: ${membership.driverId}.`);
      }

      this.membershipsByTeam.set(membership.teamId, list);
      return membership;
    } catch (error) {
      this.logger.error(`[saveMembership] Error saving membership for team ${membership.teamId}, driver ${membership.driverId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async removeMembership(teamId: string, driverId: string): Promise<void> {
    this.logger.debug(`[removeMembership] Entry - teamId: ${teamId}, driverId: ${driverId}`);
    try {
      const list = this.membershipsByTeam.get(teamId);
      if (!list) {
        this.logger.warn(`[removeMembership] No membership list found for team: ${teamId}. Cannot remove.`);
        return;
      }
      const index = list.findIndex((m) => m.driverId === driverId);
      if (index >= 0) {
        list.splice(index, 1);
        this.membershipsByTeam.set(teamId, list);
        this.logger.info(`[removeMembership] Success - removed membership for team: ${teamId}, driver: ${driverId}.`);
      } else {
        this.logger.info(`[removeMembership] Not found - membership for team: ${teamId}, driver: ${driverId}. Cannot remove.`);
      }
    } catch (error) {
      this.logger.error(`[removeMembership] Error removing membership for team ${teamId}, driver ${driverId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async getJoinRequests(teamId: string): Promise<TeamJoinRequest[]> {
    this.logger.debug(`[getJoinRequests] Entry - teamId: ${teamId}`);
    try {
      const requests = [...(this.joinRequestsByTeam.get(teamId) ?? [])];
      this.logger.info(`[getJoinRequests] Success - found ${requests.length} join requests for team: ${teamId}.`);
      return requests;
    } catch (error) {
      this.logger.error(`[getJoinRequests] Error getting join requests for team ${teamId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async saveJoinRequest(request: TeamJoinRequest): Promise<TeamJoinRequest> {
    this.logger.debug(`[saveJoinRequest] Entry - teamId: ${request.teamId}, driverId: ${request.driverId}, id: ${request.id}`);
    try {
      const list = this.getJoinRequestList(request.teamId);
      const existingIndex = list.findIndex((r) => r.id === request.id);

      if (existingIndex >= 0) {
        list[existingIndex] = request;
        this.logger.info(`[saveJoinRequest] Success - updated existing join request: ${request.id}.`);
      } else {
        list.push(request);
        this.logger.info(`[saveJoinRequest] Success - created new join request: ${request.id}.`);
      }

      this.joinRequestsByTeam.set(request.teamId, list);
      return request;
    } catch (error) {
      this.logger.error(`[saveJoinRequest] Error saving join request ${request.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async removeJoinRequest(requestId: string): Promise<void> {
    this.logger.debug(`[removeJoinRequest] Entry - requestId: ${requestId}`);
    try {
      let removed = false;
      for (const [teamId, list] of this.joinRequestsByTeam.entries()) {
        const index = list.findIndex((r) => r.id === requestId);
        if (index >= 0) {
          list.splice(index, 1);
          this.joinRequestsByTeam.set(teamId, list);
          removed = true;
          this.logger.info(`[removeJoinRequest] Success - removed join request ${requestId} from team ${teamId}.`);
          break;
        }
      }
      if (!removed) {
        this.logger.warn(`[removeJoinRequest] Not found - join request with ID ${requestId} not found for removal.`);
      }
    } catch (error) {
      this.logger.error(`[removeJoinRequest] Error removing join request ${requestId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}