import { type ElementType } from 'react'
import type React from 'react'

type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U

/**
 * Value in different formats
 *
 * @experimental
 */
export interface CurrencyInputOnChangeValues {
  /**
   * Value as float or null if empty
   *
   * Example:
   *   "1.99" > 1.99
   *   "" > null
   */
  float: number | null

  /**
   * Value after applying formatting
   *
   * Example: "1000000" > "1,000,0000"
   */
  formatted: string

  /**
   * Non formatted value as string
   */
  value: string
}

export type IntlConfig = {
  locale: string
} & Intl.NumberFormatOptions

export type CurrencyInputProps = Overwrite<
React.ComponentPropsWithRef<'input'>,
{
  /**
     * Allow decimals
     *
     * Default = true
     */
  allowDecimals?: boolean

  /**
     * Allow user to enter negative value
     *
     * Default = true
     */
  allowNegativeValue?: boolean

  /**
     * Component id
     */
  id?: string

  /**
     *  Maximum characters the user can enter
     */
  maxLength?: number

  /**
     * Class names
     */
  className?: string

  /**
     * Custom component
     *
     * Default = <input/>
     */
  customInput?: ElementType

  /**
     * Limit length of decimals allowed
     *
     * Default = 2
     */
  decimalsLimit?: number

  /**
     * Specify decimal scale for padding/trimming
     *
     * Example:
     *   1.5 -> 1.50
     *   1.234 -> 1.23
     */
  decimalScale?: number

  /**
     * Default value if not passing in value via props
     */
  defaultValue?: number | string

  /**
     * Disabled
     *
     * Default = false
     */
  disabled?: boolean

  /**
     * Value will always have the specified length of decimals
     *
     * Example:
     *   123 -> 1.23
     *
     * Note: This formatting only happens onBlur
     */
  fixedDecimalLength?: number

  /**
     * Handle change in value
     */
  onValueChange?: (
    value: string | undefined | number,
    name?: string,
    values?: CurrencyInputOnChangeValues
  ) => void

  /**
     * Placeholder if there is no value
     */
  placeholder?: string

  /**
     * Include a prefix eg. £
     */
  prefix?: string

  /**
     * Include a suffix eg. €
     */
  suffix?: string

  /**
     * Incremental value change on arrow down and arrow up key press
     */
  step?: number

  /**
     * Separator between integer part and fractional part of value.
     *
     * This cannot be a number
     */
  decimalSeparator?: string

  /**
     * Separator between thousand, million and billion
     *
     * This cannot be a number
     */
  groupSeparator?: string

  /**
     * Disable auto adding separator between values eg. 1000 -> 1,000
     *
     * Default = false
     */
  disableGroupSeparators?: boolean

  /**
     * Disable abbreviations (m, k, b)
     *
     * Default = false
     */
  disableAbbreviations?: boolean

  /**
     * International locale config, examples:
     *   { locale: 'ja-JP', currency: 'JPY' }
     *   { locale: 'en-IN', currency: 'INR' }
     *
     * Any prefix, groupSeparator or decimalSeparator options passed in
     * will override Intl Locale config
     */
  intlConfig?: IntlConfig

  /**
     * Transform the raw value form the input before parsing
     */
  transformRawValue?: (rawValue: string) => string

  /**
     * When set to false, the formatValueOnBlur flag disables the application of the __onValueChange__ function
     * specifically on blur events. If disabled or set to false, the onValueChange will not trigger on blur.
     * Default = true
     */
  formatValueOnBlur?: boolean

  /**
     * Name of the input
     */
  label?: string
}
>
