import { ForbiddenException } from '@nestjs/common';
import { RoleEnum } from '../roles/roles.enum';
import { TeamAccessService } from './team-access.service';

describe('TeamAccessService', () => {
  const userRepository = { findOne: jest.fn() };
  const playerRepository = { find: jest.fn() };
  let service: TeamAccessService;

  beforeEach(() => {
    jest.resetAllMocks();
    service = new TeamAccessService(
      userRepository as any,
      playerRepository as any,
    );
  });

  it('allows a global admin without a team membership', async () => {
    userRepository.findOne.mockResolvedValue({
      id: 1,
      role: { id: RoleEnum.admin },
    });

    await expect(service.assertManager(1, 9)).resolves.toBeUndefined();
    expect(playerRepository.find).not.toHaveBeenCalled();
  });

  it('allows an active team member to read sharing status', async () => {
    userRepository.findOne.mockResolvedValue({
      id: 2,
      role: { id: RoleEnum.user },
    });
    playerRepository.find.mockResolvedValue([
      { active: true, teamRole: { id: 1 } },
    ]);

    await expect(service.assertMember(2, 9)).resolves.toBeUndefined();
  });

  it.each([3, 4, 5])(
    'allows active team role %s to manage sharing',
    async (roleId) => {
      userRepository.findOne.mockResolvedValue({
        id: 2,
        role: { id: RoleEnum.user },
      });
      playerRepository.find.mockResolvedValue([
        { active: true, teamRole: { id: roleId } },
      ]);

      await expect(service.assertManager(2, 9)).resolves.toBeUndefined();
    },
  );

  it('uses the highest role when one user has multiple players in a team', async () => {
    userRepository.findOne.mockResolvedValue({
      id: 2,
      role: { id: RoleEnum.user },
    });
    playerRepository.find.mockResolvedValue([
      { active: true, teamRole: { id: 1 } },
      { active: true, teamRole: { id: 3 } },
    ]);

    await expect(service.assertManager(2, 9)).resolves.toBeUndefined();
  });

  it.each([
    ['a player', [{ active: true, teamRole: { id: 1 } }]],
    ['a second treasurer', [{ active: true, teamRole: { id: 2 } }]],
    ['an inactive captain', [{ active: false, teamRole: { id: 3 } }]],
    ['a non-member', []],
  ])('rejects %s from managing sharing', async (_label, players) => {
    userRepository.findOne.mockResolvedValue({
      id: 2,
      role: { id: RoleEnum.user },
    });
    playerRepository.find.mockResolvedValue(players);

    await expect(service.assertManager(2, 9)).rejects.toBeInstanceOf(
      ForbiddenException,
    );
  });
});
