import { useCallback, useState } from "react";
import { connect } from "react-redux";

import { FieldsBehavior, Modal, Tag } from "@ax/components";
import { dataPacksActions } from "@ax/containers/Settings";
import { useModal } from "@ax/hooks";
import type {
	IDataPack,
	IDataPackConfigImport,
	IDataPackConfigImportCategory,
	IRootState,
	ISite,
	IStructuredData,
	ILanguage,
} from "@ax/types";

import TemplateConfig from "./TemplateConfig";

import * as S from "./style";

const Form = (props: IProps): JSX.Element => {
	const { currentSite, selected, updateFormValue, configFormData, allStructuredData, currentSiteLanguages } = props;

	if (!currentSite) {
		throw new Error(`ERROR: User reached Data Pack form with null site info`);
	}

	if (!selected) {
		throw new Error(`ERROR: User reached Data Pack form without one selected`);
	}

	const { templates, categories, structuredData } = selected;

	const defaultLanguage = currentSiteLanguages?.find((lang) => lang.isDefault);

	const getSubscribedData = (importValue: IDataPackConfigImport[] | undefined) => {
		const value: Record<string, ICategoryValue[]> = {};
		if (!importValue) return value;
		importValue.forEach((item: IDataPackConfigImport) => {
			item.categories?.forEach((cat: IDataPackConfigImportCategory) => {
				const catObj = { value: cat.id, title: cat.title, structuredData: cat.structuredData };
				value[cat.structuredData] = value[cat.structuredData] ? [...value[cat.structuredData], catObj] : [catObj];
			});
		});
		return value;
	};

	const initialValues = configFormData && getSubscribedData(configFormData.import);
	const [selectedCategories, setSelectedCategories] = useState(initialValues);
	const { isOpen, toggleModal } = useModal();

	const indexDefaultOptions = [
		{
			value: true,
			title: "Index",
			name: "index",
		},
		{
			value: false,
			title: "No index",
			name: "noindex",
		},
	];

	const setDefaultParent = (value: number) => updateFormValue({ defaultParent: value });
	const setModifiableOnPage = (value: boolean) => updateFormValue({ modifiableOnPage: value });
	const setIndexDefault = (value: boolean) => updateFormValue({ indexDefault: value });

	const setSubscribedData = (value: Record<string, ICategoryValue[]>) => {
		const newCategories: IDataPackConfigImportCategory[] = [];
		Object.keys(value).forEach((key: string) => {
			const categories: IDataPackConfigImportCategory[] = value[key].map((cat: ICategoryValue) => {
				return { id: cat.value, title: cat.title, structuredData: key };
			});
			newCategories.push(...categories);
		});
		const newValue = [];
		if (newCategories.length) {
			newValue.push({ structuredData: structuredData[0].id, categories: newCategories });
		}
		updateFormValue({ import: newValue });
	};

	const mainAction = {
		title: "Add Subscription",
		onClick: () => setSubscribedData(selectedCategories),
	};

	const secondaryAction = { title: "Cancel", onClick: toggleModal };

	const getCategoryText = useCallback(
		(id: string): string => {
			const data = [...categories, ...allStructuredData.global, ...allStructuredData.site].find(
				(elem) => elem.id === id,
			);
			return data ? data.title : id;
		},
		[categories, allStructuredData],
	);

	const getIsGlobal = useCallback(
		(id: string): boolean => {
			const data = allStructuredData?.site.find((elem) => elem.id === id);
			return !data?.local;
		},
		[allStructuredData],
	);

	const globalPageData = structuredData.find((data) => data.fromPage && !data.local);

	const elements = globalPageData?.relatedCategories?.map((cat) => {
		return { source: cat, key: cat, placeholder: getCategoryText(cat), isGlobal: getIsGlobal(cat) };
	});

	const deleteTag = useCallback(
		(catID: number) => {
			if (!configFormData.import) return;
			const newCategories = configFormData.import.map((type: IDataPackConfigImport) => {
				const filteredCats = type.categories.filter((el: IDataPackConfigImportCategory) => el.id !== catID);
				return { ...type, categories: filteredCats };
			});
			const filteredNewCategories = newCategories.filter((cat: IDataPackConfigImport) => cat.categories.length);
			updateFormValue({ import: filteredNewCategories });
		},
		[configFormData.import, updateFormValue],
	);

	const getCategoryLabels = () => (
		<S.CategoriesWrapper isEmpty={!Object.keys(selectedCategories).length}>
			{configFormData?.import?.map((data: IDataPackConfigImport) => {
				return data.categories?.map((category: IDataPackConfigImportCategory) => {
					const categoryText = getCategoryText(category.structuredData);
					const handleDeleteTag = () => deleteTag(category.id);
					return (
						<Tag
							key={`${categoryText}-${category.title}`}
							text={`${categoryText}: ${category.title}`}
							onDeleteAction={handleDeleteTag}
						/>
					);
				});
			})}
		</S.CategoriesWrapper>
	);

	return (
		<>
			<S.Config>
				{!!globalPageData && (
					<S.SectionContent>
						<S.SubscribeWrapper>
							<S.Heading>Subscribe to data</S.Heading>
							<S.Text>
								If you want to get any Global {selected.title} Pages on this site automatically, you can do so by
								selecting the respective categories.
							</S.Text>
							{configFormData?.import && getCategoryLabels()}
							{elements && elements.length > 0 ? (
								<S.StyledButton type="button" buttonStyle="text" icon="addCircle" onClick={toggleModal}>
									Add Category
								</S.StyledButton>
							) : null}
						</S.SubscribeWrapper>
					</S.SectionContent>
				)}
				<S.SectionContent>
					<S.Heading>Detail page configuration</S.Heading>
					<FieldsBehavior
						title="Default URL parent for detail template"
						name="defaultParent"
						fieldType="AsyncSelect"
						site={currentSite}
						entity={"pages"}
						value={configFormData?.defaultParent}
						onChange={setDefaultParent}
						options={{ excludeDetailPages: true }}
						forceLanguage={defaultLanguage?.id}
					/>
					<FieldsBehavior
						title="Modifiable in page"
						name="modifiableOnPage"
						fieldType="ToggleField"
						value={configFormData?.modifiableOnPage || false}
						onChange={setModifiableOnPage}
					/>
					<FieldsBehavior
						title="Meta robots index default"
						name="indexDefault"
						fieldType="RadioGroup"
						value={configFormData?.indexDefault || false}
						options={indexDefaultOptions}
						onChange={setIndexDefault}
					/>
				</S.SectionContent>
				<TemplateConfig templates={templates} currentSite={currentSite} />
			</S.Config>
			<Modal
				isOpen={isOpen}
				hide={toggleModal}
				size="M"
				title="Subscribe to data"
				mainAction={mainAction}
				secondaryAction={secondaryAction}
			>
				<S.ModalContent>
					<FieldsBehavior
						fieldType="MultiCheckSelectGroup"
						title="Select Categories"
						filled={true}
						elements={elements}
						site={currentSite}
						value={selectedCategories}
						onChange={setSelectedCategories}
						contentLanguages={defaultLanguage?.locale ? [defaultLanguage.locale] : []}
						languages={currentSiteLanguages}
					/>
				</S.ModalContent>
			</Modal>
		</>
	);
};

interface ICategoryValue {
	value: number;
	title: string;
	structuredData: string;
}

interface IDataPackConfig {
	defaultParent?: number;
	modifiableOnPage?: boolean;
	indexDefault?: boolean;
	import?: IDataPackConfigImport[];
}

interface IProps {
	selected: IDataPack | null;
	currentSite: ISite | null;
	updateFormValue: (config: Partial<IDataPackConfig>) => void;
	configFormData: IDataPackConfig;
	allStructuredData: { global: IStructuredData[]; site: IStructuredData[] };
	currentSiteLanguages: ILanguage[];
}

const mapDispatchToProps = {
	updateFormValue: dataPacksActions.updateFormValue,
};

const mapStateToProps = (state: IRootState) => ({
	selected: state.dataPacks.selected,
	currentSite: state.sites.currentSiteInfo,
	configFormData: state.dataPacks.configFormData,
	allStructuredData: state.structuredData.structuredData,
	currentSiteLanguages: state.sites.currentSiteLanguages,
});

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