import { useEffect, useRef, useState } from "react";

import { Button, EmptyState, MenuItem, Modal, Tooltip } from "@ax/components";
import { getDefaultTheme } from "@ax/helpers";
import type { IModal, IStructuredData, ITemplateOption } from "@ax/types";

import ContentItem from "./ContentItem";
import { getOptionsByDataPacks } from "./utils";

import * as S from "./style";

const NewContentModal = (props: INewContentModalProps) => {
	const { isOpen, selectedValue, filters, values, structuredData, toggleModal, selectPage, addNewPage } = props;

	const allFilters = [{ label: "All content", value: "all" }, ...filters];

	const valueObj = values.find((value) => value.name === selectedValue);
	const currentDataPack = valueObj?.dataPacks?.length ? valueObj.dataPacks[0] : valueObj?.type || "";
	const currentType = valueObj ? currentDataPack : "all";

	const initialState: IState = {
		items: {},
		selectedOption: valueObj ? { ...valueObj, currentDataPack } : null,
		selectedType: currentType,
		searchQuery: "",
	};

	const [state, setState] = useState(initialState);
	const listRef = useRef<HTMLDivElement>(null);

	const theme = getDefaultTheme();

	const itemsByDataPack = getOptionsByDataPacks(filters, values);

	// biome-ignore lint/correctness/useExhaustiveDependencies: avoid infinite loop
	useEffect(() => {
		let filteredItems: Record<string, ITemplateOption[]> = {};
		let selected = state.selectedOption;

		if (state.searchQuery.trim().length) {
			filteredItems.result = values.filter((value) =>
				value.title.toLowerCase().includes(state.searchQuery.toLowerCase()),
			);
		} else {
			filteredItems =
				state.selectedType === "all"
					? itemsByDataPack
					: state.selectedType && itemsByDataPack[state.selectedType]
						? { [state.selectedType]: itemsByDataPack[state.selectedType] }
						: {};

			if (state.selectedType === "all" && selected === null) {
				selected = Object.values(filteredItems)?.[0]?.[0] ?? null;
			}
		}

		setState((state) => ({ ...state, items: filteredItems, selectedOption: selected }));

		if (listRef.current) {
			listRef.current.scrollTo(0, 0);
		}
	}, [state.selectedType, state.searchQuery]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: avoid infinite loop
	useEffect(() => {
		const handleKeyPress = (event: KeyboardEvent) => {
			if (event.key === "Enter") {
				handleCreateContent();
			}
		};

		document.addEventListener("keydown", handleKeyPress);

		return () => {
			document.removeEventListener("keydown", handleKeyPress);
		};
	}, [state.selectedOption]);

	const setType = (type: string) =>
		setState((state) => ({ ...state, selectedType: type, selectedOption: null, searchQuery: "" }));

	const setSearchQuery = (searchQuery: string) => setState((state) => ({ ...state, searchQuery, selectedType: "all" }));

	const handleCreateContent = () => {
		if (!state.selectedType || !state.selectedOption) return;
		addNewPage(state.selectedOption.isData ? state.selectedOption.value : undefined);
	};

	return (
		<Modal
			isOpen={isOpen}
			hide={toggleModal}
			searchAction={setSearchQuery}
			searchValue={state.searchQuery}
			size="XL"
			title="New content"
		>
			{
				<S.Wrapper>
					<S.LeftColumn>
						<S.MenuWrapper>
							{allFilters.map((item, i: number) => {
								const handleClick = () => item.value !== state.selectedType && setType(item.value);
								const isSelected = item.value === state.selectedType;
								const selectedClass = isSelected ? "selected" : "";
								return (
									<MenuItem key={`${item.value}${i}`} className={selectedClass} onClick={handleClick}>
										<S.NavLink>
											<S.Link active={isSelected}>{item.label}</S.Link>
										</S.NavLink>
									</MenuItem>
								);
							})}
						</S.MenuWrapper>
					</S.LeftColumn>
					<S.RightColumn>
						<S.Content ref={listRef}>
							{Object.keys(state.items).map((key: string) => {
								const pack = filters.find((filter) => filter.value === key);
								return (
									<S.DataWrapper key={key}>
										<S.DataTitle hasBold={state.selectedType !== "all"}>{pack?.label}</S.DataTitle>
										{!state.items[key].length && !!state.searchQuery.trim().length ? (
											<S.EmptyStateWrapper>
												<EmptyState
													icon="search"
													title="Oh! No Results Found"
													message="We couldn’t find what you are looking for. Please, try another search."
												/>
											</S.EmptyStateWrapper>
										) : (
											<S.DataContent>
												{state.items[key].map((item) => {
													const structuredDataItem = structuredData.find(
														(data) => data.id.toLowerCase() === item.type.toLowerCase(),
													);

													const handleClick = () => {
														setState((state) => ({ ...state, selectedOption: { ...item, currentDataPack: key } }));
														selectPage(item.name);
													};

													const isSelected =
														item.name === state.selectedOption?.name && key === state.selectedOption.currentDataPack;

													return (
														<ContentItem
															key={item.name}
															item={item}
															theme={theme}
															isSelected={isSelected}
															onClick={handleClick}
															pack={pack?.label}
															structuredData={structuredDataItem}
															listRef={listRef}
														/>
													);
												})}
											</S.DataContent>
										)}
									</S.DataWrapper>
								);
							})}
						</S.Content>
						<S.ModalFooter>
							<Button type="button" buttonStyle="minimal" onClick={toggleModal}>
								Close
							</Button>
							<Tooltip content={!state.selectedOption ? "Select one item first" : undefined}>
								<Button type="button" disabled={!state.selectedOption} onClick={handleCreateContent}>
									Create New
								</Button>
							</Tooltip>
						</S.ModalFooter>
					</S.RightColumn>
				</S.Wrapper>
			}
		</Modal>
	);
};

export interface IOptionFilter {
	label: string;
	value: string;
	isData?: boolean;
	special?: string;
	mode?: string;
}

interface IState {
	items: Record<string, ITemplateOption[]>;
	selectedOption: ISelectedOption | null;
	selectedType: string | null;
	searchQuery: string;
}

interface ISelectedOption extends ITemplateOption {
	currentDataPack?: string;
}

interface INewContentModalProps extends IModal {
	selectPage: (value: string) => void;
	addNewPage: (data?: string) => void;
	filters: IOptionFilter[];
	values: ITemplateOption[];
	selectedValue: string;
	structuredData: IStructuredData[];
}

export default NewContentModal;
