import React, { useEffect } from "react";
import { connect } from "react-redux";
import { Switch, Route, matchPath } from "react-router-dom";

import { ErrorGuard } from "@ax/guards";
import type { IRootState, IUser } from "@ax/types";
import { appActions } from "@ax/containers/App";
import { publicRoutes, privateRoutes, routes, type IRouter } from "@ax/routes";
import type { ILogoutAction } from "@ax/containers/App/interfaces";
import { ErrorPage } from "@ax/components";
import { usePermission } from "@ax/hooks";
import type { IGlobalSettings } from "@ax/containers/App/reducer";
import NavMenu from "./NavMenu";
import PrivateRoute from "./PrivateRoute";
import Logout from "./Logout";

import * as S from "./style";

const Routing = (props: IProps) => {
	const { path, token, currentUser, globalSettings, setHistoryPush, logout } = props;

	const { useForms } = globalSettings;

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		path === "/" && setHistoryPush("/login");

		if (path === "/login" || path === "/") {
			const loggedInUser = localStorage.getItem("user");
			if (loggedInUser) {
				setHistoryPush("/sites", false);
			} else {
				logout();
			}
		}
	}, []);

	const route: IRouter | undefined = routes.find((item: IRouter) => {
		const cleanPath = path?.replace(/\/$/, "");

		const match = cleanPath
			? matchPath(cleanPath, {
					path: item.path,
					exact: true,
					strict: false,
				})
			: null;

		return (
			!!match ||
			item.routesGroups?.find((subitem) => {
				return subitem.routes.find((subroute) => subroute.path === path);
			})
		);
	});

	const isAllowed = usePermission(route?.permission);

	if (route && !!currentUser && !isAllowed) {
		route.hideNav = true;
	}

	const getRoute = (component: any, path: string, isPrivate: boolean, permission: string | string[] | undefined) =>
		isPrivate ? (
			<PrivateRoute
				token={token}
				path={path}
				component={component}
				permission={permission}
				currentUser={currentUser}
				exact
			/>
		) : (
			<Route path={path} component={component} exact />
		);

	const mapSubroutes = (subgroup: any, isPrivate: boolean) => {
		return subgroup.routes.map((subRoute: any, subI: number) => (
			<React.Fragment key={subI}>
				{getRoute(subRoute.component, subRoute.path, isPrivate, subRoute.permission)}
			</React.Fragment>
		));
	};

	const mapRoutes = (routeArr: IRouter[], isPrivate: boolean) =>
		routeArr
			.filter((singleRoute: IRouter) => useForms || (!useForms && !singleRoute.path.includes("/forms")))
			.map((singleRoute: IRouter, i) => (
				<React.Fragment key={i}>
					{getRoute(singleRoute.component, singleRoute.path, isPrivate, singleRoute.permission)}
					{singleRoute.routesGroups?.map((subgroup: any) => mapSubroutes(subgroup, isPrivate))}
				</React.Fragment>
			));

	return (
		<S.Root>
			{route && !route.hideNav && <NavMenu />}
			<S.Main>
				<ErrorGuard />
				<Switch>
					<Route path="/">
						{mapRoutes(publicRoutes, false)}
						{mapRoutes(privateRoutes, true)}
						<Route path="/logout" exact component={Logout} />
						<Route path="/500" exact render={() => <ErrorPage type="500" />} />
						<Route path="/404" render={() => <ErrorPage type="404" />} />
					</Route>
				</Switch>
			</S.Main>
		</S.Root>
	);
};

const mapStateToProps = (state: IRootState) => ({
	path: state.router.location.pathname,
	token: state.app.token,
	currentUser: state.users.currentUser,
	globalSettings: state.app.globalSettings,
});

interface IDispatchProps {
	setHistoryPush(path: string, isEditor?: boolean): Promise<void>;
	logout(): ILogoutAction;
}

interface IStateProps {
	path?: string;
	token: string;
	currentUser: IUser | null;
	globalSettings: IGlobalSettings;
}

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

type IProps = IStateProps & IDispatchProps;

export default connect(mapStateToProps, mapDispatchToProps)(Routing);
