import { describe, it, expect, beforeEach } from 'vitest';

import type { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import type { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration';


import { Driver } from '@core/racing/domain/entities/Driver';
import type {
  TeamMembership,
  TeamMembershipStatus,
  TeamRole,
  TeamJoinRequest,
} from '@core/racing/domain/types/TeamMembership';

import { RegisterForRaceUseCase } from '@core/racing/application/use-cases/RegisterForRaceUseCase';
import { WithdrawFromRaceUseCase } from '@core/racing/application/use-cases/WithdrawFromRaceUseCase';
import { IsDriverRegisteredForRaceUseCase } from '@core/racing/application/use-cases/IsDriverRegisteredForRaceUseCase';
import { GetRaceRegistrationsUseCase } from '@core/racing/application/use-cases/GetRaceRegistrationsUseCase';












import type { IDriverRegistrationStatusPresenter } from '@core/racing/application/presenters/IDriverRegistrationStatusPresenter';
import type { IRaceRegistrationsPresenter } from '@core/racing/application/presenters/IRaceRegistrationsPresenter';
import type {
  IAllTeamsPresenter,
  AllTeamsResultDTO,
  AllTeamsViewModel,
} from '@core/racing/application/presenters/IAllTeamsPresenter';
import type { ITeamDetailsPresenter } from '@core/racing/application/presenters/ITeamDetailsPresenter';
import type {
  ITeamMembersPresenter,
  TeamMembersResultDTO,
  TeamMembersViewModel,
} from '@core/racing/application/presenters/ITeamMembersPresenter';
import type {
  ITeamJoinRequestsPresenter,
  TeamJoinRequestsResultDTO,
  TeamJoinRequestsViewModel,
} from '@core/racing/application/presenters/ITeamJoinRequestsPresenter';
import type {
  IDriverTeamPresenter,
  DriverTeamResultDTO,
  DriverTeamViewModel,
} from '@core/racing/application/presenters/IDriverTeamPresenter';
import type { RaceRegistrationsResultDTO } from '@core/racing/application/presenters/IRaceRegistrationsPresenter';

/**
 * Simple in-memory fakes mirroring current alpha behavior.
 */

class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepository {
  private registrations = new Map<string, Set<string>>(); // raceId -> driverIds

  async isRegistered(raceId: string, driverId: string): Promise<boolean> {
    const set = this.registrations.get(raceId);
    return set ? set.has(driverId) : false;
  }

  async getRegisteredDrivers(raceId: string): Promise<string[]> {
    const set = this.registrations.get(raceId);
    return set ? Array.from(set) : [];
  }

  async getRegistrationCount(raceId: string): Promise<number> {
    const set = this.registrations.get(raceId);
    return set ? set.size : 0;
  }

  async register(registration: RaceRegistration): Promise<void> {
    if (!this.registrations.has(registration.raceId)) {
      this.registrations.set(registration.raceId, new Set());
    }
    this.registrations.get(registration.raceId)!.add(registration.driverId);
  }

  async withdraw(raceId: string, driverId: string): Promise<void> {
    const set = this.registrations.get(raceId);
    if (!set || !set.has(driverId)) {
      throw new Error('Not registered for this race');
    }
    set.delete(driverId);
    if (set.size === 0) {
      this.registrations.delete(raceId);
    }
  }

  async getDriverRegistrations(driverId: string): Promise<string[]> {
    const result: string[] = [];
    for (const [raceId, set] of this.registrations.entries()) {
      if (set.has(driverId)) {
        result.push(raceId);
      }
    }
    return result;
  }

  async clearRaceRegistrations(raceId: string): Promise<void> {
    this.registrations.delete(raceId);
  }
}

class InMemoryLeagueMembershipRepositoryForRegistrations implements ILeagueMembershipRepository {
  private memberships: LeagueMembership[] = [];

  async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
    return (
      this.memberships.find(
        (m) => m.leagueId === leagueId && m.leagueId === leagueId && m.driverId === driverId,
      ) || null
    );
  }

  async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
    return this.memberships.filter(
      (m) => m.leagueId === leagueId && m.status === 'active',
    );
  }

  async getJoinRequests(): Promise<never> {
    throw new Error('Not needed for registration tests');
  }

  async saveMembership(membership: LeagueMembership): Promise<LeagueMembership> {
    this.memberships.push(membership);
    return membership;
  }

  async removeMembership(): Promise<void> {
    throw new Error('Not needed for registration tests');
  }

  async saveJoinRequest(): Promise<never> {
    throw new Error('Not needed for registration tests');
  }

  async removeJoinRequest(): Promise<never> {
    throw new Error('Not needed for registration tests');
  }

  seedActiveMembership(leagueId: string, driverId: string): void {
    this.memberships.push(
      LeagueMembership.create({
        leagueId,
        driverId,
        role: 'member',
        status: 'active' as MembershipStatus,
        joinedAt: new Date('2024-01-01'),
      }),
    );
  }
}

class TestDriverRegistrationStatusPresenter implements IDriverRegistrationStatusPresenter {
  isRegistered: boolean | null = null;
  raceId: string | null = null;
  driverId: string | null = null;

  present(isRegistered: boolean, raceId: string, driverId: string) {
    this.isRegistered = isRegistered;
    this.raceId = raceId;
    this.driverId = driverId;
    return {
      isRegistered,
      raceId,
      driverId,
    };
  }

  getViewModel() {
    return {
      isRegistered: this.isRegistered!,
      raceId: this.raceId!,
      driverId: this.driverId!,
    };
  }
}

class TestRaceRegistrationsPresenter implements IRaceRegistrationsPresenter {
  raceId: string | null = null;
  driverIds: string[] = [];

  reset(): void {
    this.raceId = null;
    this.driverIds = [];
  }

  present(input: RaceRegistrationsResultDTO) {
    this.driverIds = input.registeredDriverIds;
    this.raceId = null;
    return {
      registeredDriverIds: input.registeredDriverIds,
      count: input.registeredDriverIds.length,
    };
  }

  getViewModel() {
    return {
      registeredDriverIds: this.driverIds,
      count: this.driverIds.length,
    };
  }
}

class InMemoryTeamRepository implements ITeamRepository {
  private teams: Team[] = [];

  async findById(id: string): Promise<Team | null> {
    return this.teams.find((t) => t.id === id) || null;
  }

  async findAll(): Promise<Team[]> {
    return [...this.teams];
  }

  async findByLeagueId(leagueId: string): Promise<Team[]> {
    return this.teams.filter((t) => t.leagues.includes(leagueId));
  }

  async create(team: Team): Promise<Team> {
    this.teams.push(team);
    return team;
  }

  async update(team: Team): Promise<Team> {
    const index = this.teams.findIndex((t) => t.id === team.id);
    if (index >= 0) {
      this.teams[index] = team;
    } else {
      this.teams.push(team);
    }
    return team;
  }

  async delete(id: string): Promise<void> {
    this.teams = this.teams.filter((t) => t.id !== id);
  }

  async exists(id: string): Promise<boolean> {
    return this.teams.some((t) => t.id === id);
  }

  seedTeam(team: Team): void {
    this.teams.push(team);
  }
}

class InMemoryTeamMembershipRepository implements ITeamMembershipRepository {
  private memberships: TeamMembership[] = [];
  private joinRequests: TeamJoinRequest[] = [];

  async getMembership(teamId: string, driverId: string): Promise<TeamMembership | null> {
    return (
      this.memberships.find(
        (m) => m.teamId === teamId && m.driverId === driverId,
      ) || null
    );
  }

  async getActiveMembershipForDriver(driverId: string): Promise<TeamMembership | null> {
    return (
      this.memberships.find(
        (m) => m.driverId === driverId && m.status === 'active',
      ) || null
    );
  }

  async getTeamMembers(teamId: string): Promise<TeamMembership[]> {
    return this.memberships.filter(
      (m) => m.teamId === teamId && m.status === 'active',
    );
  }

  async findByTeamId(teamId: string): Promise<TeamMembership[]> {
    return this.memberships.filter((m) => m.teamId === teamId);
  }

  async saveMembership(membership: TeamMembership): Promise<TeamMembership> {
    const index = this.memberships.findIndex(
      (m) => m.teamId === membership.teamId && m.driverId === membership.driverId,
    );
    if (index >= 0) {
      this.memberships[index] = membership;
    } else {
      this.memberships.push(membership);
    }
    return membership;
  }

  async removeMembership(teamId: string, driverId: string): Promise<void> {
    this.memberships = this.memberships.filter(
      (m) => !(m.teamId === teamId && m.driverId === driverId),
    );
  }

  async getJoinRequests(teamId: string): Promise<TeamJoinRequest[]> {
    // For these tests we ignore teamId and return all,
    // allowing use-cases to look up by request ID only.
    return [...this.joinRequests];
  }

  async saveJoinRequest(request: TeamJoinRequest): Promise<TeamJoinRequest> {
    const index = this.joinRequests.findIndex((r) => r.id === request.id);
    if (index >= 0) {
      this.joinRequests[index] = request;
    } else {
      this.joinRequests.push(request);
    }
    return request;
  }

  async removeJoinRequest(requestId: string): Promise<void> {
    this.joinRequests = this.joinRequests.filter((r) => r.id !== requestId);
  }

  seedMembership(membership: TeamMembership): void {
    this.memberships.push(membership);
  }

  seedJoinRequest(request: TeamJoinRequest): void {
    this.joinRequests.push(request);
  }

  getAllMemberships(): TeamMembership[] {
    return [...this.memberships];
  }

  getAllJoinRequests(): TeamJoinRequest[] {
    return [...this.joinRequests];
  }

  async countByTeamId(teamId: string): Promise<number> {
    return this.memberships.filter((m) => m.teamId === teamId).length;
  }
}

describe('Racing application use-cases - registrations', () => {
  let registrationRepo: InMemoryRaceRegistrationRepository;
  let membershipRepo: InMemoryLeagueMembershipRepositoryForRegistrations;
  let registerForRace: RegisterForRaceUseCase;
  let withdrawFromRace: WithdrawFromRaceUseCase;
  let isDriverRegistered: IsDriverRegisteredForRaceUseCase;
  let getRaceRegistrations: GetRaceRegistrationsUseCase;
  let driverRegistrationPresenter: TestDriverRegistrationStatusPresenter;
  let raceRegistrationsPresenter: TestRaceRegistrationsPresenter;

  beforeEach(() => {
    registrationRepo = new InMemoryRaceRegistrationRepository();
    membershipRepo = new InMemoryLeagueMembershipRepositoryForRegistrations();

    registerForRace = new RegisterForRaceUseCase(registrationRepo, membershipRepo);
    withdrawFromRace = new WithdrawFromRaceUseCase(registrationRepo);
    driverRegistrationPresenter = new TestDriverRegistrationStatusPresenter();
    isDriverRegistered = new IsDriverRegisteredForRaceUseCase(
      registrationRepo,
      driverRegistrationPresenter,
    );
    raceRegistrationsPresenter = new TestRaceRegistrationsPresenter();
    getRaceRegistrations = new GetRaceRegistrationsUseCase(registrationRepo);
  });

  it('registers an active league member for a race and tracks registration', async () => {
    const raceId = 'race-1';
    const leagueId = 'league-1';
    const driverId = 'driver-1';

    membershipRepo.seedActiveMembership(leagueId, driverId);

    await registerForRace.execute({ raceId, leagueId, driverId });

    await isDriverRegistered.execute({ raceId, driverId });
    expect(driverRegistrationPresenter.isRegistered).toBe(true);
    expect(driverRegistrationPresenter.raceId).toBe(raceId);
    expect(driverRegistrationPresenter.driverId).toBe(driverId);

    await getRaceRegistrations.execute({ raceId }, raceRegistrationsPresenter);
    expect(raceRegistrationsPresenter.driverIds).toContain(driverId);
  });

  it('throws when registering a non-member for a race', async () => {
    const raceId = 'race-1';
    const leagueId = 'league-1';
    const driverId = 'driver-1';

    await expect(
      registerForRace.execute({ raceId, leagueId, driverId }),
    ).rejects.toThrow('Must be an active league member to register for races');
  });

  it('withdraws a registration and reflects state in queries', async () => {
    const raceId = 'race-1';
    const leagueId = 'league-1';
    const driverId = 'driver-1';

    membershipRepo.seedActiveMembership(leagueId, driverId);
    await registerForRace.execute({ raceId, leagueId, driverId });

    await withdrawFromRace.execute({ raceId, driverId });

    await isDriverRegistered.execute({ raceId, driverId });
    expect(driverRegistrationPresenter.isRegistered).toBe(false);

    await getRaceRegistrations.execute({ raceId }, raceRegistrationsPresenter);
    expect(raceRegistrationsPresenter.driverIds).toEqual([]);
  });
});

describe('Racing application use-cases - teams', () => {
  let teamRepo: InMemoryTeamRepository;
  let membershipRepo: InMemoryTeamMembershipRepository;

  let createTeam: CreateTeamUseCase;
  let joinTeam: JoinTeamUseCase;
  let leaveTeam: LeaveTeamUseCase;
  let approveJoin: ApproveTeamJoinRequestUseCase;
  let rejectJoin: RejectTeamJoinRequestUseCase;
  let updateTeamUseCase: UpdateTeamUseCase;
  let getAllTeamsUseCase: GetAllTeamsUseCase;
  let getTeamDetailsUseCase: GetTeamDetailsUseCase;
  let getTeamMembersUseCase: GetTeamMembersUseCase;
  let getTeamJoinRequestsUseCase: GetTeamJoinRequestsUseCase;
  let getDriverTeamUseCase: GetDriverTeamUseCase;

  class FakeDriverRepository {
    async findById(driverId: string): Promise<Driver | null> {
      return Driver.create({ id: driverId, iracingId: '123', name: `Driver ${driverId}`, country: 'US' });
    }

    async findByIRacingId(id: string): Promise<Driver | null> {
      return null;
    }

    async findAll(): Promise<Driver[]> {
      return [];
    }

    async create(driver: Driver): Promise<Driver> {
      return driver;
    }

    async update(driver: Driver): Promise<Driver> {
      return driver;
    }

    async delete(id: string): Promise<void> {
    }

    async exists(id: string): Promise<boolean> {
      return false;
    }

    async existsByIRacingId(iracingId: string): Promise<boolean> {
      return false;
    }

    async findByLeagueId(leagueId: string): Promise<Driver[]> {
      return [];
    }

    async findByTeamId(teamId: string): Promise<Driver[]> {
      return [];
    }
  }

  class FakeImageService {
    getDriverAvatar(driverId: string): string {
      return `https://example.com/avatar/${driverId}.png`;
    }

    getTeamLogo(teamId: string): string {
      return `https://example.com/logo/${teamId}.png`;
    }

    getLeagueCover(leagueId: string): string {
      return `https://example.com/cover/${leagueId}.png`;
    }

    getLeagueLogo(leagueId: string): string {
      return `https://example.com/logo/${leagueId}.png`;
    }
  }

  class TestAllTeamsPresenter implements IAllTeamsPresenter {
    private viewModel: AllTeamsViewModel | null = null;

    reset(): void {
      this.viewModel = null;
    }

    present(input: AllTeamsResultDTO): void {
      this.viewModel = {
        teams: input.teams.map((team) => ({
          id: team.id,
          name: team.name,
          tag: team.tag,
          description: team.description,
          memberCount: team.memberCount,
          leagues: team.leagues,
          specialization: (team as unknown).specialization,
          region: (team as unknown).region,
          languages: (team as unknown).languages,
        })),
        totalCount: input.teams.length,
      };
    }

    getViewModel(): AllTeamsViewModel | null {
      return this.viewModel;
    }

    get teams(): unknown[] {
      return this.viewModel?.teams ?? [];
    }
  }

  class TestTeamDetailsPresenter implements ITeamDetailsPresenter {
    viewModel: any = null;

    reset(): void {
      this.viewModel = null;
    }

    present(input: any): void {
      this.viewModel = input;
    }

    getViewModel(): any {
      return this.viewModel;
    }
  }

  class TestTeamMembersPresenter implements ITeamMembersPresenter {
    private viewModel: TeamMembersViewModel | null = null;

    reset(): void {
      this.viewModel = null;
    }

    present(input: TeamMembersResultDTO): void {
      const members = input.memberships.map((membership) => {
        const driverId = membership.driverId;
        const driverName = input.driverNames[driverId] ?? driverId;
        const avatarUrl = input.avatarUrls[driverId] ?? '';

        return {
          driverId,
          driverName,
          role: ((membership.role as unknown) === 'owner' ? 'owner' : (membership.role as unknown) === 'member' ? 'member' : (membership.role as unknown) === 'manager' ? 'manager' : (membership.role as unknown) === 'driver' ? 'member' : 'member') as "owner" | "member" | "manager",
          joinedAt: membership.joinedAt.toISOString(),
          isActive: membership.status === 'active',
          avatarUrl,
        };
      });

      const ownerCount = members.filter((m) => m.role === 'owner').length;
      const managerCount = members.filter((m) => m.role === 'manager').length;
      const memberCount = members.filter((m) => (m.role as unknown) === 'member').length;

      this.viewModel = {
        members,
        totalCount: members.length,
        ownerCount,
        managerCount,
        memberCount,
      };
    }

    getViewModel(): TeamMembersViewModel | null {
      return this.viewModel;
    }

    get members(): unknown[] {
      return this.viewModel?.members ?? [];
    }
  }

  class TestTeamJoinRequestsPresenter implements ITeamJoinRequestsPresenter {
    private viewModel: TeamJoinRequestsViewModel | null = null;

    reset(): void {
      this.viewModel = null;
    }

    present(input: TeamJoinRequestsResultDTO): void {
      const requests = input.requests.map((request) => {
        const driverId = request.driverId;
        const driverName = input.driverNames[driverId] ?? driverId;
        const avatarUrl = input.avatarUrls[driverId] ?? '';

        return {
          requestId: request.id,
          driverId,
          driverName,
          teamId: request.teamId,
          status: 'pending' as const,
          requestedAt: request.requestedAt.toISOString(),
          avatarUrl,
        };
      });

      const pendingCount = requests.filter((r) => r.status === 'pending').length;

      this.viewModel = {
        requests,
        pendingCount,
        totalCount: requests.length,
      };
    }

    getViewModel(): TeamJoinRequestsViewModel | null {
      return this.viewModel;
    }

    get requests(): unknown[] {
      return this.viewModel?.requests ?? [];
    }
  }

  class TestDriverTeamPresenter implements IDriverTeamPresenter {
    viewModel: DriverTeamViewModel | null = null;

    reset(): void {
      this.viewModel = null;
    }

    present(input: DriverTeamResultDTO): void {
      const { team, membership, driverId } = input;

      const isOwner = team.ownerId === driverId;
      const canManage = membership.role === 'owner' || membership.role === 'manager';

      this.viewModel = {
        team: {
          id: team.id,
          name: team.name,
          tag: team.tag,
          description: team.description,
          ownerId: team.ownerId,
          leagues: team.leagues,
        },
        membership: {
          role: (membership.role === 'owner' || membership.role === 'manager') ? membership.role : 'member' as "owner" | "member" | "manager",
          joinedAt: membership.joinedAt.toISOString(),
          isActive: membership.status === 'active',
        },
        isOwner,
        canManage,
      };
    }

    getViewModel(): DriverTeamViewModel | null {
      return this.viewModel;
    }
  }

  let allTeamsPresenter: TestAllTeamsPresenter;
  let teamDetailsPresenter: TestTeamDetailsPresenter;
  let teamMembersPresenter: TestTeamMembersPresenter;
  let teamJoinRequestsPresenter: TestTeamJoinRequestsPresenter;
  let driverTeamPresenter: TestDriverTeamPresenter;

  beforeEach(() => {
    teamRepo = new InMemoryTeamRepository();
    membershipRepo = new InMemoryTeamMembershipRepository();

    createTeam = new CreateTeamUseCase(teamRepo, membershipRepo);
    joinTeam = new JoinTeamUseCase(teamRepo, membershipRepo);
    leaveTeam = new LeaveTeamUseCase(membershipRepo);
    approveJoin = new ApproveTeamJoinRequestUseCase(membershipRepo);
    rejectJoin = new RejectTeamJoinRequestUseCase(membershipRepo);
    updateTeamUseCase = new UpdateTeamUseCase(teamRepo, membershipRepo);

    allTeamsPresenter = new TestAllTeamsPresenter();
    getAllTeamsUseCase = new GetAllTeamsUseCase(
      teamRepo,
      membershipRepo,
    );

    teamDetailsPresenter = new TestTeamDetailsPresenter();
    getTeamDetailsUseCase = new GetTeamDetailsUseCase(
      teamRepo,
      membershipRepo,
    );

    const driverRepository = new FakeDriverRepository();
    const imageService = new FakeImageService();

    teamMembersPresenter = new TestTeamMembersPresenter();
    getTeamMembersUseCase = new GetTeamMembersUseCase(
      membershipRepo,
      driverRepository,
      imageService,
      teamMembersPresenter,
    );
 
    teamJoinRequestsPresenter = new TestTeamJoinRequestsPresenter();
    getTeamJoinRequestsUseCase = new GetTeamJoinRequestsUseCase(
      membershipRepo,
      driverRepository,
      imageService,
      teamJoinRequestsPresenter,
    );

    driverTeamPresenter = new TestDriverTeamPresenter();
    getDriverTeamUseCase = new GetDriverTeamUseCase(
      teamRepo,
      membershipRepo,
      driverTeamPresenter,
    );
  });

  it('creates a team and assigns creator as active owner', async () => {
    const ownerId = 'driver-1';

    const result = await createTeam.execute({
      name: 'Apex Racing',
      tag: 'APEX',
      description: 'Professional GT3 racing',
      ownerId,
      leagues: ['league-1'],
    });

    expect(result.team.id).toBeDefined();
    expect(result.team.ownerId).toBe(ownerId);

    const membership = await membershipRepo.getActiveMembershipForDriver(ownerId);
    expect(membership?.teamId).toBe(result.team.id);
    expect(membership?.role as TeamRole).toBe('owner');
    expect(membership?.status as TeamMembershipStatus).toBe('active');
  });

  it('prevents driver from joining multiple teams and mirrors legacy error message', async () => {
    const ownerId = 'driver-1';
    const otherTeamId = 'team-2';

    // Seed an existing active membership
    membershipRepo.seedMembership({
      teamId: otherTeamId,
      driverId: ownerId,
      role: 'driver',
      status: 'active',
      joinedAt: new Date('2024-02-01'),
    });

    await expect(
      joinTeam.execute({ teamId: 'team-1', driverId: ownerId }),
    ).rejects.toThrow('Driver already belongs to a team');
  });

  it('approves a join request and moves it into active membership', async () => {
    const teamId = 'team-1';
    const driverId = 'driver-2';

    const request: TeamJoinRequest = {
      id: 'req-1',
      teamId,
      driverId,
      requestedAt: new Date('2024-03-01'),
      message: 'Let me in',
    };
    membershipRepo.seedJoinRequest(request);

    await approveJoin.execute({ requestId: request.id });

    const membership = await membershipRepo.getMembership(teamId, driverId);
    expect(membership).not.toBeNull();
    expect(membership?.status as TeamMembershipStatus).toBe('active');

    const remainingRequests = await membershipRepo.getJoinRequests(teamId);
    expect(remainingRequests.find((r) => r.id === request.id)).toBeUndefined();
  });

  it('rejects a join request and removes it', async () => {
    const teamId = 'team-1';
    const driverId = 'driver-2';

    const request: TeamJoinRequest = {
      id: 'req-2',
      teamId,
      driverId,
      requestedAt: new Date('2024-03-02'),
      message: 'Please?',
    };
    membershipRepo.seedJoinRequest(request);

    await rejectJoin.execute({ requestId: request.id });

    const remainingRequests = await membershipRepo.getJoinRequests(teamId);
    expect(remainingRequests.find((r) => r.id === request.id)).toBeUndefined();
  });

  it('updates team details when performed by owner or manager and reflects in queries', async () => {
    const ownerId = 'driver-1';
    const created = await createTeam.execute({
      name: 'Original Name',
      tag: 'ORIG',
      description: 'Original description',
      ownerId,
      leagues: [],
    });

    await updateTeamUseCase.execute({
      teamId: created.team.id,
      updates: { name: 'Updated Name', description: 'Updated description' },
      updatedBy: ownerId,
    });

    await getTeamDetailsUseCase.execute({ teamId: created.team.id, driverId: ownerId }, teamDetailsPresenter);

    expect(teamDetailsPresenter.viewModel.team.name).toBe('Updated Name');
    expect(teamDetailsPresenter.viewModel.team.description).toBe('Updated description');
  });

  it('returns driver team via query matching legacy getDriverTeam behavior', async () => {
    const ownerId = 'driver-1';

    const { team } = await createTeam.execute({
      name: 'Apex Racing',
      tag: 'APEX',
      description: 'Professional GT3 racing',
      ownerId,
      leagues: [],
    });

    await getDriverTeamUseCase.execute({ driverId: ownerId }, driverTeamPresenter);
    const result = driverTeamPresenter.viewModel;
    expect(result).not.toBeNull();
    expect(result?.team.id).toBe(team.id);
    expect(result?.membership.isActive).toBe(true);
    expect(result?.isOwner).toBe(true);
  });

  it('lists all teams and members via queries after multiple operations', async () => {
    const ownerId = 'driver-1';
    const otherDriverId = 'driver-2';

    const { team } = await createTeam.execute({
      name: 'Apex Racing',
      tag: 'APEX',
      description: 'Professional GT3 racing',
      ownerId,
      leagues: [],
    });

    await joinTeam.execute({ teamId: team.id, driverId: otherDriverId });

    await getAllTeamsUseCase.execute(undefined as void, allTeamsPresenter);
    expect(allTeamsPresenter.teams.length).toBe(1);

    await getTeamMembersUseCase.execute({ teamId: team.id }, teamMembersPresenter);
    const memberIds = teamMembersPresenter.members.map((m) => m.driverId).sort();
    expect(memberIds).toEqual([ownerId, otherDriverId].sort());
  });
});