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

import { structuredData } from "@ax/api";
import { CheckField, Flag, FloatingMenu, Icon, LanguageMenu, Tag, TruncatedTooltip } from "@ax/components";
import { structuredDataActions } from "@ax/containers/StructuredData";
import { isReqOk } from "@ax/helpers";
import { useModal, usePermission } from "@ax/hooks";
import type { ICategoryGroup, ICheck, IDataLanguage, ILanguage, IRootState, IStructuredDataCategory } from "@ax/types";

import { type AnimateLayoutChanges, useSortable } from "@dnd-kit/sortable";

import { DeleteGroupModal, DeleteModal } from "../atoms";
import CategoryPanel from "../CategoryPanel";
import { isCategory, isCategoryGroup } from "../utils";

import * as S from "./style";

const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
	const {
		category,
		deleteStructuredDataContent,
		lang,
		languages,
		isTranslatable,
		isSelected,
		onChange,
		toggleToast,
		getContents,
		currentSiteID,
		deleteCategoryGroup,
		hoverCheck,
		depth,
		indentationWidth,
		collapsed,
		onCollapse,
	} = props;

	const { isOpen, toggleModal } = useModal();
	const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
	const { isOpen: isGroupOpen, toggleModal: toggleGroupModal } = useModal();
	const [deleteGroupCategories, setDeleteGroupCategories] = useState(false);
	const [translation, setTranslation] = useState<{
		lang: { locale: string; id: number };
		isNew: boolean;
		content: IStructuredDataCategory | ICategoryGroup | null;
	} | null>(null);

	const allowedToEditSiteCategory = usePermission("categories.editSiteTaxonomies");
	const allowedToEditGlobalCategory = usePermission("global.globalData.editTaxonomies");
	const allowedToDeleteSiteCategory = usePermission("categories.deleteSiteTaxonomies");
	const allowedToDeleteGlobalCategory = usePermission("global.globalData.deleteTaxonomies");
	const allowedToEditTaxonomy = currentSiteID ? allowedToEditSiteCategory : allowedToEditGlobalCategory;
	const allowedToDeleteTaxonomy = currentSiteID ? allowedToDeleteSiteCategory : allowedToDeleteGlobalCategory;

	const animateLayoutChanges: AnimateLayoutChanges = ({ isSorting, wasDragging }) => !(isSorting || wasDragging);

	const { attributes, isDragging, listeners, setDraggableNodeRef, setDroppableNodeRef, transform, transition } =
		useSortable({
			id: category.id,
			animateLayoutChanges,
		});

	const { locale } = lang;
	const { dataLanguages = [], content } = category;
	const isGroup = category.type === "group";

	const handleClick = () => !isDragging && toggleModal();

	const handleCloseModal = () => {
		setTranslation(null);
		toggleModal();
	};

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

	const handleCheckClick = (e: React.MouseEvent<HTMLDivElement>) => e.stopPropagation();

	const removeCategory = async () => {
		const categoryIDs = dataLanguages.length > 0 ? dataLanguages.map((lang: IDataLanguage) => lang.id) : category.id;
		const deleted = await deleteStructuredDataContent(categoryIDs);

		if (deleted) {
			isDeleteOpen && toggleDeleteModal();
			toggleToast("1 category deleted");
		}
	};

	const removeGroup = async () => {
		const categoryIDs =
			dataLanguages && dataLanguages.length > 0 ? dataLanguages.map((lang: IDataLanguage) => lang.id) : category.id;
		const deleted = await deleteCategoryGroup(categoryIDs, deleteGroupCategories);

		if (deleted) {
			isGroupOpen && toggleGroupModal();
			toggleToast(
				deleteGroupCategories ? "1 grouping category and its categories deleted" : "1 grouping category deleted",
			);
		}
	};

	const menuOptions = allowedToDeleteTaxonomy
		? [
				{
					label: "delete",
					icon: "delete",
					action: isGroup ? toggleGroupModal : toggleDeleteModal,
				},
			]
		: [];

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

		dataLanguages?.forEach((dataLang) => {
			languages?.forEach((language) => {
				if (language.id === dataLang.language) {
					availables.push(language);
				}
			});
		});

		return availables;
	};

	const currentLanguages = getCurrentLanguages();

	const getDataTranslation = async (
		dataID: number,
		langID: number,
		type: "category" | "group",
	): Promise<IStructuredDataCategory | ICategoryGroup | null> => {
		const response =
			type === "group" ? await structuredData.getGroup(dataID) : await structuredData.getDataContent(dataID, langID);
		if (isReqOk(response?.status)) {
			return response.data;
		} else {
			console.log("Error en getDataTranslation");
			return null;
		}
	};

	const handleLanguage = async (language: ILanguage) => {
		const lang = {
			locale: language.locale,
			id: language.id,
		};

		const isNew = !currentLanguages.find((l) => l.id === language.id);
		let content: IStructuredDataCategory | ICategoryGroup | null = null;
		if (!isNew) {
			const translationLang = category.dataLanguages.find((dataLang) => dataLang.language === lang.id);
			content = await getDataTranslation(translationLang?.id || category.id, lang.id, category.type);
		}
		setTranslation({ lang, isNew, content });
		toggleModal();
	};

	const languageMenu = () => (
		<LanguageMenu
			language={locale}
			availableLanguages={languages}
			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 = isTranslatable ? (
		<FloatingMenu Button={FlagsButton}>{languageMenu()}</FloatingMenu>
	) : (
		"Not translatable"
	);

	const mainDeleteModalAction = {
		title: "delete",
		onClick: removeCategory,
	};

	const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };

	const mainDeleteGroupModalAction = {
		title: "Delete",
		onClick: removeGroup,
	};

	const secondaryDeleteGroupModalAction = { title: "Cancel", onClick: toggleGroupModal };

	const selectable = !(isCategoryGroup(category) && category.selectable === false);

	return (
		<>
			<S.Wrapper identationWidth={isDragging ? indentationWidth : indentationWidth * depth} ref={setDroppableNodeRef}>
				<S.CategoryRow
					selected={isSelected}
					onClick={handleClick}
					ref={setDraggableNodeRef}
					cssTransform={transform}
					transition={transition}
					{...listeners}
					{...attributes}
				>
					<S.HandleCell>
						<S.IconWrapperDrag role="cell">
							<Icon name="drag" size="16" />
						</S.IconWrapperDrag>
						<S.IconWrapper onClick={handleCheckClick}>
							{onCollapse && (
								// biome-ignore lint/a11y/useSemanticElements: TODO: fix this
								<div onClick={onCollapse} role="button" tabIndex={0} onKeyDown={onCollapse}>
									{collapsed ? <Icon name="UpArrow" /> : <Icon name="DownArrow" />}
								</div>
							)}
						</S.IconWrapper>
					</S.HandleCell>
					<S.CheckCell role="cell" onClick={handleCheckClick}>
						<CheckField name="check" value={category.id} checked={isSelected || hoverCheck} onChange={handleOnChange} />
					</S.CheckCell>
					<S.NameCell role="cell" clickable={allowedToEditTaxonomy} isGroup={isGroup}>
						{isGroup && (
							<S.FolderWrapper>
								<Icon name="project" size="24" />
							</S.FolderWrapper>
						)}
						<TruncatedTooltip content={content?.title || ""} expanded top={-5}>
							<S.Title>{content?.title || ""}</S.Title>
						</TruncatedTooltip>
					</S.NameCell>
					<S.CodeCell role="cell" clickable={allowedToEditTaxonomy}>
						<TruncatedTooltip content={isCategory(category) && category.content ? category.content.code : ""} expanded top={-5}>
							<S.Code>{isCategory(category) && category.content ? category.content.code : ""}</S.Code>
						</TruncatedTooltip>
					</S.CodeCell>
					<S.SelectableCell role="cell">
						<Tag
							type="square"
							color={selectable ? "" : "#FFD4C7"}
							text={selectable ? "Yes" : "No"}
							textColor={selectable ? "" : "#20224C"}
						/>
					</S.SelectableCell>
					<S.TransCell role="cell">{translations}</S.TransCell>
					<S.ActionsCell role="cell">
						<S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
					</S.ActionsCell>
				</S.CategoryRow>
			</S.Wrapper>
			{isOpen && (
				<CategoryPanel
					isOpen={isOpen}
					toggleModal={handleCloseModal}
					item={translation?.content || category}
					getContents={getContents}
					translation={translation}
					toggleToast={toggleToast}
				/>
			)}
			{isDeleteOpen && (
				<DeleteModal
					isOpen={isDeleteOpen}
					toggleModal={toggleDeleteModal}
					mainModalAction={mainDeleteModalAction}
					secondaryModalAction={secondaryDeleteModalAction}
				/>
			)}
			{isGroupOpen && (
				<DeleteGroupModal
					isOpen={isGroupOpen}
					toggleModal={toggleGroupModal}
					mainModalAction={mainDeleteGroupModalAction}
					secondaryModalAction={secondaryDeleteGroupModalAction}
					deleteGroupCategories={deleteGroupCategories}
					setDeleteGroupCategories={setDeleteGroupCategories}
				/>
			)}
		</>
	);
};

interface IProps {
	category: IStructuredDataCategory | ICategoryGroup;
	languages: ILanguage[];
	lang: { locale: string; id: number | null };
	isTranslatable: boolean;
	isSelected: boolean;
	onChange: (item: ICheck) => void;
	toggleToast: (state: string) => void;
	getContents: (dataId: string) => void;
	currentSiteID: number | null;
	hoverCheck?: boolean;
	depth: number;
	indentationWidth: number;
	collapsed: boolean;
	onCollapse?: () => void;
}

interface IDispatchProps {
	deleteStructuredDataContent(id: number | number[]): Promise<boolean>;
	deleteCategoryGroup(id: number | number[], deleteChildren: boolean): Promise<boolean>;
}

type ICategoryItemProps = IProps & IDispatchProps;

const mapStateToProps = (state: IRootState) => ({
	currentSiteID: state.sites.currentSiteInfo?.id ?? null,
});

const mapDispatchToProps = {
	deleteStructuredDataContent: structuredDataActions.deleteStructuredDataContent,
	deleteCategoryGroup: structuredDataActions.deleteCategoryGroup,
};

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