import { BN } from '@ocap/util';
import { Op, type WhereOptions } from 'sequelize';
import { PaymentIntent, Refund } from '../store/models';
import logger from './logger';

export async function getRefundAmountSetup({
  currencyId,
  customerId,
  subscriptionId,
  PaymentMethodId,
  paymentIntentId,
}: {
  currencyId?: string;
  customerId?: string;
  subscriptionId?: string;
  PaymentMethodId?: string;
  paymentIntentId: string;
}) {
  const paymentIntent = await PaymentIntent.findByPk(paymentIntentId);
  if (!paymentIntent) {
    throw new Error('PaymentIntent not found');
  }
  const where: WhereOptions<Refund> = {
    status: {
      [Op.not]: 'canceled',
    },
    payment_intent_id: paymentIntentId,
    amount: {
      [Op.gt]: '0',
    },
  };
  if (currencyId) {
    where.currency_id = currencyId;
  }
  if (customerId) {
    where.customer_id = customerId;
  }
  if (subscriptionId) {
    where.subscription_id = subscriptionId;
  }
  if (PaymentMethodId) {
    where.payment_method_id = PaymentMethodId;
  }
  const { rows: list, count } = await Refund.findAndCountAll({
    where,
    include: [],
  });
  if (count === 0) {
    logger.info('No refund found for payment intent', {
      paymentIntentId,
    });
    return {
      amount: paymentIntent.amount_received || '0',
      totalAmount: paymentIntent.amount_received,
    };
  }
  let refundedAmountBN = new BN('0');
  list.forEach((refund) => {
    if (refund) {
      refundedAmountBN = refundedAmountBN.add(new BN(refund.amount || '0'));
    }
  });

  return {
    amount: new BN(paymentIntent.amount_received).sub(refundedAmountBN).toString(),
    totalAmount: paymentIntent.amount_received,
  };
}

export function isRefundReasonSupportedByStripe(reason: string) {
  return ['duplicate', 'requested_by_customer', 'fraudulent'].includes(reason);
}
