import React, { useEffect, useState, useCallback } from "react";
import { Tree } from "antd";
import type { DataNode, TreeProps } from "antd/es/tree";
import { getUniqueItems } from "@nice/common";
import { api } from "@nice/client";

interface TermData {
	value?: string;
	children?: TermData[];
	key?: string;
	hasChildren?: boolean;
	isLeaf?: boolean;
	pId?: string;
	title?: React.ReactNode;
	data?: any;
	order?: string;
	id?: string;
}

interface TermTreeProps {
	defaultValue?: string | string[];
	value?: string | string[];
	onChange?: (value: string | string[]) => void;
	multiple?: boolean;
	taxonomyId?: string;
	disabled?: boolean;
	className?: string;
	domainId?: string;
	style?: React.CSSProperties;
}

const TermTree: React.FC<TermTreeProps> = ({
	defaultValue,
	value,
	onChange,
	className,
	multiple = false,
	taxonomyId,
	domainId,
	disabled = false,
	style,
}) => {
	const utils = api.useUtils();
	const [treeData, setTreeData] = useState<TermData[]>([]);

	const processTermData = (terms: TermData[]): TermData[] => {
		return terms.map((term) => ({
			...term,
			key: term.key || term.id || "",
			title: term.title || term.value,
			children: term.children
				? processTermData(term.children)
				: undefined,
		}));
	};

	const fetchParentTerms = useCallback(
		async (termIds: string | string[], taxonomyId?: string) => {
			const idsArray = Array.isArray(termIds)
				? termIds
				: [termIds].filter(Boolean);
			try {
				const result = await utils.term.getParentSimpleTree.fetch({
					termIds: idsArray,
					taxonomyId,
					domainId,
				});
				return processTermData(result);
			} catch (error) {
				console.error(
					"Error fetching parent terms for termIds",
					idsArray,
					":",
					error
				);
				throw error;
			}
		},
		[utils, domainId]
	);

	const fetchTerms = useCallback(async () => {
		try {
			const rootTerms = await utils.term.getChildSimpleTree.fetch({
				taxonomyId,
				domainId,
			});
			let combinedTerms = processTermData(rootTerms);
			if (defaultValue) {
				const defaultTerms = await fetchParentTerms(
					defaultValue,
					taxonomyId
				);
				combinedTerms = getUniqueItems(
					[...treeData, ...combinedTerms, ...defaultTerms],
					"key"
				);
			}
			if (value) {
				const valueTerms = await fetchParentTerms(value, taxonomyId);
				combinedTerms = getUniqueItems(
					[...treeData, ...combinedTerms, ...valueTerms],
					"key"
				);
			}

			setTreeData(combinedTerms);
		} catch (error) {
			console.error("Error fetching terms:", error);
		}
	}, [
		defaultValue,
		value,
		taxonomyId,
		utils,
		fetchParentTerms,
		domainId,
		treeData,
	]);

	useEffect(() => {
		fetchTerms();
	}, [fetchTerms]);

	const onLoadData = async ({ key }: any) => {
		try {
			const result = await utils.term.getChildSimpleTree.fetch({
				termIds: [key],
				taxonomyId,
				domainId,
			});
			const processedResult = processTermData(result);
			const newItems = getUniqueItems(
				[...treeData, ...processedResult],
				"key"
			);
			setTreeData(newItems);
		} catch (error) {
			console.error(
				"Error loading data for node with key",
				key,
				":",
				error
			);
		}
	};

	const handleCheck: TreeProps["onCheck"] = (checkedKeys, info) => {
		if (onChange) {
			if (multiple) {
				onChange(checkedKeys as string[]);
			} else {
				onChange((checkedKeys as string[])[0] || "");
			}
		}
	};

	const handleExpand = async (expandedKeys: React.Key[]) => {
		try {
			const allKeyIds = expandedKeys
				.map((key) => key.toString())
				.filter(Boolean);
			const expandedNodes = await utils.term.getChildSimpleTree.fetch({
				termIds: allKeyIds,
				taxonomyId,
				domainId,
			});
			const processedNodes = processTermData(expandedNodes);
			const newItems = getUniqueItems(
				[...treeData, ...processedNodes],
				"key"
			);
			setTreeData(newItems);
		} catch (error) {
			console.error(
				"Error expanding nodes with keys",
				expandedKeys,
				":",
				error
			);
		}
	};

	return (
		<Tree
			checkable={multiple}
			disabled={disabled}
			className={className}
			style={style}
			treeData={treeData as DataNode[]}
			checkedKeys={Array.isArray(value) ? value : value ? [value] : []}
			onCheck={handleCheck}
			loadData={onLoadData}
			onExpand={handleExpand}
		/>
	);
};

export default TermTree;
