import React, { Fragment, ReactNode, useEffect, useState } from 'react';
import { css } from 'styled-components';
import { lighten } from 'polished';
import {
	Flex,
	Wrapper,
	WrapperProps,
	black,
	secondary,
	borderRadius,
	boxShadow,
	centerX,
	Line,
	Text,
} from 'dot-design-system';
import { fontSizes } from '../styles/typography';
import { arrayToObject, liftChildren } from '../utils/arrays';
import { useStateEffect } from 'dot-utils';

export interface TabItem {
	key: string;
	title: string;
	icon?: any;
	onClick?: () => boolean;
	tab: () => ReactNode;
	subMenu?: TabItem[];
}

interface Props extends WrapperProps {
	tabs: TabItem[];
	renderAfterTabs?: () => ReactNode;
	variant: 'clean' | 'dark' | 'mini';
	activeKey?: string;
	onTabSelect?: (newActiveKey: string) => boolean;
	containerProps?: WrapperProps;
}

export enum MenuType {
	Dark = 'dark',
	Clean = 'clean',
	Mini = 'mini',
}

type VariantProps = {
	[Type in MenuType]: {
		line?: WrapperProps;
		nav: WrapperProps;
		item: WrapperProps;
		underline?: string;
	};
};

const variantProps: VariantProps = {
	dark: {
		line: {},
		nav: {
			background: black,
			borderRadius,
			px: 20,
			css: css`
				display: inline-flex;

				&& {
					@media (max-width: 870px) {
						* {
							font-size: 14px;
						}
					}

					@media (max-width: 650px) {
						padding-left: 0;
						padding-right: 0;
						* {
							font-size: 12px;
						}
					}

					@media (max-width: 410px) {
						p {
							font-size: 10px;
						}
					}
				}
			`,
		},
		item: {
			color: '#fff',
			css: css`
				&& {
					&:hover {
						background-color: ${lighten(0.1, black)};
					}

					@media (max-width: 550px) {
						flex-direction: column;
						padding: 10px;
						* {
							margin: 0;
						}
					}
				}
			`,
		},
		underline: secondary,
	},
	clean: {
		line: {
			mt: -7,
			opacity: 0.3,
		},
		nav: {
			css: ``,
		},
		item: {
			py: 5,
			px: 0,
			mr: 15,
			fontSize: fontSizes.theta,
		},
		underline: black,
	},
	mini: {
		nav: {
			css: ``,
		},
		item: {},
		underline: black,
	},
};

function TabsMenu({
	tabs,
	renderAfterTabs = () => null,
	variant,
	activeKey,
	onTabSelect,
	css: cssProp,
	containerProps = {},
	...props
}: Props) {
	const [active, setActive] = useStateEffect(activeKey || tabs[0].key);
	const tabMap = arrayToObject('key', liftChildren('subMenu', tabs));
	const handleChange = (key: string) => () => {
		const newTab = tabMap[key];
		const onClick = newTab.onClick;

		if (onClick) {
			const canChange = onClick();

			if (!canChange) {
				return;
			}
		}

		if (onTabSelect) {
			const canChange = onTabSelect(key);

			if (!canChange) {
				return;
			}
		}

		return setActive(key);
	};
	const currentTab = tabMap[active];
	const thisProps = variantProps[variant];

	useEffect(() => {
		if (activeKey && activeKey !== active) {
			setActive(activeKey);
		}
	}, [activeKey]);

	const hasSubmenu = tabs.some((tab) => !!tab.subMenu);
	const containerStyles = css`
		position: relative;
		${thisProps.nav.css};
		z-index: ${(hasSubmenu && 3) || 2};
	`;

	return (
		<Fragment>
			<Wrapper {...containerProps}>
				<Flex
					{...thisProps.nav}
					{...props}
					css={css`
						${containerStyles};
						${cssProp};
					`}
					component={'nav'}
				>
					{tabs.map((item: TabItem) => {
						const isActive =
							item.key === active ||
							item?.subMenu?.some((subItem) => subItem.key === active);
						return (
							<Wrapper
								css={`
									cursor: pointer;
									position: relative;

									.sub-menu--${item.key} {
										display: none;
										white-space: nowrap;
									}

									&:hover .sub-menu--${item.key} {
										display: block;
									}
								`}
								key={item.key}
							>
								<Flex
									alignItems={'center'}
									fontSize={fontSizes.theta}
									m={0}
									p={15}
									onClick={handleChange(item.key)}
									{...thisProps.item}
									css={`
										cursor: pointer;
										opacity: ${(isActive && 1) || 0.5};
										transition: opacity 0.35s ease-out;
										${thisProps.item.css};

										&:hover {
											opacity: 1;
										}
									`}
								>
									{item.icon || null}
									<Text
										m={0}
										// @ts-ignore
										fontSize={thisProps.item.fontSize || fontSizes.iota}
										ml={5}
										css={`
											position: relative;
											white-space: nowrap;
										`}
									>
										{item.title}
										{thisProps.underline && (
											<Wrapper
												component={'span'}
												height={2}
												background={thisProps.underline}
												width={'100%'}
												css={`
													display: block;
													transition: 0.35s ease-out;
													opacity: ${(isActive && 1) || 0};
												`}
											/>
										)}
									</Text>
								</Flex>
								{item.subMenu && (
									<Wrapper
										p={3}
										background={'white'}
										borderRadius={borderRadius}
										className={`sub-menu--${item.key}`}
										css={`
											box-shadow: ${boxShadow};
											position: absolute;
											top: 100%;

											${centerX};
										`}
									>
										{item.subMenu.map((subItem) => (
											<Wrapper
												p={5}
												borderRadius={borderRadius}
												onClick={handleChange(subItem.key)}
												background={
													(active === subItem.key && '#eeeeee') ||
													'transparent'
												}
												key={subItem.key}
											>
												{subItem.title}
											</Wrapper>
										))}
									</Wrapper>
								)}
							</Wrapper>
						);
					})}
				</Flex>
				{thisProps.line && <Line mt={10} {...thisProps.line} />}
				{renderAfterTabs()}
			</Wrapper>
			{currentTab.tab()}
		</Fragment>
	);
}

export default TabsMenu;
