import React, {
    DetailedHTMLProps,
    InputHTMLAttributes,
    LabelHTMLAttributes,
    RefObject,
    TextareaHTMLAttributes,
} from "react";
import { twMerge } from "tailwind-merge";

export type InputProps = DetailedHTMLProps<
    InputHTMLAttributes<HTMLInputElement>,
    HTMLInputElement
> &
    DetailedHTMLProps<
        TextareaHTMLAttributes<HTMLTextAreaElement>,
        HTMLTextAreaElement
    > & {
        label?: string;
        variant?: "normal" | "warning" | "error" | "inactive";
        prefix?: string | React.ReactNode;
        suffix?: string | React.ReactNode;
        showLabel?: boolean;
        istextarea?: boolean;
        wrapperProps?: DetailedHTMLProps<
            InputHTMLAttributes<HTMLDivElement>,
            HTMLDivElement
        >;
        labelProps?: DetailedHTMLProps<
            LabelHTMLAttributes<HTMLLabelElement>,
            HTMLLabelElement
        >;
        componentRef?: RefObject<any>;
    };

/**
 * # Input Element
 * @className twui-input
 */
export default function Input({
    label,
    variant,
    prefix,
    suffix,
    componentRef,
    labelProps,
    wrapperProps,
    showLabel,
    istextarea,
    ...props
}: InputProps) {
    const [focus, setFocus] = React.useState(false);

    const targetComponent = istextarea ? (
        <textarea
            {...props}
            className={twMerge(
                "w-full outline-none bg-transparent",
                "twui-textarea",
                props.className
            )}
            ref={componentRef}
            onFocus={(e) => {
                setFocus(true);
                props?.onFocus?.(e);
            }}
            onBlur={(e) => {
                setFocus(false);
                props?.onBlur?.(e);
            }}
        />
    ) : (
        <input
            {...props}
            className={twMerge(
                "w-full outline-none bg-transparent",
                "twui-input",
                props.className
            )}
            ref={componentRef}
            onFocus={(e) => {
                setFocus(true);
                props?.onFocus?.(e);
            }}
            onBlur={(e) => {
                setFocus(false);
                props?.onBlur?.(e);
            }}
        />
    );

    return (
        <div
            {...wrapperProps}
            className={twMerge(
                "relative flex items-center gap-2 border rounded-md px-3 py-2 outline outline-1",
                focus
                    ? "border-slate-700 dark:border-white/50"
                    : "border-slate-300 dark:border-white/20",
                focus
                    ? "outline-slate-700 dark:outline-white/50"
                    : "outline-transparent",
                variant == "warning" &&
                    "border-yellow-500 dark:border-yellow-300 outline-yellow-500 dark:outline-yellow-300",
                variant == "error" &&
                    "border-red-500 dark:border-red-300 outline-red-500 dark:outline-red-300",
                variant == "inactive" && "opacity-40 pointer-events-none",
                "bg-white dark:bg-black",
                wrapperProps?.className
            )}
        >
            {showLabel && (
                <label
                    htmlFor={props.name}
                    {...labelProps}
                    className={twMerge(
                        "text-xs absolute -top-2.5 left-2 text-slate-500 bg-white px-1.5 rounded-t",
                        "dark:text-white/60 dark:bg-black",
                        labelProps?.className
                    )}
                >
                    {label || props.placeholder || props.name}
                </label>
            )}

            {prefix && (
                <div className="opacity-60 pointer-events-none">{prefix}</div>
            )}

            {targetComponent}

            {suffix && (
                <div className="opacity-60 pointer-events-none">{suffix}</div>
            )}
        </div>
    );
}
