import React, { useEffect, useState } from "react";
import { connect } from "react-redux";

import { navigationActions } from "@ax/containers/Navigation";
import { CheckField, Loader, Modal, Select } from "@ax/components";
import { ICheck, IModal, INavPages, IRootState, IUpdateNavigationParam } from "@ax/types";
import { useBulkSelection } from "@ax/hooks";

import * as S from "./style";

const ReplaceNavModal = (props: IProps) => {
	const {
		isOpen,
		type,
		navID,
		currentSiteID,
		navigationPages,
		isLoading,
		currentDefaultsContent,
		toggleModal,
		toggleToast,
		getPagesByNavigation,
		updatePageNavigation,
	} = props;

	const initialItems = navigationPages ? navigationPages.items.pagesInUse : [];
	const totalItems = navigationPages ? navigationPages.items.totalItems : 0;
	const pagesIds = initialItems.map((item) => item.pageId);

	const [navSelected, setNavSelected] = useState<any>();
	const [items, setItems] = useState(initialItems);

	useEffect(() => {
		const getPages = async () => navID && currentSiteID && (await getPagesByNavigation(type, navID, currentSiteID));
		getPages();
	}, []);

	useEffect(() => {
		setItems(initialItems);
	}, [initialItems]);

	const { resetBulkSelection, selectedItems, isSelected, checkState, addToBulkSelection, selectAllItems } =
		useBulkSelection(pagesIds);

	const handleAllChange = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());

	const options = currentDefaultsContent
		.filter(
			(nav) =>
				navID && ((typeof navID === "number" && nav.id !== navID) || (Array.isArray(navID) && !navID.includes(nav.id))),
		)
		.map((nav) => {
			return { value: nav.id, label: nav.title };
		});

	const fullOptions = [{ value: 0, label: `${type} by default` }, ...options];

	const handleSelectChange = (value: number | string) => {
		if (typeof value !== "number") return;
		setNavSelected(value);
		const newItems = items.map((item) => {
			if (isSelected(item.pageId)) {
				return { ...item, navigationId: value };
			} else {
				return item;
			}
		});
		setItems(newItems);
		resetBulkSelection();
	};

	const handleChangeNav = async () => {
		const newNavs = items.reduce(
			(acc: { navigationId: number | null; type: "header" | "footer"; pageId: number }[], current) => {
				const original = initialItems.find((initItem) => initItem.pageId === current.pageId);
				if (original && original.navigationId !== current.navigationId) {
					const nav = {
						navigationId: current.navigationId === 0 ? null : current.navigationId,
						type,
						pageId: current.pageId,
					};
					return [...acc, nav];
				}
				return acc;
			},
			[],
		);

		const updated = await updatePageNavigation({ navigations: newNavs });

		if (updated) {
			toggleModal();
			toggleToast(newNavs.length);
		}
	};

	const secondaryAction = navSelected !== undefined ? { title: "Cancel", onClick: toggleModal } : undefined;
	const mainAction = navSelected !== undefined ? { title: "Change Navigation", onClick: handleChangeNav } : undefined;

	return (
		<Modal
			isOpen={isOpen}
			hide={toggleModal}
			title="Pages in use"
			size="L"
			secondaryAction={secondaryAction}
			mainAction={mainAction}
		>
			{isLoading ? (
				<S.LoadingWrapper>
					<Loader name="circle" />
				</S.LoadingWrapper>
			) : (
				<S.ModalContent>
					<S.TotalWrapper>
						This {type} appears on <strong>{totalItems} pages</strong>:
					</S.TotalWrapper>
					<S.Header>
						<S.CheckWrapper>
							<CheckField
								name="checkAll"
								value="checkAll"
								checked={checkState.isAllSelected}
								indeterminate={checkState.indeterminate}
								onChange={handleAllChange}
							/>
						</S.CheckWrapper>
						<S.PageInfo>
							<S.Text>Select All</S.Text>
						</S.PageInfo>
						<S.HeaderInfo>
							{selectedItems.all.length > 0 && (
								<Select
									options={fullOptions}
									name="selectNav"
									type="mini"
									value={navSelected}
									onChange={handleSelectChange}
									placeholder={`Change ${type}`}
								/>
							)}
						</S.HeaderInfo>
					</S.Header>
					<S.ItemList>
						{items.map((item) => {
							const handleChange = (value: ICheck) => addToBulkSelection(value);
							const navigation =
								item.navigationId === 0
									? { title: `${type} by default` }
									: currentDefaultsContent.find((nav: any) => nav.id === item.navigationId);
							const original = initialItems.find((initItem) => initItem.pageId === item.pageId);
							return (
								<S.Item key={item.pageId}>
									<S.CheckWrapper>
										<CheckField
											name={`check-${item.pageId}`}
											value={item.pageId}
											checked={isSelected(item.pageId)}
											onChange={handleChange}
										/>
									</S.CheckWrapper>
									<S.PageInfo>
										<S.Title>{item.pageTitle}</S.Title>
										<S.PagePath>{item.pathString}</S.PagePath>
									</S.PageInfo>
									<S.HeaderInfo>
										<S.Tag active={original?.navigationId !== item.navigationId}>{navigation?.title}</S.Tag>
									</S.HeaderInfo>
								</S.Item>
							);
						})}
					</S.ItemList>
				</S.ModalContent>
			)}
		</Modal>
	);
};

interface IReplaceModalProps {
	type: "header" | "footer";
	navID: number | number[] | null;
	currentSiteID: number | null;
	navigationPages: INavPages | null;
	isLoading: boolean;
	currentDefaultsContent: any[];
	toggleToast: (pages: number) => void;
	getPagesByNavigation: (type: string, navID: number | number[], siteID: number) => Promise<void>;
	updatePageNavigation: (data: IUpdateNavigationParam) => Promise<boolean>;
}

type IProps = IModal & IReplaceModalProps;

const mapStateToProps = (state: IRootState) => ({
	currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
	navigationPages: state.navigation.navigationPages,
	isLoading: state.app.isLoading,
	currentDefaultsContent: state.navigation.currentDefaultsContent,
});

const mapDispatchToProps = {
	getPagesByNavigation: navigationActions.getPagesByNavigation,
	updatePageNavigation: navigationActions.updatePageNavigation,
};

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