import {
	createContext,
	useState,
	useCallback,
	useContext,
	type Dispatch,
	type SetStateAction,
	type ReactElement,
} from "react";
import { moveElement } from "@ax/forms";
import { moveArrayElement } from "@ax/helpers";
import type { IDataSource, IStructuredDataContent } from "@ax/types";

const initState: IReferenceState = {
	mode: "auto",
	order: "recent",
	orderDirection: "ASC",
	quantity: 0,
	items: [],
	selectedItems: [],
	fixed: [],
	search: "",
	showSelected: false,
	sources: [],
	sourceTitles: [],
	fullRelations: false,
	allLanguages: false,
	preferenceLanguage: false,
};

const ReferenceContext = createContext<IReferenceContext>({} as IReferenceContext);

const ReferenceProvider = ({ modes, children }: { modes?: ReferenceMode[]; children: ReactElement }): JSX.Element => {
	const reference = useReferenceProvider(modes);

	return <ReferenceContext.Provider value={reference}>{children}</ReferenceContext.Provider>;
};

const useReference = (): IReferenceContext => {
	return useContext(ReferenceContext);
};

const useReferenceProvider = (modes?: ReferenceMode[]) => {
	const mode: ReferenceMode = modes?.length ? modes[0] : "auto";
	const [state, setState] = useState<IReferenceState>({ ...initState, mode });

	const setModeAndSource = useCallback((mode: ReferenceMode, sources: ISource[]) => {
		setState((prev) => ({ ...prev, mode, sources }));
	}, []);

	const setReorderElements = useCallback((item: IStructuredDataContent, newIndex: number): number[] => {
		let newFixed: number[] = [];
		setState((prev) => {
			const { selectedItems, fixed, fullRelations = false } = prev;
			const newItems = moveElement([item.id], selectedItems, newIndex, "id");
			const originalItemId = item.relatedPage?.originalStructuredDataId;
			const itemId = originalItemId && prev.fixed.includes(originalItemId) ? originalItemId : item.id;
			newFixed = moveArrayElement(itemId, fixed, newIndex);
			return {
				...prev,
				selectedItems: newItems,
				fixed: newFixed,
				fullRelations,
			};
		});
		return newFixed;
	}, []);

	return {
		state,
		setState,
		setModeAndSource,
		setReorderElements,
	};
};

type ReferenceMode = "auto" | "manual";
type OrderDirection = "ASC" | "DESC";
type SiteValue = number | "global";

interface IReferenceContext {
	state: IReferenceState;
	setState: Dispatch<SetStateAction<IReferenceState>>;
	setModeAndSource: (mode: ReferenceMode, sources: ISource[]) => void;
	setReorderElements: (item: IStructuredDataContent, newIndex: number) => number[];
}

export interface ISource {
	structuredData: string;
	filters?: IFilter[];
	globalOperator?: string;
	filterOperator?: string;
}

export interface IReferenceState {
	mode: ReferenceMode;
	order: string;
	orderDirection: OrderDirection;
	quantity: number;
	items: IStructuredDataContent[];
	selectedItems: IStructuredDataContent[];
	fixed: number[];
	search: string;
	showSelected: boolean;
	sources: ISource[];
	sourceTitles: IDataSource[];
	fullRelations: boolean;
	allLanguages: boolean;
	preferenceLanguage: boolean;
	lang?: number;
	site?: SiteValue | null;
	fields?: string[];
}

export interface IRefField {
	mode?: ReferenceMode;
	order?: string;
	fixed?: number[];
	sources?: ISource[];
	quantity?: number;
	fullRelations?: boolean;
	allLanguages?: boolean;
	preferenceLanguage?: boolean;
	lang?: number;
	site?: SiteValue | null;
	fields?: string[];
}

export interface IFilter {
	id: number;
	label: string;
	color?: string;
	category?: string;
}

export { type ReferenceMode, type OrderDirection, type SiteValue, ReferenceProvider, useReference };
