import React, { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react";
import { twMerge } from "tailwind-merge";
import Border from "./Border";
import Stack from "../layout/Stack";
import Row from "../layout/Row";
import twuiSlugify from "../utils/slugify";

export type TWUITabsObject = {
    title: string;
    value?: string;
    content?: React.ReactNode;
    defaultActive?: boolean;
};

export type TWUI_TOGGLE_PROPS = React.ComponentProps<typeof Stack> & {
    tabsContentArray: (TWUITabsObject | TWUITabsObject[] | undefined | null)[];
    tabsBorderProps?: React.ComponentProps<typeof Border>;
    tabsButtonsWrapperProps?: React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLDivElement>,
        HTMLDivElement
    >;
    centered?: boolean;
    debounce?: number;
    /**
     * React Component to display when switching
     */
    switchComponent?: ReactNode;
    setActiveValue?: React.Dispatch<React.SetStateAction<string | undefined>>;
    changeHandler?: (value: TWUITabsObject) => void;
    defaultValue?: string | null;
    hrefUpdate?: boolean;
};

/**
 * # Tabs Component
 * @className twui-tabs-wrapper
 * @className twui-tab-buttons
 * @className twui-tab-button-active
 * @className twui-tab-buttons-wrapper
 * @className twui-tab-buttons-container
 * @className twui-tabs-border
 */
export default function Tabs({
    tabsContentArray,
    tabsBorderProps,
    tabsButtonsWrapperProps,
    centered,
    debounce = 100,
    switchComponent,
    setActiveValue: existingSetActiveValue,
    changeHandler,
    defaultValue,
    hrefUpdate,
    ...props
}: TWUI_TOGGLE_PROPS) {
    const finalTabsContentArray = tabsContentArray
        .flat()
        .filter((ct) => Boolean(ct?.title)) as TWUITabsObject[];

    const values = finalTabsContentArray.map(
        (obj) => obj.value || twuiSlugify(obj.title),
    );

    const defaultActiveObj = finalTabsContentArray.find(
        (ctn) => ctn.defaultActive,
    );

    const [activeValue, setActiveValue] = React.useState(
        defaultValue
            ? defaultValue
            : defaultActiveObj
              ? defaultActiveObj?.value || twuiSlugify(defaultActiveObj.title)
              : values[0] || undefined,
    );
    const [ready, setReady] = React.useState(false);

    const targetContent = finalTabsContentArray.find(
        (ctn) =>
            ctn.value == activeValue || twuiSlugify(ctn.title) == activeValue,
    );

    React.useEffect(() => {
        if (!ready) return;
        existingSetActiveValue?.(activeValue);
        if (targetContent && activeValue) {
            changeHandler?.(targetContent);

            if (hrefUpdate) {
                const url = new URL(window.location.href);
                url.searchParams.set("tab", activeValue);
                window.history.pushState({}, "", url);
            }
        }
    }, [activeValue]);

    React.useEffect(() => {
        if (hrefUpdate) {
            const url = new URL(window.location.href);

            const activeTab = url.searchParams.get("tab");

            if (activeTab && activeValue !== activeTab) {
                setActiveValue(undefined);
                setActiveValue(activeTab);
            }

            setTimeout(() => {
                setReady(true);
            }, 500);
        } else {
            setReady(true);
        }
    }, []);

    return (
        <Stack
            {...props}
            className={twMerge("w-full", "twui-tabs-wrapper", props.className)}
        >
            <div
                {...tabsButtonsWrapperProps}
                className={twMerge(
                    "w-full",
                    "twui-tab-buttons-wrapper",
                    tabsButtonsWrapperProps?.className,
                )}
            >
                <Border
                    className="p-0 w-full overflow-hidden twui-tabs-border"
                    {...tabsBorderProps}
                >
                    <Row
                        className={twMerge(
                            "gap-0 items-stretch w-full flex-nowrap overflow-x-auto",
                            centered && "justify-center",
                            "twui-tab-buttons-container",
                        )}
                    >
                        {values.map((value, index) => {
                            const targetObject = finalTabsContentArray.find(
                                (ctn) =>
                                    ctn.value == value ||
                                    twuiSlugify(ctn.title) == value,
                            );

                            const isActive = value == activeValue;

                            return (
                                <span
                                    className={twMerge(
                                        "px-6 py-2 rounded-default -ml-[1px] whitespace-nowrap",
                                        isActive
                                            ? "bg-primary dark:bg-primary-dark text-white outline-none twui-tab-button-active"
                                            : "text-slate-400 dark:text-white/40 hover:text-slate-800 dark:hover:text-white" +
                                                  " cursor-pointer",
                                        "twui-tab-buttons",
                                    )}
                                    onClick={() => {
                                        setActiveValue(undefined);
                                        setTimeout(() => {
                                            setActiveValue(value);
                                        }, debounce);
                                    }}
                                    key={index}
                                >
                                    {targetObject?.title}
                                </span>
                            );
                        })}
                    </Row>
                </Border>
            </div>
            {activeValue ? targetContent?.content : switchComponent || null}
        </Stack>
    );
}
