import React, { useCallback, useLayoutEffect, useRef, useState } from "react";
import { XIcon } from "lucide-react";
import { SelectValueProps as ValueProps } from "@radix-ui/react-select";
import { useSelectContext } from "@/components/ui/field/select/select.context";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils/cn";

type SelectValueProps = ValueProps & {
    clickToRemove?: boolean;
    overflowBehavior?: "wrap" | "wrap-when-open" | "cutoff";
};

export const SelectValue: React.FC<SelectValueProps> = (props) => {
    const {
        placeholder,
        clickToRemove = true,
        className,
        overflowBehavior = "wrap-when-open"
    } = props;

    const {
        multiple,
        selectedValues,
        toggleValue,
        items,
        open
    } = useSelectContext();

    const [overflowAmount, setOverflowAmount] = useState(0);
    const valueRef = useRef<HTMLDivElement>(null);
    const overflowRef = useRef<HTMLDivElement>(null);

    const shouldWrap = overflowBehavior === "wrap" || (overflowBehavior === "wrap-when-open" && open);

    const checkOverflow = useCallback(() => {
        if(valueRef.current == null) return;

        const containerElement = valueRef.current;
        const overflowElement = overflowRef.current;
        const itemElements = containerElement.querySelectorAll<HTMLElement>("[data-selected-item]");

        if(overflowElement != null)
            overflowElement.style.display = "none";

        itemElements.forEach(child => child.style.removeProperty("display"));

        let amount = 0;

        for(let i = itemElements.length - 1; i >= 0; i--) {
            const child = itemElements[i];

            if(containerElement.scrollWidth <= containerElement.clientWidth) {
                break;
            }

            amount = itemElements.length - i;
            child.style.display = "none";
            overflowElement?.style.removeProperty("display");
        }

        setOverflowAmount(amount);
    }, []);

    const handleResize = useCallback((node: HTMLDivElement | null) => {
        if(!node) {
            return () => {};
        }

        const observer = new ResizeObserver(checkOverflow);

        valueRef.current = node;
        observer.observe(node);

        return () => {
            observer.disconnect();
            valueRef.current = null;
        };
    }, [checkOverflow]);

    useLayoutEffect(() => {
        if(multiple) {
            checkOverflow();
        }
    }, [selectedValues, checkOverflow, shouldWrap, multiple]);

    if(selectedValues.size === 0 && placeholder) {
        return (
            <span className="min-w-0 overflow-hidden font-normal text-muted-foreground">
                {placeholder}
            </span>
        );
    }

    if(!multiple) {
        const [value] = Array.from(selectedValues);

        return (
            <span>
                {items.get(value) ?? value}
            </span>
        );
    }

    return (
        <div
          ref={handleResize}
          className={
            cn("flex w-full gap-1.5 overflow-hidden", className, {
                "h-full flex-wrap": shouldWrap
            })
          }>
            {Array.from(selectedValues).map(value => {
                const label = items.get(value) ?? value;

                return (
                    <Badge
                      key={value}
                      className="group flex items-center gap-1"
                      // className="flex max-w-full items-center gap-1 px-1 py-0"
                      variant="outline"
                      data-selected-item
                      onClick={(e) => {
                        if(!clickToRemove) {
                            return;
                        }

                        e.stopPropagation();
                        toggleValue(value);
                      }}>
                        <span className="truncate">
                            {label}
                        </span>

                        {clickToRemove && (
                            <XIcon className="size-2 text-muted-foreground group-hover:text-destructive" />
                        )}
                    </Badge>
                );
            })}

            <Badge
              ref={overflowRef}
              style={{
                display: overflowAmount > 0 && !shouldWrap ? "block" : "none"
              }}
              variant="outline">
                +{overflowAmount}
            </Badge>
        </div>
    );
};
