import { trimValue } from '@/utils/Functions'
import { useAuthStore } from '@/zustand/auth/useAuthStore'
import React, {
    forwardRef,
    useState,
    ChangeEvent,
    FocusEvent,
    InputHTMLAttributes,
    TextareaHTMLAttributes,
    KeyboardEvent,
    WheelEvent
} from 'react'
import type { FieldError } from 'react-hook-form'

type ErrorType = {
    message?: string
}

interface BaseProps {
    id?: string
    name?: string
    label?: string
    placeholder?: string
    required?: boolean
    error?: string | ErrorType | FieldError
    disabled?: boolean
    wrapperClassName?: string
}

type InputProps = BaseProps &
    Omit<
        InputHTMLAttributes<HTMLInputElement>,
        'className' | 'onChange' | 'onBlur'
    > & {
        type?: 'text' | 'email' | 'password' | 'number'
        onChange?: (e: ChangeEvent<HTMLInputElement>) => void
        onBlur?: (e: FocusEvent<HTMLInputElement>) => void
    }

type TextareaProps = BaseProps &
    Omit<
        TextareaHTMLAttributes<HTMLTextAreaElement>,
        'className' | 'onChange' | 'onBlur'
    > & {
        type: 'textarea'
        onChange?: (e: ChangeEvent<HTMLTextAreaElement>) => void
        onBlur?: (e: FocusEvent<HTMLTextAreaElement>) => void
    }

type InputFieldProps = InputProps | TextareaProps | CheckboxProps
type CheckboxSize = 'sm' | 'md' | 'lg'

type CheckboxProps = BaseProps &
    Omit<
        InputHTMLAttributes<HTMLInputElement>,
        'className' | 'type' | 'onChange' | 'onBlur'
    > & {
        type: 'checkbox'
        size?: CheckboxSize
        onChange?: (e: ChangeEvent<HTMLInputElement>) => void
        onBlur?: (e: FocusEvent<HTMLInputElement>) => void
    }
const InputField = forwardRef<
    HTMLInputElement | HTMLTextAreaElement,
    InputFieldProps
>(
    (
        {
            type = 'text',
            id,
            name,
            label,
            placeholder,
            required,
            error,
            disabled,
            onChange,
            onBlur,
            wrapperClassName = '',
            ...rest
        },
        ref
    ) => {
        const { language } = useAuthStore();
        const errorMessage = typeof error === 'string' ? error : error?.message
        const hasError = !!errorMessage
        const isPassword = type === 'password'
        const isNumber = type === 'number'
        const isTextarea = type === 'textarea'
        const checkboxSizes = {
            sm: 'w-4 h-4',
            md: 'w-5 h-5',
            lg: 'w-6 h-6'
        }
        const isCheckbox = type === 'checkbox'
        const size = (rest as CheckboxProps)?.size || 'md'

        const [showPassword, setShowPassword] = useState(false)
        const handleChange = (
            e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
        ) => {
            // Apply trimming only for text, password, textarea
            if (
                type === 'text' ||
                type === 'password' ||
                type === 'textarea'
            ) {
                trimValue(e)
            }

            onChange?.(e as any)
        }
        const handleWheel = (e: WheelEvent<HTMLInputElement>) => {
            if (isNumber) e.currentTarget.blur()
        }

        const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
            if (!isNumber) return
            const allowed = [
                'Backspace',
                'Tab',
                'Delete',
                'ArrowLeft',
                'ArrowRight'
            ]
            if (allowed.includes(e.key)) return
            if (/^[0-9.]$/.test(e.key)) return
            e.preventDefault()
        }
        if (isCheckbox) {
            return (
                <label
                    htmlFor={id}
                    className={`flex items-center gap-2.5 cursor-pointer select-none ${wrapperClassName}`}
                >
                    <input
                        ref={ref as React.Ref<HTMLInputElement>}
                        id={id}
                        name={name}
                        type="checkbox"
                        disabled={disabled}
                        onChange={onChange as any}
                        onBlur={onBlur as any}
                        className="peer hidden"
                        {...(rest as InputHTMLAttributes<HTMLInputElement>)}
                    />

                    <span
                        className={`
                            relative shrink-0 flex items-center justify-center
                            border border-light rounded-[4px]
                            transition-all
                            ${checkboxSizes[size]}
                            peer-checked:bg-primary
                            peer-checked:border-primary
                            ${disabled ? 'opacity-60' : ''}
                            group
                        `}
                    >
                        <i
                            className="
                            icon icon-check
                            w-3 h-3
                            bg-white
                            opacity-0 scale-50
                            transition-all duration-150
                            group-[.peer:checked+&]:opacity-100
                            group-[.peer:checked+&]:scale-100
                            "
                        />
                    </span>

                    {label && (
                        <span className="text-sm md:text-base font-normal">
                            {label}
                            {required && (
                                <span className="text-red ml-1">*</span>
                            )}
                        </span>
                    )}
                </label>
            )
        }

        return (
            <div className={`relative w-full mb-4 ${wrapperClassName}`}>
                {label && (
                    <label
                        htmlFor={id}
                        className="block mb-2 lg:mb-2.5 text-sm lg:text-base font-semibold leading-none"
                    >
                        {label}
                        {required && <span className="text-red ml-1">*</span>}
                    </label>
                )}

                {isTextarea ? (
                    <textarea
                        ref={ref as React.Ref<HTMLTextAreaElement>}
                        id={id}
                        name={name}
                        placeholder={placeholder}
                        disabled={disabled}
                        onChange={handleChange}
                        onBlur={onBlur as any}
                        className={`w-full border border-grey32 bg-secondary25 px-4 md:px-5 py-3 md:py-4 text-sm md:text-base font-normal leading-tight outline-none focus:border-light rounded-xl lg:rounded-2xl resize-y
        ${disabled ? 'opacity-60' : ''}
        ${hasError ? 'border-red' : ''}
    `}
                        {...(rest as TextareaHTMLAttributes<HTMLTextAreaElement>)}
                    />

                ) : (
                    <div className={`relative`}>
                        <input
                            ref={ref as React.Ref<HTMLInputElement>}
                            id={id}
                            name={name}
                            type={isPassword && showPassword ? 'text' : type}
                            placeholder={placeholder}
                            disabled={disabled}
                            onChange={handleChange}
                            onBlur={onBlur as any}
                            onWheel={handleWheel}
                            onKeyDown={handleKeyDown}
                            className={`w-full text-sm md:text-base font-normal leading-tight outline-none pr-8 px-4 md:px-5 py-3 md:py-4 rounded-xl lg:rounded-2xl border border-grey32 bg-secondary25 focus:border-light ${hasError ? 'border-red' : ''} ${disabled ? 'opacity-60 cursor-not-allowed' : ''}`}
                            {...(rest as InputHTMLAttributes<HTMLInputElement>)}
                        />


                        {isPassword && (
                            <i
                                onClick={() => setShowPassword(!showPassword)}
                                className={`icon ${!showPassword
                                    ? 'icon-eye'
                                    : 'icon-eye-close'
                                    } w-5 md:w-6 h-5 md:h-6 bg-grey92 absolute top-1/2 -translate-y-1/2  cursor-pointer ${language === "en" ? "right-3 md:right-4" : "left-3 md:left-4"}`}
                            />
                        )}
                    </div>
                )}

                {hasError && (
                    <span className={`absolute top-full text-[12px] leading-none text-red ${language === "en" ? "left-0" : "right-0"}`}>
                        {errorMessage}
                    </span>
                )}
            </div>
        )
    }
)

InputField.displayName = 'InputField'
export default InputField
