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

import type {
	IAvailableSites,
	IFilterValue,
	IGetPagesParams,
	IModal,
	INavigation,
	IPage,
	IQueryValue,
	ISite,
} from "@ax/types";
import { CheckGroupFilter, Loading, Modal } from "@ax/components";
import { getStructuredDataTitle } from "@ax/helpers";
import { useCategoryColors } from "@ax/hooks";
import { appActions } from "@ax/containers/App";
import { pageEditorActions } from "@ax/containers/PageEditor";
import { navigationActions } from "@ax/containers/Navigation";
import { sitesActions } from "@ax/containers/Sites";
import {
	addSiteOptions,
	getFilterDataIds,
	getFilterSitesIds,
	getNavigations,
	getPages,
	getSite,
	getSiteOptions,
	getStructuredDataOptions,
} from "./utils";
import FormUseItem from "./FormUseItem";

import * as S from "./style";

const FormUseModal = (props: IFormUseModalModal): JSX.Element => {
	const { isOpen, toggleModal, formInUse, isSiteView } = props;
	const { page, header, footer } = formInUse || {};
	const navigationsIds = React.useMemo(() => [...(header ?? []), ...(footer ?? [])], [header, footer]);

	const [isLoading, setIsLoading] = useState<boolean>(false);
	const [filters, setFilters] = useState({
		filterStructuredData: [{ value: "all", label: "All" }],
		filterSites: [{ value: "all", label: "All" }],
	});
	const [options, setOptions] = useState<Record<string, IFilterValue[]>>({
		sites: [{ value: "all", name: "all", title: "All" }],
		structuredData: [{ value: "all", name: "all", title: "All" }],
	});
	const [items, setItems] = useState<{ pages: IPage[]; navigations: INavigation[] }>({ pages: [], navigations: [] });
	const { categoryColors, addCategoryColors } = useCategoryColors();
	const firstUpdate = useRef(true);

	const getParams = useCallback(() => {
		const sitesIDs = getFilterSitesIds(filters.filterSites);
		const dataIDs = getFilterDataIds(filters.filterStructuredData);
		const isBasicChecked = filters.filterStructuredData.some((item) => item.value === "unique");

		const params: IGetPagesParams = {
			deleted: false,
			filterPages: page,
			ignoreLang: true,
			filterSites: sitesIDs.length ? sitesIDs : undefined,
			filterStructuredData: dataIDs.length ? dataIDs.join(",") : undefined,
			type: isBasicChecked ? "unique" : undefined,
		};

		return params;
	}, [page, filters]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		let isMounted = true;

		const fetchData = async () => {
			setIsLoading(true);

			try {
				let allSites: IFilterValue[] = [];
				let structuredData: IFilterValue[] = [];
				let pagesData: IPage[] = [];
				let navsData: INavigation[] = [];

				if (page?.length) {
					const params = getParams();
					const data = await getPages(params);

					if (isMounted && data.length) {
						pagesData = data;

						if (firstUpdate.current) {
							allSites = getSiteOptions(data);
							structuredData = getStructuredDataOptions(data);
						}
					}
				}

				const dataIDs = getFilterDataIds(filters.filterStructuredData);
				if (!dataIDs.length && navigationsIds.length) {
					const data = await getNavigations(navigationsIds);

					if (isMounted && data.length) {
						const sitesIDs = getFilterSitesIds(filters.filterSites);
						navsData = sitesIDs.length ? data.filter((item: INavigation) => sitesIDs.includes(item.site)) : data;

						if (firstUpdate.current) {
							const siteIds = data.map((item: INavigation) => item.site);
							const sitesWithNavs = await addSiteOptions(allSites, siteIds);
							allSites = sitesWithNavs;
						}
					}
				}

				setItems((prev) =>
					prev.pages.length !== pagesData.length || prev.navigations.length !== navsData.length
						? { pages: pagesData, navigations: navsData }
						: prev,
				);

				if (firstUpdate.current && isMounted) {
					setOptions((state) => ({
						...state,
						sites: [...state.sites, ...allSites],
						structuredData: [...state.structuredData, ...structuredData],
					}));
					firstUpdate.current = false;
				}
			} catch (error) {
				console.error("Error general en fetchData:", error);
			} finally {
				if (isMounted) setIsLoading(false);
			}
		};

		fetchData();

		return () => {
			isMounted = false;
		};
	}, [getParams]);

	const filterItems = (pointer: string, filter: IQueryValue[]) => {
		setFilters((state) => ({ ...state, [pointer]: filter }));
	};

	const goToPage = async (pageID: number, siteID: number | null) => {
		const { setCurrentPageID, setSiteInfo, setHistoryPush } = props;
		if (!isSiteView && siteID) {
			const siteInfo = await getSite(siteID);
			if (siteInfo) {
				await setSiteInfo(siteInfo);
			}
			setCurrentPageID(pageID);
			setHistoryPush("/sites/pages/editor", true);
		} else {
			setCurrentPageID(pageID);
			setHistoryPush(isSiteView ? "/sites/pages/editor" : "/data/pages/editor", true);
		}
	};

	const goToNavigation = async (navID: number, siteID: number, type: "header" | "footer") => {
		const { setHeader, setFooter, setSelectedDefault, setHistoryPush, setSiteInfo } = props;
		const isHeader = type === "header";

		if (!isSiteView) {
			const siteInfo = await getSite(siteID);
			if (siteInfo) {
				await setSiteInfo(siteInfo);
			}
		}
		setSelectedDefault(isHeader ? "Headers" : "Footers");
		isHeader ? setHeader(navID) : setFooter(navID);
		setHistoryPush("/sites/navigations/editor", true);
	};

	const pagesText = items.pages.length ? `${items.pages.length} page${items.pages.length > 1 ? "s" : ""}` : "";
	const navigationsText = items.navigations.length
		? `${items.navigations.length} navigation module${items.navigations.length > 1 ? "s" : ""}`
		: "";
	const andText = items.navigations.length && items.pages.length ? " and " : "";
	const textInfo = `This form appears on ${pagesText}${andText}${navigationsText}:`;

	return (
		<Modal isOpen={isOpen} hide={toggleModal} title="Using this form" size="L" height={640}>
			<S.ModalContent>
				<S.ListHeader>
					<S.HeaderText>{textInfo}</S.HeaderText>
					<S.Type>
						<CheckGroupFilter
							filterItems={filterItems}
							value={filters.filterStructuredData}
							pointer="filterStructuredData"
							label="Content Type"
							description="Type Filter"
							initialState={["all"]}
							selectAllOption="all"
							filters={options.structuredData}
							menuPosition="left"
							multipleSelection={false}
						/>
					</S.Type>
					{!isSiteView && (
						<S.SiteInfo>
							<CheckGroupFilter
								filterItems={filterItems}
								value={filters.filterSites}
								pointer="filterSites"
								label="Site"
								description="Site Filter"
								initialState={["all"]}
								selectAllOption="all"
								filters={options.sites}
								menuPosition="left"
							/>
						</S.SiteInfo>
					)}
					<S.Action></S.Action>
				</S.ListHeader>
				{isLoading ? (
					<Loading />
				) : (
					<S.ListContent>
						{items.navigations.map((item) => {
							const { id, title, site, type } = item;

							const handleGoToNavigation = () => id && goToNavigation(id, site, type);
							const availableSiteNames =
								options.sites.filter((item) => item.name === site).map((item) => item.title) || [];

							return (
								<FormUseItem
									key={id}
									title={title}
									subtitle={"Navigation modules"}
									availableSiteNames={availableSiteNames}
									isSiteView={isSiteView}
									goToItem={handleGoToNavigation}
								/>
							);
						})}
						{items.pages.map((item) => {
							const { id, title, fullPath, structuredData, availableSites, site } = item;
							const structuredDataTitle = structuredData ? getStructuredDataTitle(structuredData) : "Base Page";

							addCategoryColors([structuredDataTitle]);

							const availableSiteNames = availableSites?.map((site: IAvailableSites) => site.name) || [];

							const handleGoToPage = () => goToPage(id, site);

							return (
								<FormUseItem
									key={id}
									title={title}
									subtitle={fullPath?.page || ""}
									structuredDataTitle={structuredDataTitle}
									categoryColors={categoryColors}
									availableSiteNames={availableSiteNames}
									isSiteView={isSiteView}
									goToItem={handleGoToPage}
								/>
							);
						})}
					</S.ListContent>
				)}
			</S.ModalContent>
		</Modal>
	);
};

interface IFormUseModalModal extends IModal {
	formInUse: { page?: number[]; header?: number[]; footer?: number[] } | null;
	isSiteView: boolean;
	setHistoryPush: (path: string, isEditor: boolean) => void;
	setCurrentPageID: (currentPageID: number | null) => void;
	setSiteInfo(currentSiteInfo: ISite): Promise<void>;
	setSelectedDefault(selectedDefault: string): void;
	setHeader(id: number | null): void;
	setFooter(id: number | null): void;
}

const mapDispatchToProps = {
	setHistoryPush: appActions.setHistoryPush,
	setCurrentPageID: pageEditorActions.setCurrentPageID,
	setSiteInfo: sitesActions.setSiteInfo,
	setSelectedDefault: navigationActions.setSelectedDefault,
	setHeader: navigationActions.setHeader,
	setFooter: navigationActions.setFooter,
};

export default connect(null, mapDispatchToProps)(FormUseModal);
