import type Stripe from 'stripe';
import { PaymentErrorCode, type PaymentFailure } from '@/server/payments/provider.js';

const CODE_MAP: Record<string, PaymentErrorCode> = {
  card_declined: PaymentErrorCode.CARD_DECLINED,
  insufficient_funds: PaymentErrorCode.INSUFFICIENT_FUNDS,
  expired_card: PaymentErrorCode.TOKEN_EXPIRED,
  invalid_cvc: PaymentErrorCode.TOKEN_INVALID,
  invalid_number: PaymentErrorCode.TOKEN_INVALID,
  incorrect_number: PaymentErrorCode.TOKEN_INVALID,
  incorrect_cvc: PaymentErrorCode.TOKEN_INVALID,
  duplicate_transaction: PaymentErrorCode.DUPLICATE,
  authentication_required: PaymentErrorCode.AUTH_REQUIRED,
  processing_error: PaymentErrorCode.PROVIDER_ERROR,
  account_invalid: PaymentErrorCode.TERMINAL_INACTIVE,
};

export function mapStripeError(
  err: InstanceType<typeof Stripe.errors.StripeError>,
): PaymentFailure {
  const stripeCode = err.code ?? err.decline_code;
  let code = stripeCode ? CODE_MAP[stripeCode] : undefined;
  if (!code) {
    switch (err.type) {
      case 'StripeRateLimitError':
        code = PaymentErrorCode.RATE_LIMITED;
        break;
      case 'StripeCardError':
        code = err.decline_code ? PaymentErrorCode.CARD_DECLINED : PaymentErrorCode.PROVIDER_ERROR;
        break;
      default:
        code = PaymentErrorCode.UNKNOWN;
    }
  }
  return { ok: false, code, message: 'Payment declined' };
}

// PI status-based mapping (used by reconcile + finalize when no exception was thrown)
export function mapStripePaymentIntentFailure(pi: Stripe.PaymentIntent): PaymentFailure {
  if (pi.status === 'canceled') {
    return {
      ok: false,
      code:
        pi.cancellation_reason === 'automatic'
          ? PaymentErrorCode.HOLD_EXPIRED
          : PaymentErrorCode.PAYMENT_CANCELED,
      message: pi.cancellation_reason === 'automatic' ? 'Payment hold expired' : 'Payment canceled',
    };
  }
  const last = pi.last_payment_error;
  if (last) {
    return mapStripeError(last as unknown as InstanceType<typeof Stripe.errors.StripeError>);
  }
  return {
    ok: false,
    code: PaymentErrorCode.UNKNOWN,
    message: 'Payment could not be processed',
  };
}
