import { useEffect, useMemo, useState } from "react";
import { type RouteComponentProps, withRouter } from "react-router-dom";

import {
	Button,
	ErrorCenter,
	ExportButton,
	FloatingMenu,
	IconAction,
	LanguageMenu,
	SearchField,
	Tabs,
	Tag,
	Tooltip,
} from "@ax/components";
import { getScheduleFormatDate, trimText } from "@ax/helpers";
import { useModal } from "@ax/hooks";
import type { IActionMenuOption, IErrorItem, ILanguage } from "@ax/types";

import {
	ActionMenu,
	ChangeLanguageModal,
	DownArrowButton,
	ErrorCenterBtn,
	type IMenuButton,
	LanguageBtn,
	PageStatus,
} from "./atoms";

import * as S from "./style";

const AppBar = (props: IProps): JSX.Element => {
	const {
		backLink,
		rightButton,
		rightLineButton,
		title,
		fixedAppBar,
		downArrowMenu,
		tabs,
		pageStatus,
		language,
		availableLanguages,
		currentLanguages,
		languageAction,
		additionalClass,
		subtitle,
		inversed,
		currentPageID,
		searchAction,
		errors,
		errorActions,
		isFromEditor,
		pageStatusActions,
		filterSearchAction,
		searchFilters,
		hasAnimation,
		searchValue,
		isDirty,
		exportAction,
		scheduledPublication,
		isSaving,
		showTagHidden = false,
	} = props;

	const publishedTooltip: Record<string, string> = {
		active: "Live",
		"upload-pending": "Publication pending",
		offline: "Offline",
		"offline-pending": "Offline pending",
		modified: "Live & Modified",
		scheduled: "Scheduled publication",
	};

	const fixedClass = fixedAppBar ? "fixed" : "";
	const isScheduledPub = !!scheduledPublication && pageStatus === "scheduled";
	const currentLang = availableLanguages?.find((lang) => lang.id === language?.id);

	const hasLanguageOrMore = !!(language || pageStatus || rightButton || rightLineButton);
	const hasStatusOrMore = !!(pageStatus || rightButton || rightLineButton);
	const hasActionItems = !!(rightButton || rightLineButton);

	const languageTooltip = typeof currentPageID === "number" ? "Add language" : undefined;

	const classes = [fixedClass, additionalClass, hasAnimation && "animate"].filter(Boolean).join(" ");

	const { isOpen, toggleModal } = useModal();
	const [langSelected, setLangSelected] = useState<ILanguage | undefined>(currentLang);

	useEffect(() => {
		setLangSelected(currentLang);
	}, [currentLang]);

	const goToPages = () =>
		typeof backLink === "string" ? props.history.push(backLink, { isFromEditor }) : props.history.goBack();

	const handleLanguage = (item?: ILanguage) => {
		if (!item || !languageAction) return;

		if (langSelected && langSelected.locale !== item.locale && isDirty) {
			setLangSelected(item);
			toggleModal();
			return;
		}

		languageAction(item);
	};

	const mainAction = {
		title: "Change language",
		onClick: () => handleLanguage(langSelected),
	};

	const secondaryAction = {
		title: "Cancel",
		onClick: () => {
			setLangSelected(currentLang);
			toggleModal();
		},
	};

	const BoundLanguageBtn = useMemo(
		() => () => <LanguageBtn language={language!} availableLanguages={availableLanguages} />,
		[language, availableLanguages],
	);

	return (
		<S.Header className={classes} inversed={inversed} data-testid="appbar-header">
			<S.WrapperTitle>
				{backLink && (
					<span data-testid="back-button-wrapper">
						<Tooltip content="Back to content screen" bottom>
							<IconAction icon="FullArrowLeft" onClick={goToPages} inversed={inversed} />
						</Tooltip>
					</span>
				)}
				<S.Title>
					{trimText(title, 50)}
					<S.Subtitle>{subtitle}</S.Subtitle>
				</S.Title>
			</S.WrapperTitle>
			{tabs && (
				<S.WrapperTabs data-testid="tabs-wrapper">
					<S.TabsContent>
						<Tabs
							tabs={tabs.tabSet}
							icons={tabs.icons}
							active={tabs.selectedTab}
							setSelectedTab={tabs.action}
							isInAppBar
							inversed={inversed}
							disabled={tabs.disabled}
						/>
					</S.TabsContent>
				</S.WrapperTabs>
			)}
			<S.WrapperEnd>
				{searchAction && (
					<>
						<S.SearchWrapper length={searchFilters?.length ? 8 : 5} data-testid="search-wrapper">
							<SearchField
								onChange={searchAction}
								onFilterChange={filterSearchAction}
								searchFilters={searchFilters}
								value={searchValue}
								closeOnInactive
							/>
						</S.SearchWrapper>
						{hasLanguageOrMore && <S.Separator />}
					</>
				)}
				{showTagHidden && (
					<>
						<S.TagWrapper>
							<Tag text="Hidden" type="square" icon="hide" />
						</S.TagWrapper>
						{hasLanguageOrMore && <S.Separator />}
					</>
				)}
				{language && availableLanguages && (
					<>
						<ChangeLanguageModal
							isOpen={isOpen}
							hide={toggleModal}
							title="Change language"
							mainAction={mainAction}
							secondaryAction={secondaryAction}
						/>
						<S.LanguageWrapper data-testid="language-wrapper">
							<Tooltip content={languageTooltip} hideOnClick bottom>
								<FloatingMenu
									Button={BoundLanguageBtn}
									isInAppBar
									position="left"
									offset={rightButton || rightLineButton ? 0 : -85}
									disabled={!availableLanguages.length}
								>
									<LanguageMenu
										language={language.locale}
										availableLanguages={availableLanguages}
										currentLanguages={currentLanguages || availableLanguages}
										setLanguage={handleLanguage}
										isInAppBar
										isDraft={pageStatus === "modified"}
									/>
								</FloatingMenu>
							</Tooltip>
						</S.LanguageWrapper>
						{hasStatusOrMore && <S.Separator />}
					</>
				)}
				{pageStatus && (
					<>
						<S.IconStatusWrapper data-testid="page-status-wrapper" last={!rightButton && !rightLineButton}>
							<Tooltip content={publishedTooltip[pageStatus]} bottom>
								<PageStatus
									pageStatus={pageStatus}
									pageStatusActions={pageStatusActions}
									hasRightButton={!!(rightButton || rightLineButton)}
								/>
							</Tooltip>
							{isScheduledPub && (
								<S.ScheduledDate inversed={inversed}>{getScheduleFormatDate(scheduledPublication)}</S.ScheduledDate>
							)}
						</S.IconStatusWrapper>
						{hasActionItems && <S.Separator />}
					</>
				)}
				{isFromEditor && errors && errors.length > 0 && (
					<>
						<S.IconStatusWrapper last={false} data-testid="error-center-wrapper">
							<FloatingMenu Button={ErrorCenterBtn} isInAppBar position="left" offset={-20}>
								<ErrorCenter errors={errors} actions={errorActions} />
							</FloatingMenu>
						</S.IconStatusWrapper>
						<S.Separator />
					</>
				)}
				{exportAction && <ExportButton onClick={exportAction} />}
				{rightLineButton && (
					<Button
						className="button"
						type="button"
						buttonStyle="line"
						onClick={rightLineButton.action}
						{...rightLineButton}
					>
						{rightLineButton.label}
					</Button>
				)}
				{rightButton && (
					<Button className="button" type="button" onClick={rightButton.action} {...rightButton}>
						{rightButton.label}
					</Button>
				)}
				{downArrowMenu?.displayed && (downArrowMenu.button || downArrowMenu.options.length > 0) && (
					<Tooltip content="Actions" hideOnClick bottom>
						<FloatingMenu Button={DownArrowButton} isInAppBar disabled={isSaving}>
							<ActionMenu menu={downArrowMenu} />
						</FloatingMenu>
					</Tooltip>
				)}
			</S.WrapperEnd>
		</S.Header>
	);
};

export interface IAppBarProps {
	backLink?: boolean | string;
	rightButton?: { label: string; disabled?: boolean; action: () => void };
	rightLineButton?: { label: string; disabled?: boolean; action: () => void };
	tabs?: {
		tabSet?: any[];
		icons?: { name: string; text: string }[];
		selectedTab: string;
		action: (tab: string) => void;
		disabled?: boolean;
	};
	downArrowMenu?: { displayed: boolean; options: IActionMenuOption[]; button?: IMenuButton | null };
	title: string;
	subtitle?: string;
	fixedAppBar?: boolean;
	pageStatus?: string;
	language?: { locale: string; id: number | null } | null;
	availableLanguages?: ILanguage[];
	currentLanguages?: ILanguage[];
	languageAction?: (lang: ILanguage) => void;
	additionalClass?: string;
	inversed?: boolean;
	currentPageID?: number;
	searchAction?(query: string): void;
	filterSearchAction?(filter: string): void;
	searchFilters?: any;
	errors?: IErrorItem[];
	errorActions?: {
		goToError(editorID: number, tab: string, template: boolean, parentEditorID?: number): void;
		goToPackage?(): void;
	};
	isFromEditor?: boolean;
	pageStatusActions?: IActionMenuOption[];
	hasAnimation?: boolean;
	searchValue?: string;
	isDirty?: boolean;
	exportAction?(formats: (number | string)[]): void;
	scheduledPublication?: string | null;
	isSaving?: boolean;
	showTagHidden?: boolean;
}

type IProps = IAppBarProps & RouteComponentProps;

export default withRouter(AppBar);
