import React, {createRef, FC, ReactNode, useEffect, useRef, useState} from "react";
import classNames from "classnames";
import {debounce} from 'lodash'
import {lastChanged, NumberFieldType} from "./LastChanged";
import getSymbolFromCurrency from "currency-symbol-map";
import {__, CouponsPlus} from "../../globals";
import input from "../../fields/Input";
import {renderCurrencyValue} from "./helpers";

export type NumberInputProps = {
    id?: string, // this needs to be unique if you have several instances at once, for focusing the input on change
    numberId: string, // this may be repeated from a group
    fieldType: NumberFieldType, // even this, but this is enough for single ranges (no extra instances)
    value: number,
    onChange: (value: number) => void,
    type?: 'currency' | 'percentage' | 'free' | 'custom',
    customRenderer?: ReactNode, // for 'custom' === type (unexpected yoda)
    labels?: {
        inputRightOutside: string | ReactNode;
        inputLeftOutside: string | ReactNode;
        top?: string,
        bottom?: string,
        beforeSymbol?: string,
        afterSymbol?: string,
        inputLeft?: string | ReactNode,
        inputRight?: string | ReactNode,
        lineHeight?: {
            top?: string,
            bottom?: string,
        }
    },
    input?: {
        top?: FC
    },
    size?: 'normal' | 'small',
}

type ButtonAction = 'increase' | 'decrease';

function convert(value: string | number) {
    return typeof value === 'string'? value.includes('.') ? parseFloat(value) : parseInt(value) : value
}

export const NumberInput: FC<NumberInputProps> = ({
                                                      id,
                                                      numberId,
                                                      fieldType,
                                                      value,
                                                      onChange,
                                                      type,
                                                      labels,
                                                      input,
                                                      size = 'normal',
                                                      customRenderer
                                                  }) => {
    const [pressed, setPressed] = useState<ButtonAction | null>(null);
    const [focused, setFocused] = useState<boolean>(false);
    const inputRef = useRef<HTMLInputElement | null>(null)


    // @ts-ignore
    useEffect(() => {
        if (value == 0) {
            return
        }
        if (!value) {
            onChange(0)
        }
    }, [value])
    const increaseOrDecrease = (action: ButtonAction) => () => onChange(action === 'increase' ? value + 1 : value - 1);

    if (pressed !== null) {
        debounce(increaseOrDecrease(pressed), 80)()
    }

    /**
     * Because the re-rendering seems to be too slow (that's my guess)
     * Everytime the user enters 2 or more digits at once, the input gets blurred and the second number never gets captured
     * so let's focus this everytime the value changes so that the user may add several numbers at once (eg: type the number "20")
     */
    useEffect(() => {
        /**
         * Unfortunately, due to re-renders we have to use this hack. otherwise, the range field would always focus the second input since
         * for some reason this component is unmounting and mounting on every update.
         * I know i should probably fox the root, but that could probably take DAYS which I don't have rn.
         */
        if (lastChanged.fieldType === 'text') {
            return
        }
        if (false && typeof lastChanged.id !== 'undefined') {
            // only there's an id, halt execution if its not this one
            if (lastChanged.id !== id) {
                return
            }
        }
        if (lastChanged.numberId === numberId && lastChanged.fieldType === fieldType) {
            inputRef.current?.focus()
        }
    }, [value, pressed])

    const fontSizes = {
        normal: 'text-5x',
        small: 'text-3x',
    }

    const isCustomRender = type === 'custom' || type === 'free';

    return <>
        {labels?.beforeSymbol}
        {input?.top && <input.top/>}
        <div
            className={classNames('flex flex-col items-center bg-white/[.40]  rounded-1 --border-gray-150 --border-[2px] text-5x text-gray-750 font-semibold', {
                [`py-2 px-4 ${fontSizes[size]}`]: size === 'normal',
                [`py-0 px-1 ${fontSizes[size]}`]: size === 'small',
            })}>
            {labels?.top && <p className={`text-gray-500 ${labels?.lineHeight?.top}`}>{labels.top}</p>}
            <div className="flex items-center space-x-3">
                {labels?.inputLeftOutside}
                {!isCustomRender && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
                                         className={classNames('p-[2px] bg-gray-200 bg-opacity-40 rounded-full active:scale-[.80] transition-all duration-75 hover:cursor-pointer', {
                                             'min-w-4 min-h-4 max-w-4 max-h-4': size === 'normal',
                                             'min-w-[14px] min-h-[14px] max-w-[14px] max-h-[14px]': size === 'small',
                                         })}
                                         onMouseDownCapture={() => {
                                             // we need to overhaul it here.
                                             // so first
                                             /**
                                              * 1 - add a settimeout listener, to only trigger this after about 150ms
                                              * 2- then check if after that its still pressed, if so, start the autp-icnrease
                                              * 3- if not, that means it was a simple clieck, so abandon it.
                                              *
                                              */
                                             // lets ignore it for now as it is clashing with regular clicks
                                             //setPressed('increase')
                                             increaseOrDecrease('decrease')()
                                         }}
                                         onMouseUpCapture={() => setPressed(null)}>
                    <path fillRule="evenodd"
                          d="M4.25 12a.75.75 0 0 1 .75-.75h14a.75.75 0 0 1 0 1.5H5a.75.75 0 0 1-.75-.75Z"
                          clipRule="evenodd"/>
                </svg>}
                <div className="flex items-center space-x-0">
                    {labels?.inputLeft}
                    {(type === 'currency' ? renderCurrencyValue : v => v)(<>
                        {type === 'free' && <span className={'--text-greenb-90'}>{__('FREE')}</span>}
                        {type === 'custom' && customRenderer}
                        {!isCustomRender && <input key={numberId} ref={inputRef}
                                                   type="number"
                                                   className={classNames("px-0 h-8 !min-h-[auto] border-none text-gray-750 font-bold bg-transparent focus:border-transparent focus:shadow-none no-spin-button", {
                                                       [`${fontSizes[size]}`]: size === 'normal',
                                                       [`${fontSizes[size]}`]: size === 'small',
                                                   })}
                                                   value={(value || 0)}
                                                   onChange={({target: {value}}) => {
                                                       onChange(convert(value))
                                                   }}
                                                   onClick={() => {
                                                       inputRef.current?.select()
                                                   }}
                                                   onFocus={({target}) => {
                                                       const input = target as HTMLInputElement

                                                       //input.select()
                                                       setFocused(true)
                                                   }}
                                                   onBlur={({target}) => {
                                                       setFocused(false)
                                                   }}
                                                   style={{
                                                       width: 16 * (value == 0 ? 1 : (`${value}`.trim().length || 1))
                                                   }}
                        />}
                    </>)}
                    {type === 'percentage' && <span>%</span>}
                    {labels?.inputRight}
                </div>
                {!isCustomRender &&
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
                         className={classNames('p-[2px] bg-gray-200 bg-opacity-40 rounded-full active:scale-[.80] transition-all duration-75 hover:cursor-pointer', {
                             'min-w-4 min-h-4 max-w-4 max-h-4': size === 'normal',
                             'min-w-[14px] min-h-[14px] max-w-[14px] max-h-[14px]': size === 'small',
                         })}
                         onMouseDownCapture={() => {
                             // we need to overhaul it here.
                             // so first
                             /**
                              * 1 - add a settimeout listener, to only trigger this after about 150ms
                              * 2- then check if after that its still pressed, if so, start the autp-icnrease
                              * 3- if not, that means it was a simple clieck, so abandon it.
                              *
                              */
                             // lets ignore it for now as it is clashing with regular clicks
                             //setPressed('increase')
                             increaseOrDecrease('increase')()
                         }}
                         onMouseUpCapture={() => setPressed(null)}>
                        <path fillRule="evenodd"
                              d="M12 3.75a.75.75 0 0 1 .75.75v6.75h6.75a.75.75 0 0 1 0 1.5h-6.75v6.75a.75.75 0 0 1-1.5 0v-6.75H4.5a.75.75 0 0 1 0-1.5h6.75V4.5a.75.75 0 0 1 .75-.75Z"
                              clipRule="evenodd"/>
                    </svg>}
                {labels?.inputRightOutside}
            </div>
            {labels?.bottom && <p className="text-gray-500">{labels.bottom}</p>}
        </div>
        {labels?.afterSymbol}
    </>;
}
