/**
 * Application Use Case: UpdatePaymentStatusUseCase
 *
 * Updates the status of a payment.
 */

import type { UseCase } from '@core/shared/application/UseCase';
import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { Payment } from '../../domain/entities/Payment';
import { PaymentStatus } from '../../domain/entities/Payment';
import type { PaymentRepository } from '../../domain/repositories/PaymentRepository';

export type UpdatePaymentStatusErrorCode = 'PAYMENT_NOT_FOUND';

export interface UpdatePaymentStatusInput {
  paymentId: string;
  status: PaymentStatus;
}

export interface UpdatePaymentStatusResult {
  payment: Payment;
}

export class UpdatePaymentStatusUseCase
  implements UseCase<UpdatePaymentStatusInput, UpdatePaymentStatusResult, UpdatePaymentStatusErrorCode>
{
  constructor(
    private readonly paymentRepository: PaymentRepository,
  ) {}

  async execute(input: UpdatePaymentStatusInput): Promise<Result<UpdatePaymentStatusResult, ApplicationErrorCode<UpdatePaymentStatusErrorCode>>> {
    const { paymentId, status } = input;

    const existingPayment = await this.paymentRepository.findById(paymentId);
    if (!existingPayment) {
      return Result.err({ code: 'PAYMENT_NOT_FOUND' as const });
    }

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

    const savedPayment = await this.paymentRepository.update(updatedPayment as Payment);

    return Result.ok({ payment: savedPayment });
  }
}