import { useEffect, useRef, useState } from "react";

import { useModals, usePermissionsForSite } from "@ax/hooks";
import type { IGetSitesParams, IQueryValue, ISite } from "@ax/types";

import type { ISortedListStatus } from "./utils";

const sortedListDefaultState: ISortedListStatus = {
	isAscending: false,
	sortedByTitle: false,
	sortedByLastAccess: true,
	sortedByDateCreated: false,
};

const useSortedListStatus = (initialValue?: ISortedListStatus) => {
	const [sortedListStatus, setSortedListStatus] = useState<ISortedListStatus>(initialValue || sortedListDefaultState);

	return {
		sortedListStatus,
		setSortedListStatus,
	};
};

const useFilterQuery = (defaultValues?: { order: IQueryValue[]; liveStatus: IQueryValue[] }): ISitesFilterQuery => {
	const initialQueryValues: Record<string, IQueryValue[]> = {
		order: [{ value: "lastAccess-desc", label: "lastAccess-desc" }],
		liveStatus: [{ value: "all", label: "All" }],
	};

	const getFiltersQuery = (filterValues: Record<string, IQueryValue[]>): string => {
		const { order, liveStatus } = filterValues;

		let filterQuery = "";
		const currentQuery = (pointer: string, values: IQueryValue[]) => {
			if (!values.length || !values[0].value || values[0].value === "all") {
				return "";
			}
			return `&${pointer}=${values[0].value}`;
		};

		const isNotInitialValue = (pointer: keyof Record<string, IQueryValue[]>) => {
			return filterValues[pointer] && initialQueryValues[pointer] !== filterValues[pointer];
		};

		if (isNotInitialValue("liveStatus")) {
			const query = currentQuery("liveStatus", liveStatus);
			filterQuery = `${filterQuery}${query}`;
		}

		const query = currentQuery("order", order);
		filterQuery = `${filterQuery}${query}`;

		return filterQuery;
	};

	const [query, setQuery] = useState(defaultValues || initialQueryValues);
	const initialFilterQuery = getFiltersQuery(defaultValues || initialQueryValues);
	const [currentFilterQuery, setCurrentFilterQuery] = useState(initialFilterQuery);

	const setFilterQuery = (filterValues: Record<string, IQueryValue[]>) => {
		const filterQuery = getFiltersQuery(filterValues);
		setCurrentFilterQuery(filterQuery);
	};

	const setFiltersSelection = (pointer: string, filter: IQueryValue[], isAscendent?: boolean) => {
		const { order, liveStatus } = query;
		const orderMethod = isAscendent ? "asc" : "desc";
		const liveStatusValue: Record<string, string> = {
			all: "all",
			active: "online",
			offline: "offline",
		};

		const liveValue = filter.length > 0 ? [{ value: liveStatusValue[filter[0].value], label: filter[0].label }] : [];

		const filterValues = {
			order: pointer === "order" ? [{ value: `${filter[0].value}-${orderMethod}`, label: filter[0].label }] : order,
			liveStatus: pointer === "liveStatus" ? liveValue : liveStatus,
		};

		setQuery(filterValues);
		setFilterQuery(filterValues);
	};

	const resetFilterQuery = () => {
		setQuery(initialQueryValues);
		setCurrentFilterQuery("");
	};

	return {
		setFiltersSelection,
		resetFilterQuery,
		filterValues: query,
		filterQuery: currentFilterQuery,
	};
};

const useIsMount = () => {
	const isMountRef = useRef(true);
	useEffect(() => {
		isMountRef.current = false;
	}, []);
	return isMountRef.current;
};

interface ISitesFilterQuery {
	setFiltersSelection(pointer: string, filter: IQueryValue[], isAscendent?: boolean): void;
	resetFilterQuery(): void;
	filterValues: Record<string, IQueryValue[]>;
	filterQuery: string;
}

interface IUseSiteActionsParams {
	site: ISite;
	setSiteInfo(currentSiteInfo: ISite): Promise<void>;
	setHistoryPush(page: string, isEditor: boolean): void;
	deleteSite(siteID: number, params?: IGetSitesParams): Promise<void>;
	publishSite(siteID: number, params?: IGetSitesParams): Promise<void>;
	unpublishSite(siteID: number, params?: IGetSitesParams): Promise<void>;
	getParams: () => IGetSitesParams;
}

const publishedTooltip: Record<string, string> = {
	active: "Live",
	"upload-pending": "Publication pending",
	offline: "Offline",
	"offline-pending": "Offline pending",
};

const getPublishedState = (isPublished: boolean, updated: boolean): string => {
	switch (isPublished) {
		case true:
			return updated ? "active" : "upload-pending";
		case false:
			return updated ? "offline" : "offline-pending";
	}
};

const useSiteActions = ({
	site,
	setSiteInfo,
	setHistoryPush,
	deleteSite,
	publishSite,
	unpublishSite,
	getParams,
}: IUseSiteActionsParams) => {
	const { isOpen, toggleModal } = useModals(["delete", "publish"]);
	const [inputValue, setInputValue] = useState("");

	const { allowedToDeleteSite, allowedToPublishSite, allowedToUnpublishSite } = usePermissionsForSite(site.id, {
		allowedToDeleteSite: "general.deleteSite",
		allowedToPublishSite: "general.publishSite",
		allowedToUnpublishSite: "general.unpublishSite",
	});

	const { updated, isPublished } = site;
	const publishedState = getPublishedState(isPublished, updated);

	const setSite = async () => {
		await setSiteInfo(site);
		setHistoryPush("/sites/pages", false);
	};

	const deleteOption = allowedToDeleteSite
		? { label: "delete", icon: "delete", action: () => toggleModal("delete") }
		: undefined;

	const publishOptionProps =
		isPublished && allowedToUnpublishSite
			? { label: "Unpublish", icon: "offlinePending" }
			: !isPublished && allowedToPublishSite
				? { label: "Publish", icon: "uploadPending" }
				: null;

	const publishOption = publishOptionProps
		? { label: publishOptionProps.label, icon: publishOptionProps.icon, action: () => toggleModal("publish") }
		: undefined;

	const menuOptions = [deleteOption, publishOption];

	const handleDeleteSite = async () => {
		const params = getParams();
		await deleteSite(site.id, params);
		toggleModal("delete");
	};

	const mainDeleteAction = {
		title: "Delete Site",
		onClick: handleDeleteSite,
		disabled: inputValue !== site.name.toUpperCase(),
	};
	const secondaryDeleteAction = { title: "Cancel", onClick: () => toggleModal("delete") };

	const handlePublishSite = async () => {
		const params = getParams();
		await publishSite(site.id, params);
		toggleModal("publish");
	};

	const handleUnpublishSite = async () => {
		const params = getParams();
		await unpublishSite(site.id, params);
		toggleModal("publish");
	};

	const publishModal = isPublished
		? {
				mainAction: { title: "Unpublish Site", onClick: handleUnpublishSite },
				secondaryAction: { title: "Cancel", onClick: () => toggleModal("publish") },
				title: "Unpublish Site",
				content: (
					<p>
						You are going to unpublish <strong>{site.name}</strong> site.
						<br />
						This action can take several minutes.
					</p>
				),
			}
		: {
				mainAction: { title: "Publish Site", onClick: handlePublishSite },
				secondaryAction: { title: "Cancel", onClick: () => toggleModal("publish") },
				title: "Publish Site",
				content: (
					<p>
						You are going to publish <strong>{site.name}</strong> site.
						<br />
						Make sure everything is ok before you do it.
					</p>
				),
			};

	return {
		publishedState,
		publishedTooltip,
		setSite,
		menuOptions,
		inputValue,
		setInputValue,
		isOpenDelete: isOpen("delete"),
		toggleDeleteModal: () => toggleModal("delete"),
		mainDeleteAction,
		secondaryDeleteAction,
		isOpenPublish: isOpen("publish"),
		togglePublishModal: () => toggleModal("publish"),
		publishModal,
	};
};

export { useSortedListStatus, useFilterQuery, useIsMount, useSiteActions };
