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

import { TypeOrmTeamMembershipRepository, TypeOrmTeamRepository } from './TeamTypeOrmRepositories';

describe('TypeOrmTeamRepository', () => {
  it('uses injected repo + mapper (DB-free)', async () => {
    const ormEntity = { id: 'team-1' };

    const repo = {
      findOne: vi.fn().mockResolvedValue(ormEntity),
      find: vi.fn(),
      save: vi.fn(),
      delete: vi.fn(),
      count: vi.fn(),
      createQueryBuilder: vi.fn(),
    };

    const mapper = {
      toDomain: vi.fn().mockReturnValue({ id: 'domain-team' }),
      toOrmEntity: vi.fn().mockReturnValue({ id: 'team-1-orm' }),
    };

    const teamRepo = new TypeOrmTeamRepository(repo as any, mapper as any);

    const team = await teamRepo.findById('team-1');

    expect(repo.findOne).toHaveBeenCalledWith({ where: { id: 'team-1' } });
    expect(mapper.toDomain).toHaveBeenCalledWith(ormEntity);
    expect(team).toEqual({ id: 'domain-team' });
  });

  it('create uses mapper.toOrmEntity + repo.save', async () => {
    const repo = {
      save: vi.fn().mockResolvedValue(undefined),
    };

    const mapper = {
      toOrmEntity: vi.fn().mockReturnValue({ id: 'team-1-orm' }),
    };

    const teamRepo = new TypeOrmTeamRepository(repo as any, mapper as any);

    const domainTeam = { id: 'team-1' };

    await expect(teamRepo.create(domainTeam as any)).resolves.toBe(domainTeam);

    expect(mapper.toOrmEntity).toHaveBeenCalledWith(domainTeam);
    expect(repo.save).toHaveBeenCalledWith({ id: 'team-1-orm' });
  });
});

describe('TypeOrmTeamMembershipRepository', () => {
  it('getMembership returns null when TypeORM returns null (DB-free)', async () => {
    const membershipRepo = {
      findOne: vi.fn().mockResolvedValue(null),
      find: vi.fn(),
      save: vi.fn(),
      delete: vi.fn(),
      count: vi.fn(),
    };

    const joinRequestRepo = {
      find: vi.fn(),
      save: vi.fn(),
      delete: vi.fn(),
    };

    const mapper = {
      toDomainMembership: vi.fn(),
      toOrmMembership: vi.fn(),
      toDomainJoinRequest: vi.fn(),
      toOrmJoinRequest: vi.fn(),
    };

    const repo = new TypeOrmTeamMembershipRepository(
      membershipRepo as any,
      joinRequestRepo as any,
      mapper as any,
    );

    await expect(repo.getMembership('team-1', 'driver-1')).resolves.toBeNull();
    expect(membershipRepo.findOne).toHaveBeenCalledWith({ where: { teamId: 'team-1', driverId: 'driver-1' } });
    expect(mapper.toDomainMembership).not.toHaveBeenCalled();
  });

  it('saveMembership uses mapper.toOrmMembership + repo.save', async () => {
    const membershipRepo = {
      save: vi.fn().mockResolvedValue(undefined),
    };

    const joinRequestRepo = {
      find: vi.fn(),
      save: vi.fn(),
      delete: vi.fn(),
    };

    const mapper = {
      toOrmMembership: vi.fn().mockReturnValue({ teamId: 'team-1', driverId: 'driver-1' }),
    };

    const repo = new TypeOrmTeamMembershipRepository(
      membershipRepo as any,
      joinRequestRepo as any,
      mapper as any,
    );

    const membership = {
      teamId: 'team-1',
      driverId: 'driver-1',
      role: 'driver',
      status: 'active',
      joinedAt: new Date('2025-01-01T00:00:00.000Z'),
    };

    await expect(repo.saveMembership(membership as any)).resolves.toBe(membership);

    expect(mapper.toOrmMembership).toHaveBeenCalledWith(membership);
    expect(membershipRepo.save).toHaveBeenCalledWith({ teamId: 'team-1', driverId: 'driver-1' });
  });
});