import {RadioGroup, TabProps} from "@headlessui/react";
import React, {FC, isValidElement, ReactElement, ReactNode} from "react";
import classNames from "classnames";
import {__} from "../../globals";

export type Tab = {
    id: string,
    label: string | ((isSelected: boolean) => ReactElement),
    subLabel?: string,
    tabDescription?: string[],
    icon?: ReactNode,
    showDescriptionOnlyWhenSelected?: boolean
    isPreview?: boolean,
    disabled?: boolean,
};
export type TabsProps = {
    tabs: Tab[],
    selectedTabId: TabsProps['multiple'] extends true ? string[] : string,
    onTabSelect: (tabId: TabsProps['selectedTabId']) => void,
    onTabHover?: (tabId: string) => void,
    onTabUnhover?: () => void,
    disabledTabs?: string[],
    size?: 'extra-small' | 'normal',
    direction?: 'horizontal' | 'vertical',
    width?: 'auto' | 'full',
    fixedHeight?: boolean,
    dimUnselected?: boolean,
    style?: 'transparent' | 'outline',
    multiple?: boolean,
    connectedToThe?: 'top' |  'bottom'
}

function DefaultTab(props: {
    selected: boolean,
    size: string,
    label: string | React.ReactElement,
    subLabel?: string,
    isPreview?: boolean,
    direction?: string
}) {
    return <>
        {props.selected ? <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
                               className={classNames({
                                   "min-h-5 max-h-5 min-w-5 max-w-5": props.size === "normal",
                                   "min-h-4 max-h-4 min-w-4 max-w-4": props.size === "extra-small",
                               })}>
            <path fillRule="evenodd"
                  d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"
                  clipRule="evenodd"/>
        </svg> : <div className={classNames("rounded-full border-px", {
            "min-h-5 min-w-5": props.size === "normal",
            "min-h-3 min-w-3": props.size === "extra-small",
        })}></div>}
        <div className="flex flex-col gap-[2px] items-center-- justify-center">
            <span className={classNames('flex items-center gap-1', {
                "text-base leading-4": props.size === "normal",
                "text-smaller-1 leading-4": props.size === "extra-small",
            })}>
                <span className="whitespace-nowrap">{props.label}</span>
                {props.isPreview && <span
                className="text-[9.22px] uppercase px-1 h-4 flex items-center bg-gray-400 text-gray-100 rounded-5">{__('Preview')}</span>}
            </span>
            {props.subLabel && <span className="text-smaller-1 leading-4 opacity-70 font-light">{props.subLabel}</span>}
        </div>
    </>;
}

function TabDescription(props: { description: string, label?: string }) {
    return <p
        className="text-smaller-1 text-gray-450 mb-2">
        {props.label && <span className="font-semibold text-gray-550 mr-2">{props.label}:</span>}
        {props.description}
    </p>;
}

export const Tabs: FC<TabsProps> = ({
                                        tabs,
                                        disabledTabs,
                                        selectedTabId,
                                        onTabSelect,
                                        onTabHover,
                                        onTabUnhover,
                                        size = 'normal',
                                        direction = 'horizontal',
                                        width = 'full',
                                        dimUnselected,
                                        style = 'outline',
                                        fixedHeight,
                                        multiple,
                                        connectedToThe
                                    }) => {
    const selectedTab = tabs.find(tab => tab.id === selectedTabId);

    const onTabChange = id => {
        let newValue: string | string[]

        if (multiple) {
            if (selectedTabId.includes(id)) {
                newValue = selectedTabId.filter(tabId => tabId !== id)
            } else {
                newValue = [...selectedTabId, id]
            }
        } else {
            newValue = id;
        }

        onTabSelect(newValue);
    };

    const atLeastOneTabHasSubLabel = tabs.some(tab => !!tab.subLabel);

    return <div className="space-y-2">
        <RadioGroup value={selectedTabId} onChange={onTabChange}
                    className={classNames('grid border-gray-150 border-l-px border-r-px', {
                        //'p-2': size === 'normal',
                        //'p-1': size === 'extra-small'
                        '!border-none': style === 'transparent',
                        'rounded-1 border-px': !connectedToThe && size === 'normal',
                        'rounded-2 border-px': !connectedToThe && size === 'extra-small',
                        'rounded-t-1 border-t-px': connectedToThe === 'bottom',
                        'w-full': width === 'full',
                        'w-fit inline-grid': width === 'auto',
                        'grid-flow-row auto-rows-auto': direction === 'vertical',
                        /*'gap-3'*/'--gap-x-2 --gap-y-1': size === 'normal',
                        'gap-1': size === 'extra-small',
                    })} style={direction === 'horizontal' ? {gridTemplateColumns: `repeat(${tabs.length}, ${width === 'auto'? '0fr' : '1fr'})`} : {}}>
            {tabs.map(({
                           id,
                           label,
                           subLabel,
                           tabDescription,
                           showDescriptionOnlyWhenSelected = false,
                           disabled,
                           isPreview
                       }, index) => {
                const isSelected = multiple ? selectedTabId.includes(id) : selectedTabId === id
                disabled = disabled || (disabledTabs?.includes(id) === true);
                const isFirst = index === 0;
                const isLast = index === tabs.length - 1;

                return (
                    <div key={id} className={classNames('w-full', {
                        //'w-[fit-content]': width === 'auto',
                        'opacity-60': !isSelected,
                        '-mt-2 first:mt-0': size === 'normal' && direction === 'vertical' && !atLeastOneTabHasSubLabel,
                        //'border-r-px border-gray-150 last:border-none': atLeastOneTabHasSubLabel && direction === 'horizontal',
                    })}>
                        <RadioGroup.Option value={id}
                                           key={id}
                                           disabled={disabled}
                                            className={classNames({
                                                'hover:cursor-pointer': !disabled,
                                                'opacity-50 cursor-not-allowed': disabled,
                                                'w-full': true,
                                                'p-2': size === 'normal',
                                                'p-1': size === 'extra-small',
                                                'pb-1': size === 'normal' && direction === 'vertical' && isFirst,
                                                'pt-1': size === 'normal' && direction === 'vertical' && isLast,
                                            })}
                                            onMouseEnter={() => onTabHover?.(id)} onMouseLeave={() => onTabUnhover?.()}
                                            onMouseUp={() => {
                                                if (multiple) {
                                                    return
                                                }
                                                /*
                                                                                               if (direction === 'vertical') {
                                                                                                   return
                                                                                              }
                                               */

                                               /**
                                                * So there's a bug that it seems to come from headlessui in horizontal tabs,
                                                * sometimes the onChange event on the RadioGroup.Option is not triggered on click.
                                                * so we manually call the onTabChange function here.
                                                */
                                               setTimeout(() => onTabChange(id), 100)
                                           }}
                        >
                            {({checked: selected}) => typeof label == 'function' ? label(isSelected) :
                                <div>
                                    <div
                                        className={classNames({/*'flex items-center justify-start font-medium transition-all duration-150 ring-[1px] ring-offset-0 ring-gray-150 ring-transparent'*/}, {
                                            'flex items-center rounded-2 text-gray-750 text-1x w-full active:scale-[.97] transition-all ease ': true,
                                            'gap-2': size === 'normal',
                                            'gap-1': size === 'extra-small',
                                            'min-h-5': direction === 'horizontal' && size === 'normal',
                                            'min-h-3': direction === 'horizontal' && size === 'extra-small',
                                            'min-h-10': direction === 'vertical',
                                            'py-[6px]  px-2 --normal': size === 'normal',
                                            'py-[6px] px-2 --extra-small': size === 'extra-small',
                                            'hover:bg-gray-150 hover:bg-opacity-30': !isSelected,
                                            'bg-gray-150 bg-opacity-60': isSelected,
                                            //'bg-gray-150 bg-opacity-30': !isSelected && atLeastOneTabHasSubLabel,
                                            //'border-px': style === 'outline',
                                            //'min-h-17 px-5 rounded-[14px] space-x-4 py-2': size === 'normal',
                                            //'min-h-9 px-2 rounded-3 space-x-2': size === 'extra-small',
                                            //' border-gray-800 --bg-blue-10 bg-opacity-20 border-[2px] --text-blue-shade-100': style === 'outline' && isSelected,
                                            //'border-gray-200 text-gray-700': style === 'outline' && !isSelected && !dimUnselected,
                                            //'border-gray-150 text-gray-400': style === 'outline' && !isSelected && dimUnselected,
                                            //'hover:scale-[1.005] active:scale-[0.98] hover:ring-gray-150 hover:ring-offset-2 ': !disabled,
                                        })}>
                                        {typeof label === 'function' ? label(isSelected) :
                                            <DefaultTab selected={isSelected} size={size} label={label}
                                                        subLabel={direction === 'vertical'? subLabel : undefined} direction={direction} isPreview={isPreview}/>}
                                    </div>
                                </div>}
                        </RadioGroup.Option>
                        {subLabel && direction === 'horizontal' &&
                            <div className={classNames("text-smaller-1 leading-4 font-light border-gray-150 border-opacity-50 w-full p-2 --pb-2 --mt-1 px-[18px]", {
                                'p-2 border-t-px': direction === 'horizontal',
                                /*'!px-11': direction === 'vertical',
                                'border-b-px pt-0': direction === 'vertical' && atLeastOneTabHasSubLabel,
                                '-mt-2': direction === 'vertical' && atLeastOneTabHasSubLabel && !isSelected,*/
                                'text-gray-550': isSelected,
                                'text-gray-450': !isSelected,
                            })}>{subLabel}</div>}

                        {multiple && tabDescription?.length && (showDescriptionOnlyWhenSelected ? isSelected : true) &&
                            <div className={classNames({
                                'px-14 mt-1': direction === 'vertical',
                            })}>
                                {tabDescription.map((description) => <TabDescription
                                    description={description}/>)}
                            </div>}
                    </div>
                )
            })}
        </RadioGroup>
        {selectedTab?.tabDescription?.length && <div className="px-4">{selectedTab.tabDescription.map((description) => <TabDescription
            description={description}
            label={direction === 'vertical' && typeof selectedTab.label === 'string' ? selectedTab.label : undefined}/>)}</div>
        }
    </div>
}
