import { useCallback, useEffect, useRef, useState } from "react";
import classes from "./classes.module.scss";
import HorizontalTab, { ITab } from "./HorizontalTab";
import VerticalTabs from "./VerticalTabs";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import { useDebounce, useWindowSize } from "@uidotdev/usehooks";
import useOpenable from "@Front/Hooks/useOpenable";

export type ITabValue<T> = T & {
	id: unknown;
};

type ITabInternal<T> = ITab & {
	key?: string;
	value: ITabValue<T>;
};

type IProps<T> = {
	tabs: ITabInternal<T>[];
	onSelect: (value: T) => void;
};

export default function Tabs<T>(props: IProps<T>) {
	const { onSelect } = props;
	const rootRef = useRef<HTMLDivElement>(null);
	const [visibleElements, setVisibleElements] = useState<ITabInternal<T>[]>([]);
	const [overflowedElements, setOverflowedElements] = useState<ITabInternal<T>[]>([]);

	const [selectedTab, setSelectedTab] = useState<ITabValue<T>>(props.tabs[0]!.value);

	const { close, isOpen, toggle } = useOpenable();

	const windowSize = useWindowSize();
	const windowSizeDebounced = useDebounce(windowSize, 100);

	const calculateVisibleElements = useCallback(() => {
		const container = rootRef.current;
		if (!container) return;

		const containerWidth = container.offsetWidth;
		let totalWidth = 115;
		let visibleCount = 0;

		const children = Array.from(container.children) as HTMLDivElement[];
		for (let i = 0; i < children.length; i++) {
			totalWidth += children[i]!.offsetWidth;
			if (totalWidth > containerWidth) {
				break;
			}
			visibleCount++;
		}

		setVisibleElements(props.tabs.slice(0, visibleCount));
		setOverflowedElements(props.tabs.slice(visibleCount));
	}, [props.tabs]);

	useEffect(() => {
		calculateVisibleElements();
	}, [calculateVisibleElements, windowSizeDebounced]);

	const handleSelect = useCallback(
		(value: ITabValue<T>) => {
			setSelectedTab(value);
			onSelect(value);
			close();
		},
		[close, onSelect],
	);

	return (
		<div className={classes["root"]}>
			<div className={classes["hidden-tester"]} ref={rootRef}>
				{props.tabs.map((element, index) => (
					<HorizontalTab<T>
						label={element.label}
						key={element.key ?? index}
						value={element.value}
						onSelect={handleSelect}
						isSelected={element.value.id === selectedTab.id}
					/>
				))}
			</div>
			<div className={classes["horizontal-container"]}>
				<div className={classes["horizontal-tab"]}>
					{visibleElements.map((element, index) => (
						<HorizontalTab<T>
							label={element.label}
							key={element.key ?? index}
							value={element.value}
							onSelect={handleSelect}
							isSelected={element.value.id === selectedTab.id}
						/>
					))}
				</div>
				{overflowedElements.length > 0 && (
					<div className={classes["show-more-container"]}>
						<div className={classes["show-more"]} onClick={toggle}>
							<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
								{overflowedElements.length}&nbsp;de&nbsp;plus...
							</Typography>
						</div>
						<div className={classes["vertical-container"]} data-visible={isOpen}>
							{overflowedElements.length > 0 &&
								overflowedElements.map((element, index) => (
									<VerticalTabs<T>
										label={element.label}
										key={element.key ?? index}
										value={element.value}
										onSelect={handleSelect}
										isSelected={selectedTab === element.value}
									/>
								))}
						</div>
					</div>
				)}
			</div>
		</div>
	);
}
