import type { MemberPayment } from '@core/payments/domain/entities/MemberPayment';
import { MemberPaymentStatus } from '@core/payments/domain/entities/MemberPayment';
import type { MembershipFee } from '@core/payments/domain/entities/MembershipFee';
import { MembershipFeeType } from '@core/payments/domain/entities/MembershipFee';
import type { Logger } from '@core/shared/domain/Logger';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { InMemoryMemberPaymentRepository, InMemoryMembershipFeeRepository } from './InMemoryMembershipFeeRepository';

describe('InMemoryMembershipFeeRepository', () => {
  let feeRepo: InMemoryMembershipFeeRepository;
  let paymentRepo: InMemoryMemberPaymentRepository;
  let logger: Logger;

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

    feeRepo = new InMemoryMembershipFeeRepository(logger);
    paymentRepo = new InMemoryMemberPaymentRepository(logger);
  });

  it('creates and finds membership fees', async () => {
    const fee: MembershipFee = {
      id: 'fee-1',
      leagueId: 'league-1',
      type: MembershipFeeType.SEASON,
      amount: 100,
      enabled: true,
      createdAt: new Date('2025-01-01T00:00:00.000Z'),
      updatedAt: new Date('2025-01-01T00:00:00.000Z'),
    };

    await feeRepo.create(fee);

    expect((await feeRepo.findById('fee-1'))?.id).toBe('fee-1');
    expect((await feeRepo.findByLeagueId('league-1'))?.id).toBe('fee-1');

    const updated = await feeRepo.update({
      ...fee,
      amount: 120,
      updatedAt: new Date('2025-01-02T00:00:00.000Z'),
    });
    expect(updated.amount).toBe(120);
  });

  it('creates and queries member payments by league via fee lookup', async () => {
    const fee1: MembershipFee = {
      id: 'fee-a',
      leagueId: 'league-a',
      type: MembershipFeeType.SEASON,
      amount: 100,
      enabled: true,
      createdAt: new Date('2025-01-01T00:00:00.000Z'),
      updatedAt: new Date('2025-01-01T00:00:00.000Z'),
    };
    const fee2: MembershipFee = {
      id: 'fee-b',
      leagueId: 'league-b',
      type: MembershipFeeType.SEASON,
      amount: 50,
      enabled: true,
      createdAt: new Date('2025-01-01T00:00:00.000Z'),
      updatedAt: new Date('2025-01-01T00:00:00.000Z'),
    };

    await feeRepo.create(fee1);
    await feeRepo.create(fee2);

    const p1: MemberPayment = {
      id: 'mp-1',
      feeId: 'fee-a',
      driverId: 'driver-1',
      amount: 100,
      platformFee: 5,
      netAmount: 95,
      status: MemberPaymentStatus.PENDING,
      dueDate: new Date('2025-02-01T00:00:00.000Z'),
    };
    const p2: MemberPayment = {
      id: 'mp-2',
      feeId: 'fee-b',
      driverId: 'driver-1',
      amount: 50,
      platformFee: 2.5,
      netAmount: 47.5,
      status: MemberPaymentStatus.PENDING,
      dueDate: new Date('2025-02-01T00:00:00.000Z'),
    };

    await paymentRepo.create(p1);
    await paymentRepo.create(p2);

    expect((await paymentRepo.findByFeeIdAndDriverId('fee-a', 'driver-1'))?.id).toBe('mp-1');

    const leagueAPayments = await paymentRepo.findByLeagueIdAndDriverId('league-a', 'driver-1', feeRepo);
    expect(leagueAPayments.map(p => p.id)).toEqual(['mp-1']);
  });
});
