import { parseAbbrValue } from './parseAbbrValue'
import { removeSeparators } from './removeSeparators'
import { removeInvalidChars } from './removeInvalidChars'
import { escapeRegExp } from './escapeRegExp'
import { type CurrencyInputProps } from '../CurrencyInputProps'

export type CleanValueOptions = Pick<
CurrencyInputProps,
| 'decimalSeparator'
| 'groupSeparator'
| 'allowDecimals'
| 'decimalsLimit'
| 'allowNegativeValue'
| 'disableAbbreviations'
| 'prefix'
| 'transformRawValue'
> & { value: string }

/**
 * Remove prefix, separators and extra decimals from value
 */
export const cleanValue = ({
  value,
  groupSeparator = ',',
  decimalSeparator = '.',
  allowDecimals = true,
  decimalsLimit = 2,
  allowNegativeValue = true,
  disableAbbreviations = false,
  prefix = '',
  transformRawValue = (rawValue) => rawValue
}: CleanValueOptions): string => {
  const transformedValue = transformRawValue(value)

  if (transformedValue === '-') {
    return transformedValue
  }

  const abbreviations = disableAbbreviations ? [] : ['k', 'm', 'b']
  const reg = new RegExp(`((^|\\D)-\\d)|(-${escapeRegExp(prefix)})`)
  const isNegative = reg.test(transformedValue)

  // Is there a digit before the prefix? eg. 1$
  const [prefixWithValue, preValue] = RegExp(`(\\d+)-?${escapeRegExp(prefix)}`).exec(value) || []
  const withoutPrefix = prefix
    ? prefixWithValue
      ? transformedValue.replace(prefixWithValue, '').concat(preValue)
      : transformedValue.replace(prefix, '')
    : transformedValue
  const withoutSeparators = removeSeparators(withoutPrefix, groupSeparator)
  const withoutInvalidChars = removeInvalidChars(withoutSeparators, [
    groupSeparator,
    decimalSeparator,
    ...abbreviations
  ])

  let valueOnly = withoutInvalidChars

  if (!disableAbbreviations) {
    // disallow letter without number
    if (
      abbreviations.some(
        (letter) => letter === withoutInvalidChars.toLowerCase().replace(decimalSeparator, '')
      )
    ) {
      return ''
    }
    const parsed = parseAbbrValue(withoutInvalidChars, decimalSeparator)
    if (parsed) {
      valueOnly = String(parsed)
    }
  }

  const includeNegative = isNegative && allowNegativeValue ? '-' : ''

  if (decimalSeparator && valueOnly.includes(decimalSeparator)) {
    const [int, decimals] = withoutInvalidChars.split(decimalSeparator)
    const trimmedDecimals = decimalsLimit && decimals ? decimals.slice(0, decimalsLimit) : decimals
    const includeDecimals = allowDecimals ? `${decimalSeparator}${trimmedDecimals}` : ''

    return `${includeNegative}${int}${includeDecimals}`
  }

  return `${includeNegative}${valueOnly}`
}
