import { connect } from "react-redux";

import { CheckField, Flag, FloatingMenu, Icon, LanguageMenu, Tooltip, TruncatedTooltip } from "@ax/components";
import { appActions } from "@ax/containers/App";
import { structuredDataActions } from "@ax/containers/StructuredData";
import {
	buildCategoryColumns,
	getActivatedDataPacksIds,
	getHumanLastModifiedDate,
	getScheduleFormatDate,
} from "@ax/helpers";
import { usePermissions } from "@ax/hooks";
import type {
	ICheck,
	IColumn,
	IDataLanguage,
	IDataPack,
	ILanguage,
	IRootState,
	ISchemaField,
	ISite,
	IStructuredData,
	IStructuredDataContent,
} from "@ax/types";

import { getPermission } from "./utils";

import * as S from "./style";

const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
	const {
		structuredData,
		handleClick,
		updateForm,
		deleteStructuredDataContent,
		lang,
		languages,
		setLanguage,
		setEntity,
		currentStructuredData,
		setCurrentDataID,
		resetForm,
		isSelected,
		onChange,
		toggleToast,
		setDeletedItem,
		isEditable,
		activatedDataPacks,
		setDataStatus,
		categoryColumns,
		columns,
		categoryColors,
		addCategoryColors,
		currentSiteInfo,
		hoverCheck,
		getDataContent,
	} = props;

	const isPrivateData = currentStructuredData?.private || false;
	const isGlobal = !currentSiteInfo;

	const isAllowedTo = usePermissions({
		duplicatePages: getPermission("duplicate", isGlobal, isPrivateData),
		publishPages: getPermission("publish", isGlobal, isPrivateData),
		createPages: getPermission("create", isGlobal, isPrivateData),
		deletePages: getPermission("delete", isGlobal, isPrivateData),
	});

	const { locale } = lang;
	const { dataLanguages, publicationScheduled } = structuredData;

	const isScheduledPub = !!publicationScheduled && structuredData.draft;
	const activeColumns = columns.filter((col) => col.show).map((col) => col.id);

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

	const _handleClick = () => {
		getDataContent(structuredData.id);
		setCurrentDataID(structuredData.id);
		handleClick();
	};

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

	const removeItem = async () =>
		deleteStructuredDataContent(structuredData.id).then((deleted: boolean) => {
			if (deleted) {
				setDeletedItem(structuredData.id);
				toggleToast();
			}
		});

	const publishItem = async () => setDataStatus(structuredData.id, "undraft");

	const unpublishItem = async () => setDataStatus(structuredData.id, "draft");

	const duplicateItem = async () => {
		resetForm();
		updateForm({ content: structuredData.content });
		handleClick();
	};

	const checkStatus = () => {
		return isScheduledPub ? "scheduled" : structuredData.draft ? "offline" : "active";
	};

	const getCurrentLanguages = () => {
		const available: ILanguage[] = [];

		dataLanguages.forEach((dataLang: IDataLanguage) => {
			languages?.forEach((language: ILanguage) => {
				if (language.id === dataLang.language) {
					available.push(language);
				}
			});
		});

		return available;
	};

	const currentLanguages = getCurrentLanguages();
	const activatedDataPacksIds = getActivatedDataPacksIds(activatedDataPacks);
	const isDisabled =
		currentStructuredData?.dataPacks[0] && !activatedDataPacksIds.includes(currentStructuredData.dataPacks[0]);

	const availableLanguages = isDisabled || !isAllowedTo.createPages ? currentLanguages : languages;

	const handleLanguage = (language: ILanguage) => {
		const {
			structuredData: { id: dataId, entity },
			getDataContent,
		} = props;

		const { locale, id } = language;

		const lang = {
			locale,
			id,
		};

		const isNew = !currentLanguages.find((l) => l.id === language.id);

		if (isNew) {
			updateForm({
				...structuredData,
				id: null,
				language: id,
				canBeTranslated: true,
			});
		} else {
			getDataContent(dataId, lang);
		}

		setLanguage(lang);
		setEntity(entity);
		handleClick();
	};

	const languageMenu = () => (
		<LanguageMenu
			language={locale}
			availableLanguages={availableLanguages}
			setLanguage={handleLanguage}
			currentLanguages={currentLanguages}
		/>
	);

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

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

	const menuOptions = [];

	if (!isDisabled && isEditable && isAllowedTo.duplicatePages) {
		menuOptions.push({
			label: "duplicate",
			icon: "duplicate",
			action: duplicateItem,
		});
	}

	if (isEditable && isAllowedTo.deletePages) {
		menuOptions.push({
			label: "delete",
			icon: "delete",
			action: removeItem,
		});
	}

	if (isAllowedTo.publishPages) {
		menuOptions.push({
			label: structuredData.draft ? "Publish" : "Unpublish",
			icon: structuredData.draft ? "upload-pending" : "offline",
			action: structuredData.draft ? publishItem : unpublishItem,
		});
	}

	const CategoryColumns = buildCategoryColumns(
		categoryColumns,
		activeColumns,
		structuredData?.content,
		categoryColors,
		addCategoryColors,
		_handleClick,
	);

	return (
		<S.StructuredDataRow role="rowgroup" selected={isSelected} disabled={!isEditable}>
			<S.CheckCell role="cell">
				<CheckField
					name="check"
					value={structuredData.id}
					checked={isSelected || hoverCheck}
					onChange={handleOnChange}
				/>
			</S.CheckCell>
			<S.NameCell role="cell" onClick={_handleClick}>
				<TruncatedTooltip content={structuredData.content.title} expanded top={1}>
					<S.Title>{structuredData.content.title}</S.Title>
				</TruncatedTooltip>
			</S.NameCell>
			{activeColumns.includes("live") && (
				<S.LiveCell role="cell" onClick={_handleClick}>
					<Tooltip content={publishedTooltip[checkStatus()]}>
						<Icon name={checkStatus()} />
					</Tooltip>
				</S.LiveCell>
			)}
			{CategoryColumns}
			{activeColumns.includes("status") && (
				<S.StatusCell role="cell" onClick={_handleClick}>
					<S.ModDate>{`Mod. ${getHumanLastModifiedDate(structuredData.modified)}`}</S.ModDate>
				</S.StatusCell>
			)}
			{activeColumns.includes("translation") && <S.TransCell role="cell">{translations}</S.TransCell>}
			<S.ActionsCell role="cell">
				<S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
			</S.ActionsCell>
		</S.StructuredDataRow>
	);
};

interface IStructuredDataItemProps {
	structuredData: IStructuredDataContent;
	languages: ILanguage[];
	lang: { locale: string; id: number | null };
	currentStructuredData: IStructuredData | null;
	handleClick: () => void;
	updateForm: (form: any) => void;
	setLanguage(lang: { locale: string; id: number | null }): void;
	deleteStructuredDataContent(id: number): Promise<boolean>;
	setEntity(entity: string | null): void;
	getDataContent(id: number, lang?: { locale: string; id: number }): void;
	resetForm(): void;
	isSelected: boolean;
	onChange: (value: ICheck) => void;
	toggleToast(): void;
	setDeletedItem(item: number): void;
	isEditable?: boolean | null;
	activatedDataPacks?: IDataPack[];
	setDataStatus(id: number, status: string): void;
	categoryColumns: ISchemaField[];
	columns: IColumn[];
	categoryColors: any;
	addCategoryColors(cats: string[]): void;
	setCurrentDataID(id: number | null): void;
	currentSiteInfo: ISite | null;
	hoverCheck?: boolean;
}

const mapStateToProps = (state: IRootState) => ({
	currentStructuredData: state.structuredData.currentStructuredData,
	currentSiteInfo: state.sites.currentSiteInfo,
});

const mapDispatchToProps = {
	updateForm: structuredDataActions.updateForm,
	deleteStructuredDataContent: structuredDataActions.deleteStructuredDataContent,
	setEntity: structuredDataActions.setEntity,
	getDataContent: structuredDataActions.getDataContent,
	resetForm: structuredDataActions.resetForm,
	setLanguage: appActions.setLanguage,
	setDataStatus: structuredDataActions.setStatusStructuredDataContent,
	setCurrentDataID: structuredDataActions.setCurrentDataID,
};

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