import { pageStatus } from "@ax/containers/PageEditor/interfaces";
import { arrayInsert, getActivatedDataPacksIds } from "@ax/helpers";
import type { IBulkSelectedItems } from "@ax/hooks";
import type {
	IColumn,
	IDataPack,
	IPage,
	IPageLanguage,
	ISchemaField,
	IStructuredData,
	IStructuredDataFilter,
	IStructuredDataValue,
} from "@ax/types";

import { config } from "components";

const schemas = config.schemas.ui;
const { templates } = schemas;

const getOptionFilters = (options: IStructuredData[], dataPacks: IDataPack[]) => {
	const dataPacksIds = getActivatedDataPacksIds(dataPacks);

	const mappedOptions = options.flatMap((option: IStructuredData) =>
		option.dataPacks.reduce((acc: { label: string; value: string; isData: boolean }[], current: string) => {
			if (dataPacksIds.includes(current)) {
				const currentDataPack = dataPacks.find((activatedDataPack: IDataPack) => current === activatedDataPack.id);
				if (currentDataPack) {
					const option = {
						label: currentDataPack.title,
						value: currentDataPack.id,
						isData: true,
					};
					acc.push(option);
					return acc;
				}
			}
			return acc;
		}, []),
	);

	const uniqueFilters = [...new Map(mappedOptions.map((item: any) => [item.value, item])).values()];
	const sortedUniqueFilters = uniqueFilters.sort((a, b) => a.label.localeCompare(b.label));
	return sortedUniqueFilters;
};

const mapStructuredOptions = (options: IStructuredData[]) => {
	const pureOptions = options.filter((option: IStructuredData) => !option.fromPage && !option.local);

	return pureOptions.map((option: IStructuredData) => {
		const { id, title, dataPacks } = option;
		const type = title.toLowerCase();

		return {
			name: id,
			value: id,
			title,
			type,
			isData: true,
			dataPacks,
		};
	});
};

const getOptionValues = (options: IStructuredData[]): IStructuredDataValue[] => {
	const templatesOptionsValues: IStructuredDataValue[] = [];

	Object.keys(templates).forEach((schema: string) => {
		const currSchema = templates[schema];

		const { component, displayName, dataPacks } = currSchema;
		const type =
			!!currSchema.type && currSchema.type.value && currSchema.type.value && currSchema.type.value.toLowerCase();

		const isDetailTemplate = currSchema.type.mode === "detail";
		const structuredDataItem = options.find((data) => data.id.toLowerCase() === type);

		!!currSchema.type &&
			isDetailTemplate &&
			structuredDataItem?.local === false &&
			templatesOptionsValues.push({
				name: component,
				title: displayName || "",
				type,
				value: component,
				dataPacks,
			});
	});

	return [...templatesOptionsValues, ...mapStructuredOptions(options)];
};

const getSelectedValue = (
	options: { filters: IStructuredDataFilter[]; values: IStructuredDataValue[] },
	filter?: string,
): string => {
	const firstOptionsFilter = options.filters[0]?.value;
	const selectedValue =
		!filter || filter === "all-pages"
			? options.values.find((value: IStructuredDataValue) => value.type === firstOptionsFilter)?.value
			: options.values.find((value: IStructuredDataValue) => value.type === filter.toLowerCase())?.value;
	return selectedValue || "";
};

const getCurrentFilter = (structuredData: any, filter: any) =>
	structuredData.filter((dataObj: any) => dataObj.id === filter)[0];

const filterByStatus = (bulkSelection: number[], currentSitePages: IPage[]): Record<string, number[]> => {
	const notPublishedItems: number[] = [];
	const publishedItems: number[] = [];
	const draftItems: number[] = [];

	currentSitePages.forEach((page: IPage) => {
		const { id, liveStatus, haveDraftPage } = page;
		if (bulkSelection.includes(id)) {
			switch (liveStatus.status) {
				case pageStatus.OFFLINE_PENDING:
				case pageStatus.OFFLINE:
				case pageStatus.UPLOAD_PENDING:
					haveDraftPage ? draftItems.push(id) : notPublishedItems.push(id);
					break;
				case pageStatus.PUBLISHED:
					haveDraftPage ? draftItems.push(id) : publishedItems.push(id);
					break;
			}
		}
	});

	const filteredItems = {
		all: bulkSelection,
		notPublished: notPublishedItems,
		published: publishedItems,
		drafts: draftItems,
	};

	return filteredItems;
};

const getSortedListStatus = (orderPointer: string, isAscending: boolean) => {
	const sortedListStatus = {
		isAscending,
		sortedByTitle: orderPointer === "title",
		sortedByURL: orderPointer === "slug",
		sortedByDate: ["modified", "date"].includes(orderPointer),
	};

	return sortedListStatus;
};

const getAllLangPagesIds = (
	currentSitePages: IPage[],
	selectedItems: IBulkSelectedItems,
	getAllVersions: boolean,
): number[] => {
	let langsPagesIds: number[] = [];
	if (getAllVersions) {
		const selectedPages = currentSitePages.filter((page: IPage) => selectedItems.all.includes(page.id));
		langsPagesIds = selectedPages.reduce((ids: number[], page: IPage) => {
			const langsPageIds = page.pageLanguages.map((lang: IPageLanguage) => lang.pageId);

			// biome-ignore lint/performance/noAccumulatingSpread: TODO: fix this
			return [...ids, ...langsPageIds];
		}, []);
	}

	return langsPagesIds.length ? langsPagesIds : selectedItems.all;
};

const getColumns = (
	categoryColumns: ISchemaField[],
	isStructuredDataFromPage: boolean,
	isAllPages: boolean,
	maxColumns: number,
): IColumn[] => {
	let defaultColumns: IColumn[] = [
		{ id: "live", title: "Live", show: true, default: true },
		{ id: "status", title: "Status", show: true, default: true },
		{ id: "translation", title: "Trans.", show: true, default: true },
	];

	if (isStructuredDataFromPage) {
		defaultColumns.push({ id: "seo", title: "SEO", show: true, default: true });
	}

	if (isStructuredDataFromPage) {
		defaultColumns = [{ id: "site", title: "Site", show: !isAllPages, default: !isAllPages }, ...defaultColumns];
	}

	if (isAllPages) {
		defaultColumns = [{ id: "type", title: "Types", show: true, default: true }, ...defaultColumns];
	}

	let availableColumns = maxColumns - defaultColumns.length;

	const extraColumns = categoryColumns.reduce((acc: IColumn[], cur: ISchemaField) => {
		acc.push({ id: cur.key, title: cur.title, show: availableColumns > 0, default: false });
		availableColumns = availableColumns - 1;
		return acc;
	}, []);

	const position = isStructuredDataFromPage ? 2 : 1;
	const columns = arrayInsert(defaultColumns, position, extraColumns);

	return columns;
};

export {
	filterByStatus,
	getAllLangPagesIds,
	getColumns,
	getCurrentFilter,
	getOptionFilters,
	getOptionValues,
	getSelectedValue,
	getSortedListStatus,
};
