/**
 * Application Use Case: CreatePaymentUseCase
 *
 * Creates a new payment.
 */

import type { IPaymentRepository } from '../../domain/repositories/IPaymentRepository';
import type { PaymentType, PayerType, PaymentStatus, Payment } from '../../domain/entities/Payment';
import type {
  ICreatePaymentPresenter,
  CreatePaymentResultDTO,
  CreatePaymentViewModel,
} from '../presenters/ICreatePaymentPresenter';
import type { UseCase } from '@core/shared/application/UseCase';

const PLATFORM_FEE_RATE = 0.10;

export interface CreatePaymentInput {
  type: PaymentType;
  amount: number;
  payerId: string;
  payerType: PayerType;
  leagueId: string;
  seasonId?: string;
}

export class CreatePaymentUseCase
  implements UseCase<CreatePaymentInput, CreatePaymentResultDTO, CreatePaymentViewModel, ICreatePaymentPresenter>
{
  constructor(private readonly paymentRepository: IPaymentRepository) {}

  async execute(
    input: CreatePaymentInput,
    presenter: ICreatePaymentPresenter,
  ): Promise<void> {
    presenter.reset();

    const { type, amount, payerId, payerType, leagueId, seasonId } = input;

    const platformFee = amount * PLATFORM_FEE_RATE;
    const netAmount = amount - platformFee;

    const id = `payment-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    const payment: Payment = {
      id,
      type,
      amount,
      platformFee,
      netAmount,
      payerId,
      payerType,
      leagueId,
      seasonId,
      status: 'pending' as PaymentStatus,
      createdAt: new Date(),
    };

    const createdPayment = await this.paymentRepository.create(payment);

    const dto: CreatePaymentResultDTO = {
      payment: {
        id: createdPayment.id,
        type: createdPayment.type,
        amount: createdPayment.amount,
        platformFee: createdPayment.platformFee,
        netAmount: createdPayment.netAmount,
        payerId: createdPayment.payerId,
        payerType: createdPayment.payerType,
        leagueId: createdPayment.leagueId,
        seasonId: createdPayment.seasonId,
        status: createdPayment.status,
        createdAt: createdPayment.createdAt,
        completedAt: createdPayment.completedAt,
      },
    };

    presenter.present(dto);
  }
}