import { LucideProps, Star } from "lucide-react";
import React, {
    DetailedHTMLProps,
    ForwardRefExoticComponent,
    HTMLAttributes,
    RefAttributes,
} from "react";
import { twMerge } from "tailwind-merge";

type StarProps = {
    total?: number;
    value?: number;
    size?: number;
    starProps?: LucideProps;
    allowRating?: boolean;
    setValueExternal?: React.Dispatch<React.SetStateAction<number>>;
    changeHandler?: (value: number) => void;
};

export type TWUI_STAR_RATING_PROPS = DetailedHTMLProps<
    HTMLAttributes<HTMLDivElement>,
    HTMLDivElement
> &
    StarProps;

let timeout: any;

/**
 * # Star Rating Component
 * @className_wrapper twui-star-rating
 */
export default function StarRating({
    total = 5,
    value = 0,
    size,
    starProps,
    allowRating,
    setValueExternal,
    changeHandler,
    ...props
}: TWUI_STAR_RATING_PROPS) {
    const totalArray = Array(total).fill(null);

    const [finalValue, setFinalValue] = React.useState(value);
    const [selectedStarValue, setSelectedStarValue] = React.useState(value);

    const starClicked = React.useRef(false);
    const sectionHovered = React.useRef(false);

    React.useEffect(() => {
        window.clearTimeout(timeout);
        timeout = setTimeout(() => {
            setValueExternal?.(finalValue);
        }, 500);
    }, [selectedStarValue]);

    return (
        <div
            {...props}
            className={twMerge(
                "flex flex-row items-center gap-0 -ml-[2px]",
                "twui-star-rating",
                props.className,
            )}
            onMouseEnter={() => {
                sectionHovered.current = true;
            }}
            onMouseLeave={() => {
                sectionHovered.current = false;
            }}
        >
            {totalArray.map((_, index) => {
                const isActive = index + 1 <= finalValue;

                return (
                    <StarComponent
                        {...{
                            total,
                            value,
                            size,
                            starProps,
                            index,
                            allowRating,
                            finalValue,
                            setFinalValue,
                            starClicked,
                            selectedStarValue,
                            sectionHovered,
                            setSelectedStarValue,
                            isActive,
                            changeHandler,
                        }}
                        key={index}
                    />
                );
            })}
        </div>
    );
}

function StarComponent({
    size = 20,
    starProps,
    index,
    allowRating,
    setFinalValue,
    starClicked,
    sectionHovered,
    setSelectedStarValue,
    selectedStarValue,
    isActive,
    changeHandler,
}: StarProps & {
    index: number;
    setFinalValue: React.Dispatch<React.SetStateAction<number>>;
    setSelectedStarValue: React.Dispatch<React.SetStateAction<number>>;
    starClicked: React.MutableRefObject<boolean>;
    sectionHovered: React.MutableRefObject<boolean>;
    selectedStarValue: number;
    isActive: boolean;
}) {
    return (
        <div
            className={twMerge("p-[2px]", allowRating && "cursor-pointer")}
            onMouseEnter={() => {
                if (!allowRating) return;
                setFinalValue(index + 1);
            }}
            onMouseLeave={() => {
                if (!allowRating) return;

                setTimeout(() => {
                    if (sectionHovered.current) {
                        return;
                    }

                    if (!starClicked.current) {
                        setFinalValue(0);
                    }

                    if (selectedStarValue) {
                        setFinalValue(selectedStarValue);
                    }
                }, 200);
            }}
            onClick={() => {
                if (!allowRating) return;

                starClicked.current = true;
                setSelectedStarValue(index + 1);
                changeHandler?.(index + 1);
            }}
        >
            <Star
                size={size}
                className={twMerge(
                    "text-slate-300 dark:text-white/20",
                    isActive &&
                        "text-orange-500 dark:text-orange-400 fill-orange-500 dark:fill-orange-400",
                    // allowRating &&
                    //     "hover:text-orange-500 hover:dark:text-orange-400 hover:fill-orange-500 hover:dark:fill-orange-400",
                    starProps?.className,
                )}
                {...starProps}
            />
        </div>
    );
}
