import { useState } from "react";
import { connect } from "react-redux";
import { type RouteComponentProps, withRouter } from "react-router-dom";

import { Icon, Tag } from "@ax/components";
import { appActions } from "@ax/containers/App";
import type { IGlobalSettings } from "@ax/containers/App/reducer";
import { Restricted } from "@ax/guards";
import { type IRouter, multisite, site } from "@ax/routes";
import type { ILanguage, IRootState, ISite, IStructuredData, IUser } from "@ax/types";

import { version } from "./../../../../../package.json";
import { NavProvider } from "./context";
import NavItem from "./NavItem";

import * as S from "./style";

const NavMenu = (props: IProps) => {
	const {
		location,
		setHistoryPush,
		logoutAndNavigate,
		currentSiteInfo,
		siteLanguages,
		lang,
		categories,
		globalSettings,
		structuredData,
		currentUser,
	} = props;

	const { useForms } = globalSettings;

	const [isOpened, setIsOpened] = useState(false);

	const initState: Record<string, unknown> = {};
	const [state, setState] = useState(initState);

	const toggleSubmenu = (value: string) => {
		setState({ [value]: !state[value] });
	};

	const logoPlaceholder = "/img/logos/logoGriddoExtended@3x.svg";
	const logoMiniPlaceholder = "/img/logos/logoGriddoReduce@3x.svg";

	const toggleMenu = () => {
		setState({});
		setIsOpened(!isOpened);
	};

	const siteLogo = currentSiteInfo?.bigAvatar ? currentSiteInfo.bigAvatar : logoPlaceholder;
	const siteLogoMini = currentSiteInfo?.smallAvatar ? currentSiteInfo.smallAvatar : logoMiniPlaceholder;

	const sitesPath = "/sites/";
	const isSite =
		location.pathname.includes(sitesPath) && location.pathname.length > sitesPath.length && !!currentSiteInfo;
	const siteSelector = location.pathname === "/sites";

	const goToPublishedSite = () => {
		const language = siteLanguages.find((l) => l.id === lang.id);
		if (language?.home) {
			const urlHome = `${language.home}${language.home.endsWith("/") ? "" : "/"}`;
			window.open(urlHome, "_blank");
		}
	};

	const goToSites = () => {
		!siteSelector && setHistoryPush("/sites");
	};

	const goToProfile = () => {
		const profileRoute = isSite ? "/sites/profile" : "/profile";
		setHistoryPush(profileRoute);
	};

	const filterRoutes = (routes: IRouter[]) => routes.filter((route) => useForms || !route.path.includes("/forms"));

	const filteredSiteRoutes = filterRoutes(site);
	const filteredMultisiteRoutes = filterRoutes(multisite);

	const config: IConfig = isSite
		? {
				type: "site",
				routes: [...filteredSiteRoutes],
				logo: (
					<>
						<S.LogoSite src={siteLogo} alt="Logo" />
						<S.LogoSiteMini src={siteLogoMini} alt="Logo" />
					</>
				),
			}
		: {
				type: "multisite",
				routes: [...filteredMultisiteRoutes],
				logo: (
					<>
						<S.Logo src={logoPlaceholder} alt="Logo Griddo" />
						<S.LogoSiteMini src={logoMiniPlaceholder} alt="Logo Griddo" />
					</>
				),
			};

	const siteRoute = {
		component: "",
		name: "Visit Site",
		icon: "Web",
		path: "",
		onClick: goToPublishedSite,
	};

	const logoutRoute = {
		component: "",
		name: "Logout",
		icon: "Power",
		path: "",
		onClick: logoutAndNavigate,
	};

	const profileRoute = {
		component: "",
		name: "Profile",
		icon: "User",
		path: isSite ? "/site/profile" : "/profile",
		onClick: goToProfile,
		avatar: currentUser ? { image: currentUser.image?.url, name: currentUser.name } : undefined,
	};

	const toggleIcon = isOpened ? "Collapsed" : "Extend";
	const collapsedTitle = isOpened ? "Collapsed sidebar" : "Expanded sidebar";

	const collapseRoute = {
		component: "",
		name: collapsedTitle,
		icon: toggleIcon,
		path: "",
		onClick: toggleMenu,
	};

	const isSitePublished = isSite && currentSiteInfo && currentSiteInfo.isPublished;

	if (isSite) {
		const isSiteCategoriesAvailable = !!categories.site.length;
		config.routes = config.routes.map((route) =>
			route.path === "/sites/categories" ? { ...route, showInNav: isSiteCategoriesAvailable } : route,
		);
	} else {
		const isGlobalCategoriesAvailable = !!categories.global.length;
		const isGlobalDataAvailable = !!structuredData.global.length;
		config.routes = config.routes.map((route) => {
			if (route.path === "/categories") {
				return { ...route, showInNav: isGlobalCategoriesAvailable };
			}
			if (route.path === "/data") {
				return { ...route, showInNav: isGlobalDataAvailable };
			}
			return route;
		});
	}

	return (
		<NavProvider value={{ state, toggleSubmenu }}>
			<S.NavWrapper type={config.type} isOpened={isOpened}>
				<S.Home type={config.type} onClick={goToSites} isSite={isSite} isOpened={isOpened} siteSelector={siteSelector}>
					{isSite && (
						<S.GoBack>
							<Icon name="LeftArrow" />
						</S.GoBack>
					)}
					<S.NavLink>{config.logo}</S.NavLink>
					{isOpened && !isSite ? <Tag type="square" text={`V ${version}`} color="rgba(80, 87, 255, 0.16)" /> : null}
				</S.Home>
				<S.Lists>
					<S.List>
						{config.routes
							?.filter((route: IRouter) => route.showInNav)
							.map((route: IRouter): JSX.Element => {
								const navItem = (
									<NavItem
										setHistoryPush={setHistoryPush}
										key={route.name}
										route={route}
										location={location}
										type={config.type}
										isOpened={isOpened}
									/>
								);

								return route.permission ? (
									<Restricted key={route.name} to={route.permission}>
										{navItem}
									</Restricted>
								) : (
									navItem
								);
							})}
					</S.List>
					<S.List>
						{isSitePublished && (
							<NavItem setHistoryPush={setHistoryPush} route={siteRoute} type={config.type} isOpened={isOpened} />
						)}
						<S.Separator />
						<NavItem
							setHistoryPush={setHistoryPush}
							route={profileRoute}
							type={config.type}
							isOpened={isOpened}
							location={location}
						/>
						<NavItem setHistoryPush={setHistoryPush} route={logoutRoute} type={config.type} isOpened={isOpened} />
						<S.Separator />
						<NavItem setHistoryPush={setHistoryPush} route={collapseRoute} type={config.type} isOpened={isOpened} />
					</S.List>
				</S.Lists>
			</S.NavWrapper>
		</NavProvider>
	);
};

interface IDispatchProps {
	logoutAndNavigate(): void;
	setHistoryPush(path: string): void;
}

interface IConfig {
	routes: IRouter[];
	type: string;
	logo: JSX.Element;
}

interface INavMenuProps {
	categories: {
		global: IStructuredData[];
		site: IStructuredData[];
	};
	structuredData: {
		global: IStructuredData[];
		site: IStructuredData[];
	};
	currentSiteInfo: ISite | null;
	siteLanguages: ILanguage[];
	lang: { locale: string; id: number };
	globalSettings: IGlobalSettings;
	currentUser: IUser | null;
}

const mapStateToProps = (state: IRootState) => ({
	categories: state.structuredData.categories,
	structuredData: state.structuredData.structuredData,
	currentSiteInfo: state.sites.currentSiteInfo,
	siteLanguages: state.sites.currentSiteLanguages,
	lang: state.app.lang,
	globalSettings: state.app.globalSettings,
	currentUser: state.users.currentUser,
});

type IProps = INavMenuProps & IDispatchProps & RouteComponentProps;

const mapDispatchToProps = {
	logoutAndNavigate: appActions.logoutAndNavigate,
	setHistoryPush: appActions.setHistoryPush,
};

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(NavMenu));
