import type React from "react";

import { CheckField, Icon, SideModal } from "@ax/components";
import { getDisplayName, isEmptyContainer, trimText } from "@ax/helpers";
import { useModal } from "@ax/hooks";
import type { ICheck, IComponent, ModuleCategoryInfo } from "@ax/types";

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

import { ArrayContainerButtons, ContainerButtons } from "./atoms";
import EmptyContainer from "./EmptyContainer";

import * as S from "./style";

const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
	const {
		goTo,
		objKey,
		editorID,
		text,
		moduleTitle,
		selectedContent,
		whiteList,
		isArray,
		value,
		actions,
		title,
		categories,
		disabled,
		canDuplicate,
		canDelete,
		parentKey,
		theme,
		canReplace,
		actionReplace,
		arrayLength,
		isSelected,
		onChange,
		hasMenu = true,
		toggleToast,
		className,
		isMultiDragging = false,
		draggingCount = 0,
		isActive = false,
	} = props;

	const { addComponentAction, deleteModuleAction, duplicateModuleAction, copyModuleAction, replaceModuleAction } =
		actions || {};

	const { isOpen, toggleModal } = useModal();

	const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
		id: editorID,
		disabled: !!disabled,
	});

	const whiteListFirstItem: string | undefined = whiteList?.[0];
	const hasMultipleOptions = !!(whiteList && whiteList.length > 1);

	const containerOptions = parentKey && objKey ? selectedContent[parentKey][objKey] : objKey && selectedContent[objKey];

	let containerText: string = text ? text : whiteListFirstItem ? getDisplayName(whiteListFirstItem) : "";
	let componentID: number = editorID ? editorID : containerOptions?.editorID;

	const containerInfo = !isArray && value ? isEmptyContainer(value, hasMultipleOptions) : null;
	const isEmpty: boolean = !!containerInfo?.isEmpty;

	const currentComponent = containerInfo?.containedComponent;

	if (currentComponent) {
		containerText = currentComponent.containerText;
		componentID = currentComponent.componentID;
	}

	const handleClick = () => {
		if (!disabled) {
			goTo(componentID);
		}
	};

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

	const removeItem = () => deleteModuleAction?.([editorID], parentKey);

	const duplicateItem = () => parentKey && duplicateModuleAction?.([editorID], parentKey);

	const copyItem = () => {
		const isCopied = copyModuleAction?.([editorID]);
		isCopied && toggleToast?.("1 module copied to clipboard");
	};

	const copyOpt = {
		label: "copy",
		icon: "copy",
		action: copyItem,
	};

	const duplicateOpt = {
		label: "duplicate",
		icon: "duplicate",
		action: duplicateItem,
	};

	const deleteOpt = {
		label: "delete",
		icon: "delete",
		action: removeItem,
		disabled: !canDelete,
		helpText: !canDelete ? "CRM Required. Can't remove." : "",
	};

	const replaceOpt = {
		label: "replace",
		icon: "change",
		action: () => actionReplace?.(),
	};

	const actionArrayMenuOptions = [
		copyOpt,
		...(canDuplicate ? [duplicateOpt] : []),
		deleteOpt,
		...(canReplace ? [replaceOpt] : []),
	];

	const actionMenuOptions = [
		{
			label: "replace",
			icon: "change",
			action: toggleModal,
		},
	];

	const actionMenuIcon = "more";

	const handleEmptyContainerClick = () => addComponentAction?.(value, objKey);

	const handleOptionClick = (option: string | IComponent) => addComponentAction?.(option, objKey);

	const compoundKey = parentKey ? `${parentKey}.${objKey}` : objKey;

	const handleReplace = (option: string | IComponent) => {
		compoundKey && typeof option !== "string" && replaceModuleAction?.(option, selectedContent, compoundKey);
	};

	const arrayContainerButtonsProps = {
		options: actionArrayMenuOptions,
		icon: actionMenuIcon,
	};

	const handleChange = (value: ICheck) => onChange?.(value);

	const textComponents = isMultiDragging ? (
		<S.LabelDrag>
			Dragging <span>{draggingCount}</span> modules
		</S.LabelDrag>
	) : (
		<>
			<S.Label containerInfo={!!containerInfo} disabled={disabled}>
				{trimText(containerText, 25)}
			</S.Label>
			{moduleTitle && <S.Title disabled={disabled}>{trimText(moduleTitle, 25)}</S.Title>}
		</>
	);

	return isEmpty ? (
		<EmptyContainer
			whiteList={whiteList}
			categories={categories}
			hasMultipleOptions={hasMultipleOptions}
			goTo={handleEmptyContainerClick}
			handleAdd={handleOptionClick}
			componentOptions={containerOptions}
			title={title}
			theme={theme}
			disabled={disabled}
		/>
	) : (
		<>
			<S.Component
				disabled={disabled}
				className={`editorId-${editorID} ${className}`}
				onClick={handleClick}
				isActive={isActive}
				cssTransform={transform}
				transition={transition}
				ref={setNodeRef}
				{...listeners}
				{...attributes}
				data-testid="component-container"
			>
				{isArray && (
					<S.HandleWrapper hidden={arrayLength < 2} data-testid="handle-wrapper">
						<S.IconHandleWrapper>
							<Icon name="drag" size="16" />
						</S.IconHandleWrapper>
					</S.HandleWrapper>
				)}
				{isArray && !isMultiDragging && arrayLength > 1 && (
					<S.CheckWrapper onClick={handleCheckClick}>
						<CheckField
							name="check"
							value={editorID}
							checked={isSelected}
							onChange={handleChange}
							light={true}
							disabled={disabled}
						/>
					</S.CheckWrapper>
				)}
				{containerInfo && !disabled && (
					<S.IconWrapper data-testid="icon-wrapper">
						<Icon name={containerText} />
					</S.IconWrapper>
				)}
				<S.Text>{textComponents}</S.Text>
				{isArray && !disabled && !hasMenu && <ArrayContainerButtons {...arrayContainerButtonsProps} />}
				{!isArray && !disabled && hasMultipleOptions && (
					<ContainerButtons options={actionMenuOptions} icon={actionMenuIcon} />
				)}
			</S.Component>
			{!isArray && hasMultipleOptions && (
				<SideModal
					optionsType={"components"}
					whiteList={whiteList}
					categories={categories}
					onClick={handleReplace}
					toggleModal={toggleModal}
					isOpen={isOpen}
					componentOptions={containerOptions}
					current={currentComponent}
					theme={theme}
				/>
			)}
		</>
	);
};

export interface IComponentContainerProps {
	text: string;
	editorID: number;
	whiteList: string[] | undefined;
	categories?: ModuleCategoryInfo[];
	goTo(editorID: number): void;
	isArray?: boolean | undefined;
	value?: any;
	title?: string;
	moduleTitle?: string;
	selectedContent?: any;
	objKey?: string;
	actions?: {
		addComponentAction: (componentType: IComponent | string, key?: string) => void;
		deleteModuleAction: (editorID: number[], key?: string) => void;
		duplicateModuleAction: (editorID: number[], key?: string) => number;
		copyModuleAction: (editorID: number[]) => boolean | number;
		replaceModuleAction: (module: IComponent, parent: any, objKey: string) => void;
	};
	disabled?: boolean;
	canDuplicate?: boolean;
	canDelete?: boolean;
	parentKey?: string;
	theme: string;
	canReplace?: boolean;
	actionReplace?: () => void;
	arrayLength: number;
	isSelected?: boolean;
	onChange?: (value: ICheck) => void;
	hasMenu?: boolean;
	toggleToast?: (state: string) => void;
	className?: string;
	isMultiDragging?: boolean;
	draggingCount?: number;
	isActive?: boolean;
}

export default ComponentContainer;
