import { BigNumberInput } from '@medusajs/framework/types'
import { BigNumber, MathBN } from '@medusajs/framework/utils'

function getCurrencyMultiplier(currency) {
  const currencyMultipliers = {
    0: [
      'BIF',
      'CLP',
      'DJF',
      'GNF',
      'JPY',
      'KMF',
      'KRW',
      'MGA',
      'PYG',
      'RWF',
      'UGX',
      'VND',
      'VUV',
      'XAF',
      'XOF',
      'XPF'
    ],
    3: ['BHD', 'IQD', 'JOD', 'KWD', 'OMR', 'TND']
  }

  currency = currency.toUpperCase()
  let power = 2
  for (const [key, value] of Object.entries(currencyMultipliers)) {
    if (value.includes(currency)) {
      power = parseInt(key, 10)
      break
    }
  }
  return Math.pow(10, power)
}

/**
 * Converts an amount to the format required by Stripe based on currency.
 * https://docs.stripe.com/currencies
 * @param {BigNumberInput} amount - The amount to be converted.
 * @param {string} currency - The currency code (e.g., 'USD', 'JOD').
 * @returns {number} - The converted amount in the smallest currency unit.
 */
export function getSmallestUnit(
  amount: BigNumberInput,
  currency: string
): number {
  const multiplier = getCurrencyMultiplier(currency)

  const amount_ =
    Math.round(new BigNumber(MathBN.mult(amount, multiplier)).numeric) /
    multiplier

  const smallestAmount = new BigNumber(MathBN.mult(amount_, multiplier))

  let numeric = smallestAmount.numeric
  // Check if the currency requires rounding to the nearest ten
  if (multiplier === 1e3) {
    numeric = Math.ceil(numeric / 10) * 10
  }

  return parseInt(numeric.toString().split('.').shift()!, 10)
}

/**
 * Converts an amount from the smallest currency unit to the standard unit based on currency.
 * @param {BigNumberInput} amount - The amount in the smallest currency unit.
 * @param {string} currency - The currency code (e.g., 'USD', 'JOD').
 * @returns {number} - The converted amount in the standard currency unit.
 */
export function getAmountFromSmallestUnit(
  amount: BigNumberInput,
  currency: string
): number {
  const multiplier = getCurrencyMultiplier(currency)
  const standardAmount = new BigNumber(MathBN.div(amount, multiplier))
  return standardAmount.numeric
}
