import { useState } from "react";
import { connect } from "react-redux";

import {
	CheckField,
	ElementsTooltip,
	Flag,
	FloatingMenu,
	Icon,
	LanguageMenu,
	Tooltip,
	TruncatedTooltip,
} from "@ax/components";
import { appActions } from "@ax/containers/App";
import { pageEditorActions } from "@ax/containers/PageEditor";
import { type ISetCurrentPageIDAction, pageStatus } from "@ax/containers/PageEditor/interfaces";
import {
	buildCategoryColumns,
	getHumanLastModifiedDate,
	getScheduleFormatDate,
	getStructuredDataTitle,
	trimText,
} from "@ax/helpers";
import { useModals, usePermissions } from "@ax/hooks";
import type {
	IAvailableSites,
	ICheck,
	IColumn,
	ILanguage,
	IPage,
	IPageLanguage,
	IRootState,
	ISavePageParams,
	ISchemaField,
} from "@ax/types";

import { DeleteModal, DuplicateModal, UnpublishModal } from "./atoms";
import { getCurrentLanguages } from "./utils";

import * as S from "./style";

const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
	const {
		handleClick,
		lang,
		languages,
		setLanguage,
		isSelected,
		onChange,
		isEditable,
		isTranslatable,
		globalPage,
		isAllPages,
		updatePageStatus,
		duplicatePage,
		getPage,
		validatePage,
		setHistoryPush,
		deletePage,
		getGlobalPages,
		createNewTranslation,
		setCurrentPageID,
		toggleToast,
		setDeletedItem,
		deleteBulk,
		categoryColumns,
		columns,
		categoryColors,
		addCategoryColors,
		skipReview,
		hoverCheck,
		isSaving,
	} = props;

	const { locale } = lang;
	const {
		pageLanguages,
		metaDescription,
		metaTitle,
		isIndexed,
		availableSites,
		structuredData,
		structuredDataContent,
		fullPath,
		publicationScheduled,
		liveStatus,
		haveDraftPage,
	} = globalPage;

	const activeColumns = columns.filter((col) => col.show).map((col) => col.id);
	const isScheduledPub =
		!!publicationScheduled && (liveStatus.status === pageStatus.SCHEDULED || liveStatus.status === pageStatus.MODIFIED);

	const initValue = { title: "", slug: "" };
	const [duplicateModalState, setDuplicateModalState] = useState(initValue);
	const { isOpen, toggleModal } = useModals(["duplicate", "delete", "unpublish"]);
	const [deleteAllVersions, setDeleteAllVersions] = useState(false);

	const API_URL = process.env.GRIDDO_API_URL || process.env.REACT_APP_API_ENDPOINT;

	const isAllowedTo = usePermissions({
		duplicatePages: "global.globalData.duplicateGlobalData",
		publishPages: "global.globalData.publishUnpublishAllGlobalData",
		createPages: "global.globalData.createAllGlobalData",
		deletePages: "global.globalData.deleteAllGlobalData",
		editContentPages: "global.globalData.editAllGlobalData",
	});

	const publishedTooltip: Record<string, string> = {
		active: "Live",
		"upload-pending": "Publication pending",
		offline: "Offline",
		"offline-pending": "Offline pending",
		modified: "Live & Modified",
		scheduled: `Scheduled publication: ${isScheduledPub ? getScheduleFormatDate(publicationScheduled) : ""}`,
	};

	const _handleClick = () => {
		handleClick(true, globalPage);
	};

	const handleEditLivePage = () => {
		handleClick(true, globalPage, true);
	};

	const handleOnChange = (value: ICheck) => onChange(value);

	const checkSeoDone = (value: string | boolean) => {
		if (typeof value === "string") {
			value = value.trim();
		}
		if (value) {
			return (
				<S.StyledDone>
					<Icon name="done" />
				</S.StyledDone>
			);
		}
		return (
			<S.StyledClose>
				<Icon name="close" />
			</S.StyledClose>
		);
	};

	const SeoItems = {
		Index: () => <S.StyledSeo>{checkSeoDone(isIndexed)}Indexed</S.StyledSeo>,
		Title: () => <S.StyledSeo>{checkSeoDone(metaTitle)}Title</S.StyledSeo>,
		Description: () => <S.StyledSeo>{checkSeoDone(metaDescription)}Description</S.StyledSeo>,
	};

	const SeoTitleMenu = () => {
		if (metaTitle) {
			return (
				<FloatingMenu Button={SeoItems.Title}>
					<S.FloatingSeo>{metaTitle}</S.FloatingSeo>
				</FloatingMenu>
			);
		}
		return SeoItems.Title();
	};

	const SeoDescriptionMenu = () => {
		if (metaDescription) {
			return (
				<FloatingMenu Button={SeoItems.Description}>
					<S.FloatingSeo>{metaDescription}</S.FloatingSeo>
				</FloatingMenu>
			);
		}
		return SeoItems.Description();
	};

	const removeItem = async () => {
		const deletePageParams: ISavePageParams = { site: "global", page: globalPage };
		const allPageVersions = globalPage.pageLanguages.map((lang: IPageLanguage) => lang.pageId);
		const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage(deletePageParams);
		const deletedItems = deleteAllVersions ? allPageVersions : globalPage.id;
		if (isDeleted) {
			setDeletedItem(deletedItems);
			toggleToast();
		}
		toggleModal("delete");
		getGlobalPages();
	};

	const publishPage = async () => {
		await getPage(globalPage.id);
		const isValidated = skipReview ? true : await validatePage(true);

		if (isValidated) {
			await updatePageStatus([globalPage.id], pageStatus.UPLOAD_PENDING, true);
			getGlobalPages();
		}
	};

	const unpublishPage = async () => {
		await updatePageStatus([globalPage.id], pageStatus.OFFLINE_PENDING, true);
		getGlobalPages();
	};

	const cancelPublishPage = async () => {
		await updatePageStatus([globalPage.id], pageStatus.OFFLINE, true);
		getGlobalPages();
	};

	const handleDuplicatePage = async () => {
		const isDuplicated = await duplicatePage(globalPage.id, duplicateModalState);
		if (isDuplicated) {
			toggleModal("duplicate");
			setHistoryPush("data/pages/editor", true);
		}
	};

	let menuOptions: IPageOption[] = [];

	if (isAllowedTo.duplicatePages) {
		menuOptions.push({
			label: "duplicate",
			icon: "duplicate",
			action: () => toggleModal("duplicate"),
		});
	}

	if (isAllowedTo.deletePages) {
		menuOptions.push({
			label: "delete",
			icon: "delete",
			action: () => toggleModal("delete"),
		});
	}

	const getPublishItem = (status: string) => {
		switch (status) {
			case pageStatus.OFFLINE:
			case pageStatus.OFFLINE_PENDING:
				return {
					label: "publish",
					icon: "upload-pending",
					action: publishPage,
				};
			case pageStatus.PUBLISHED:
				return {
					label: "unpublish",
					icon: "offline",
					action: globalPage.haveDraftPage ? () => toggleModal("unpublish") : unpublishPage,
				};
			case pageStatus.UPLOAD_PENDING:
				return {
					label: "unpublish",
					icon: "offline",
					action: globalPage.haveDraftPage ? () => toggleModal("unpublish") : cancelPublishPage,
				};
			default:
				return null;
		}
	};

	const viewPage = () => {
		window.open(globalPage.fullUrl || `${API_URL}/page/go/${globalPage.id}`, "_blank");
	};

	const viewOption = {
		label: "View online",
		icon: "View",
		action: viewPage,
	};

	const editOptions = [
		{
			label: "View live",
			icon: "active",
			action: handleEditLivePage,
			color: true,
		},
	];

	if (isAllowedTo.editContentPages) {
		editOptions.unshift({
			label: "Edit draft",
			icon: "modified",
			action: _handleClick,
			color: true,
		});
	}

	const publishAction = getPublishItem(globalPage.liveStatus?.status);
	const publishItems = publishAction && isAllowedTo.publishPages ? [publishAction] : [];
	menuOptions = [...publishItems, ...menuOptions];

	menuOptions = globalPage.haveDraftPage ? [...editOptions, ...menuOptions] : menuOptions;

	menuOptions = globalPage.liveStatus?.status === pageStatus.PUBLISHED ? [viewOption, ...menuOptions] : menuOptions;

	const handleCloseDuplicate = () => {
		toggleModal("duplicate");
		setDuplicateModalState({ title: "", slug: "" });
	};

	const mainDuplicateModalAction = {
		title: "Duplicate",
		onClick: handleDuplicatePage,
		disabled: !duplicateModalState.title.trim() || !duplicateModalState.slug.trim() || isSaving,
	};

	const secondaryDuplicateModalAction = { title: "Cancel", onClick: handleCloseDuplicate };

	const isTranslated = globalPage.pageLanguages.length > 1;

	const mainDeleteModalAction = {
		title: "Delete page",
		onClick: removeItem,
	};
	const secondaryDeleteModalAction = { title: "Cancel", onClick: () => toggleModal("delete") };

	const currentLanguages = getCurrentLanguages(languages, pageLanguages);

	const changeLanguage = (language: { locale: string; id: number | null }) => {
		return setLanguage(language);
	};

	const handleNewTranslation = (isNewTranslation: boolean) => {
		setCurrentPageID(globalPage.id);
		createNewTranslation(isNewTranslation);
	};

	const languageActions = {
		setLanguage: changeLanguage,
		createNewTranslation: handleNewTranslation,
		getGlobalPages,
	};

	const getSelectedPageLanguage = (language: ILanguage) =>
		pageLanguages.find((lang: IPageLanguage) => lang.languageId === language.id);

	const handleLanguage = (language: ILanguage) => {
		if (!languageActions || !languageActions.setLanguage) return;

		const { locale, id } = language;
		const lang = { locale, id };

		languageActions.setLanguage(lang);

		const selectedPageLanguage = getSelectedPageLanguage(language);

		selectedPageLanguage ? setCurrentPageID(selectedPageLanguage.pageId) : languageActions.createNewTranslation?.(true);

		setHistoryPush("data/pages/editor", true);
	};

	const languageMenu = () => (
		<LanguageMenu
			language={locale}
			availableLanguages={isAllowedTo.createPages ? languages : currentLanguages}
			setLanguage={handleLanguage}
			currentLanguages={currentLanguages}
		/>
	);

	const FlagsButton = () => (
		<S.FlagsWrapper>
			{currentLanguages.slice(0, 2).map((language, i: number) => (
				<Flag key={`${language.language}${i}`} name={language.locale} size="15" />
			))}
			<span>({currentLanguages.length})</span>
		</S.FlagsWrapper>
	);

	const translations = isTranslatable ? (
		<FloatingMenu Button={FlagsButton}>{languageMenu()}</FloatingMenu>
	) : (
		"Not translatable"
	);

	const availableSiteNames = availableSites?.map((site: IAvailableSites) => site.name);

	const getLiveStatus = () => (isScheduledPub ? "scheduled" : haveDraftPage ? "modified" : liveStatus.status);

	const mainUnpublishAction = { title: "Ok", onClick: () => toggleModal("unpublish") };

	const CategoryColumns = buildCategoryColumns(
		categoryColumns,
		activeColumns,
		structuredDataContent,
		categoryColors,
		addCategoryColors,
		_handleClick,
	);

	const structuredDataTitle = structuredData ? getStructuredDataTitle(structuredData) : "";
	const typeTitle =
		structuredDataTitle && structuredDataTitle.length > 20 ? (
			<Tooltip content={structuredDataTitle} left={0} top={1} expanded>
				{trimText(structuredDataTitle, 19)}
			</Tooltip>
		) : (
			<>{structuredDataTitle}</>
		);

	return (
		<>
			<S.StructuredDataRow role="rowgroup" selected={isSelected} disabled={!isEditable}>
				<S.CheckCell role="cell">
					<CheckField name="check" value={globalPage.id} checked={isSelected || hoverCheck} onChange={handleOnChange} />
				</S.CheckCell>
				<S.NameCell role="cell" onClick={_handleClick}>
					<TruncatedTooltip content={globalPage.title} expanded top={-5}>
						<S.Title>{globalPage.title}</S.Title>
					</TruncatedTooltip>
					<TruncatedTooltip content={fullPath.page} expanded top={5}>
						<S.Slug>{fullPath.page}</S.Slug>
					</TruncatedTooltip>
				</S.NameCell>
				{isAllPages && activeColumns.includes("type") && <S.TypeCell role="cell">{typeTitle}</S.TypeCell>}
				{activeColumns.includes("site") && (
					<S.SiteCell role="cell">
						<ElementsTooltip elements={availableSiteNames || []} elementsPerRow={3} maxChar={30} />
					</S.SiteCell>
				)}
				{activeColumns.includes("live") && (
					<S.LiveCell role="cell" onClick={_handleClick}>
						<Tooltip content={publishedTooltip[getLiveStatus()]}>
							<Icon name={getLiveStatus()} />
						</Tooltip>
					</S.LiveCell>
				)}
				{CategoryColumns}
				{activeColumns.includes("status") && (
					<S.StatusCell role="cell" onClick={_handleClick}>
						<S.ModDate>{`Mod. ${getHumanLastModifiedDate(globalPage.modified)}`}</S.ModDate>
					</S.StatusCell>
				)}
				{activeColumns.includes("translation") && <S.TransCell role="cell">{translations}</S.TransCell>}
				{activeColumns.includes("seo") && (
					<S.SeoCell role="cell">
						<SeoItems.Index />
						{SeoTitleMenu()}
						{SeoDescriptionMenu()}
					</S.SeoCell>
				)}
				<S.ActionsCell role="cell">
					<S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
				</S.ActionsCell>
			</S.StructuredDataRow>
			<DuplicateModal
				isOpen={isOpen("duplicate")}
				toggleModal={() => toggleModal("duplicate")}
				mainModalAction={mainDuplicateModalAction}
				secondaryModalAction={secondaryDuplicateModalAction}
				{...{ duplicateModalState, setDuplicateModalState }}
			/>
			<DeleteModal
				isOpen={isOpen("delete")}
				toggleModal={() => toggleModal("delete")}
				mainModalAction={mainDeleteModalAction}
				secondaryModalAction={secondaryDeleteModalAction}
				{...{ title: globalPage.title, isTranslated, deleteAllVersions, setDeleteAllVersions }}
			/>
			<UnpublishModal
				isOpen={isOpen("unpublish")}
				toggleModal={() => toggleModal("unpublish")}
				mainModalAction={mainUnpublishAction}
			/>
		</>
	);
};

interface IPageOption {
	label: string;
	icon: string;
	action: () => void | Promise<void>;
	disabled?: boolean;
	helpText?: string | null;
	color?: boolean;
}

interface IGlobalPageItemProps {
	languages: ILanguage[];
	lang: { locale: string; id: number | null };
	handleClick: (isFromPage?: boolean, globalPage?: IPage, forceLive?: boolean) => void;
	setLanguage(lang: { locale: string; id: number | null }): void;
	isSelected: boolean;
	onChange: (e: ICheck) => void;
	isEditable?: boolean | null;
	isTranslatable?: boolean;
	isAllPages?: boolean;
	globalPage: IPage;
	updatePageStatus(ids: number[], status: string, updatedFromList: boolean): Promise<boolean>;
	duplicatePage(pageID: number, data: { title: string; slug: string }, siteID?: number): Promise<boolean>;
	getPage(pageID?: number, global?: boolean): Promise<void>;
	validatePage(publish?: boolean, browserRef?: any, currentPage?: IPage): Promise<boolean>;
	setHistoryPush(path: string, isEditor: boolean): void;
	deletePage(params?: ISavePageParams, currentLanguage?: string): Promise<boolean>;
	getGlobalPages(): void;
	createNewTranslation(isNewTranslation: boolean): void;
	setCurrentPageID(currentPageID: number | null): ISetCurrentPageIDAction;
	toggleToast(): void;
	setDeletedItem(item: number | number[] | null): void;
	deleteBulk(ids: number[]): Promise<boolean>;
	categoryColumns: ISchemaField[];
	columns: IColumn[];
	categoryColors: any;
	addCategoryColors(cats: string[]): void;
	skipReview?: boolean;
	hoverCheck?: boolean;
	isSaving: boolean;
}

const mapStateToProps = (state: IRootState) => ({
	isSaving: state.app.isSaving,
});

const mapDispatchToProps = {
	setLanguage: appActions.setLanguage,
	updatePageStatus: pageEditorActions.updatePageStatus,
	duplicatePage: pageEditorActions.duplicatePage,
	getPage: pageEditorActions.getPage,
	validatePage: pageEditorActions.validatePage,
	setHistoryPush: appActions.setHistoryPush,
	deletePage: pageEditorActions.deletePage,
	createNewTranslation: pageEditorActions.createNewTranslation,
	setCurrentPageID: pageEditorActions.setCurrentPageID,
	deleteBulk: pageEditorActions.deleteBulk,
};

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