import { Children, PropsWithChildren, useEffect } from 'react';
import { useTabs, TabPanel } from 'react-headless-tabs';
import Block from '../../atoms/Block';
import Button from '../../atoms/Button';
import Select from '../Select';
import style from '../../../style';
import { ButtonProps } from '../../atoms/Button/Button';

export interface TabsProps<T extends string> {
    /**
     * className prop forwarded to the main root element
     */
    className?: string;
    /**
     * Array of T that will define the tabs value and the number of panels.
     */
    tabs: T[];
    /**
     * A T that will match the tab name from the tabs array to set the Initial Tab, or update the tab value.
     */
    value: T;
    /**
     * Color variation that will switch between styles for the Select .
     */
    variation?: 'initial' | 'default' | 'primary' | 'secondary';
    /**
     * Extend the props to the Button component inside the Tab
     */
    buttonProps?: ButtonProps;
    /**
     * Extend the props to the Button component inside the Tab
     */
    onChange?: (value: React.SetStateAction<T>) => void;
}

export interface TabProps {
    label: string;
}

export interface PanelProps {
    children: React.ReactNode;
}

const Tabs = <T extends string>(props: PropsWithChildren<TabsProps<T>>) => {
    const { tabs, variation, buttonProps, value, onChange } = props;
    const [selectedTab, setSelectedTab] = useTabs(tabs, value);

    useEffect(() => {
        setSelectedTab(value);
    }, [value, setSelectedTab]);

    useEffect(() => {
        if (onChange && selectedTab) {
            onChange(selectedTab);
        }
    }, [selectedTab, onChange]);

    let variationStyle = style.tabs.default;

    switch (variation) {
        case 'default':
            variationStyle = style.tabs.default;
            break;
        case 'primary':
            variationStyle = style.tabs.primary;
            break;
        case 'secondary':
            variationStyle = style.tabs.secondary;
            break;
        default:
            variationStyle = style.tabs.default;
    }

    const Tab: React.FC<TabProps> = (props) => {
        const { label } = props;
        return (
            <Button
                {...buttonProps}
                onClick={() => setSelectedTab(label as T)}
                className={`border-b-2 border-t-0 border-l-0 border-r-0 ${
                    selectedTab === label ? variationStyle.selectedTab : ''
                } ${buttonProps?.className}`}
                variation={variation}
            >
                {label}
            </Button>
        );
    };

    return (
        <Block className={props.className}>
            <Block className={'md:hidden flex-grow-0 shrink-0'}>
                <Select
                    variation={variation}
                    value={{
                        label: selectedTab ?? '',
                        value: selectedTab ?? '',
                    }}
                    onChange={(e) => setSelectedTab(e?.value as T)}
                    options={tabs.map((tab) => {
                        return { label: tab, value: tab };
                    })}
                ></Select>
            </Block>
            <Block className={`hidden md:block border-b ${variationStyle.tabs}`}>
                {tabs.map((tab, index) => (
                    <Tab key={`${tab}${index}`} label={tab} />
                ))}
            </Block>
            {Children.map(props.children, (child, index) => {
                const childrenLength = Children.count(props.children);
                const isTheSameNumber = childrenLength === tabs.length;
                if (!isTheSameNumber) {
                    console.error(
                        'The number of tabs and the children inside the tabs must be the same for the tabs component to work properly',
                    );
                }
                return (
                    <TabPanel
                        className={selectedTab !== tabs[index] ? 'hidden' : 'flex flex-col flex-auto'}
                        key={`${child}${index}`}
                        hidden={selectedTab !== tabs[index]}
                    >
                        {child}
                    </TabPanel>
                );
            })}
        </Block>
    );
};

Tabs.defaultProps = { variation: 'initial' };

Tabs.displayName = 'Tabs';

export default Tabs;
