import type { SponsorAccount } from '@core/identity/domain/entities/SponsorAccount';
import { UserId } from '@core/identity/domain/value-objects/UserId';
import type { Logger } from '@core/shared/domain/Logger';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { InMemorySponsorAccountRepository } from './InMemorySponsorAccountRepository';

describe('InMemorySponsorAccountRepository', () => {
  let repository: InMemorySponsorAccountRepository;
  let logger: Logger;

  const makeAccount = (id: string, sponsorId: string, email: string): SponsorAccount => {
    return {
      getId: () => ({ value: id }),
      getSponsorId: () => sponsorId,
      getEmail: () => email,
    } as unknown as SponsorAccount;
  };

  beforeEach(() => {
    logger = {
      debug: vi.fn(),
      info: vi.fn(),
      warn: vi.fn(),
      error: vi.fn(),
    } as unknown as Logger;

    repository = new InMemorySponsorAccountRepository(logger);
    repository.clear();
  });

  it('saves and finds sponsor accounts by id / sponsorId / email', async () => {
    const account = makeAccount('user-1', 'sponsor-1', 'Sponsor@Example.com');

    await repository.save(account);

    expect(await repository.findById(UserId.fromString('user-1'))).toBe(account);
    expect(await repository.findBySponsorId('sponsor-1')).toBe(account);
    expect(await repository.findByEmail('sponsor@example.com')).toBe(account);
  });

  it('deletes sponsor accounts', async () => {
    const account = makeAccount('user-del', 'sponsor-del', 'del@example.com');
    await repository.save(account);

    await repository.delete(UserId.fromString('user-del'));
    expect(await repository.findById(UserId.fromString('user-del'))).toBeNull();
  });

  it('seeds via constructor', async () => {
    const seeded = makeAccount('user-seed', 'sponsor-seed', 'seed@example.com');
    repository = new InMemorySponsorAccountRepository(logger, [seeded]);

    expect(await repository.findBySponsorId('sponsor-seed')).toBe(seeded);
  });
});
