import { describe, expect, it, vi, type Mock } from 'vitest';
import { PayerType, PaymentStatus, PaymentType } from '../../domain/entities/Payment';
import type { PaymentRepository } from '../../domain/repositories/PaymentRepository';
import { UpdatePaymentStatusUseCase, type UpdatePaymentStatusInput } from './UpdatePaymentStatusUseCase';

describe('UpdatePaymentStatusUseCase', () => {
  let paymentRepository: {
    findById: Mock;
    update: Mock;
  };
  let useCase: UpdatePaymentStatusUseCase;

  beforeEach(() => {
    paymentRepository = {
      findById: vi.fn(),
      update: vi.fn(),
    };

    useCase = new UpdatePaymentStatusUseCase(
      paymentRepository as unknown as PaymentRepository,
    );
  });

  it('updates payment status and returns result', async () => {
    const input: UpdatePaymentStatusInput = {
      paymentId: 'payment-1',
      status: PaymentStatus.COMPLETED,
    };

    const existingPayment = {
      id: 'payment-1',
      type: PaymentType.SPONSORSHIP,
      amount: 100,
      platformFee: 5,
      netAmount: 95,
      payerId: 'payer-1',
      payerType: PayerType.SPONSOR,
      leagueId: 'league-1',
      status: PaymentStatus.PENDING,
      createdAt: new Date(),
    };

    const updatedPayment = {
      ...existingPayment,
      status: PaymentStatus.COMPLETED,
      completedAt: new Date(),
    };

    paymentRepository.findById.mockResolvedValue(existingPayment);
    paymentRepository.update.mockResolvedValue(updatedPayment);

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(paymentRepository.findById).toHaveBeenCalledWith('payment-1');
    expect(paymentRepository.update).toHaveBeenCalled();
    
    if (result.isOk()) {
      expect(result.value.payment).toEqual(updatedPayment);
    }
  });

  it('returns error when payment not found', async () => {
    const input: UpdatePaymentStatusInput = {
      paymentId: 'non-existent',
      status: PaymentStatus.COMPLETED,
    };

    paymentRepository.findById.mockResolvedValue(null);

    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);
    if (result.isErr()) {
      expect(result.error.code).toBe('PAYMENT_NOT_FOUND');
    }
  });
});