import _ from "lodash";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import classNames from "classnames";

import {
	ITask,
	IParameter,
} from "../../../Project/ProjectSubmitWork/interface";
import noTemplate from "@/assets/project/noTemplate.svg";
import MyInput from "@/components/mui/MyInput";
import MyCheckBox from "@/components/mui/MyCheckBox";
import MySelect from "@/components/mui/MySelect";
import FileSelect, {
	FileSelectType,
} from "@/components/BusinessComponents/FileSelect";
import MyRadio from "@/components/mui/MyRadio";
import questionMark from "@/assets/project/questionMark.svg";
import fileSelectIcon from "@/assets/project/fileSelect.svg";
import MySwitch from "@/components/mui/MySwitch";
import Tabs from "@/components/mui/Tabs";
import { getCustomTemplateParameterCheckResult } from "../../util";
import MyTooltip from "@/components/mui/MyTooltip";
import { useSize } from "ahooks";

import styles from "./index.module.css";

type IParameterSettingProps = {
	templateConfigInfo: ITask[];
	taskId: string;
	setTemplateConfigInfo: any;
};
const ParameterSetting = (props: IParameterSettingProps) => {
	const { templateConfigInfo, setTemplateConfigInfo, taskId } = props; // 算子大数组
	const [isShowAllDese, setIsShowAllDese] = useState(false); // 是否展示全部描述
	const [fileSelectOpen, setFileSelectOpen] = useState(false); // 选择输出路径的弹窗显示控制
	const [fileSelectType, setFileSelectType] = useState<FileSelectType>("path");
	const [parameterName, setParameterName] = useState(""); // 当前算子中的parameters中正在编辑饿parameter（参数）
	const resizeRef = useRef<HTMLDivElement>(null);
	const [activeParamsTab, setActiveParamsTab] = useState<string>("");

	const size = useSize(resizeRef);

	// 文件夹路线选择器弹窗
	const handleFileSelectOnClose = () => {
		setFileSelectOpen(false);
	};

	// 选中的算子详情
	const taskInfo: ITask | null = useMemo(() => {
		if (!taskId) {
			return null;
		} else {
			const randerTaskArr = templateConfigInfo.filter(
				(task) => task.id === taskId
			);
			if (randerTaskArr.length > 0) {
				return randerTaskArr[0] as ITask;
			} else {
				return null;
			}
		}
	}, [templateConfigInfo, taskId]);

	/** 通过parameter.name删除与之相关联的线 */
	const handleHiddenDeleteEdge = useCallback(
		(val: ITask[], parameterName: string) => {
			let taskParentNode = "";
			val.forEach((task) => {
				if (task.id === taskId) {
					taskParentNode = task.parentNode || "";
				}
			});
			return (
				val?.length &&
				val?.map((item) => {
					if (item.id === taskId) {
						const newParameters =
							(item.parameters?.length &&
								item.parameters.map((every) => {
									if (every.name === parameterName) {
										return {
											...every,
											linked: false,
										};
									} else {
										return every;
									}
								})) ||
							[];
						return {
							...item,
							parameters: newParameters,
						};
					} else {
						const newEdges =
							(item?.edges?.length &&
								item?.edges?.filter((every) => {
									// 因为存在同名的parameterName  所以增加every.source === taskParentNode判断
									return (
										every.targetHandle !== parameterName ||
										every.source === taskParentNode
									);
								})) ||
							[];
						return {
							...item,
							edges: newEdges,
						};
					}
				})
			);
		},
		[taskId]
	);

	// 设置parameter.hidden字段
	const handleHiddenChange = useCallback(
		(e: any, parameterName: string) => {
			let result: ITask[] = _.cloneDeep(templateConfigInfo);
			const taskIndex = result.findIndex((item) => {
				return item.id === taskId;
			});
			if (taskIndex !== -1) {
				let isCheck = true;
				result[taskIndex].parameters.forEach((parameter) => {
					if (parameter.name === parameterName) {
						parameter.hidden = !e.target.checked;
						const checkResult =
							getCustomTemplateParameterCheckResult(parameter);
						parameter.error = checkResult.error;
						parameter.helperText = checkResult.helperText;
					}
					if (getCustomTemplateParameterCheckResult(parameter).error === true) {
						isCheck = false;
					}
				});
				result[taskIndex].isCheck = isCheck;
			}
			if (e.target.checked) {
				result = handleHiddenDeleteEdge(result, parameterName) || [];
			}
			setTemplateConfigInfo(result);
		},
		[templateConfigInfo, handleHiddenDeleteEdge, setTemplateConfigInfo, taskId]
	);

	// 设置parameter.defaultValue字段
	const handleParameterChange = useCallback(
		(e: any, parameterName: string) => {
			const result: ITask[] = _.cloneDeep(templateConfigInfo);
			const taskIndex = result.findIndex((item) => {
				return item.id === taskId;
			});
			if (taskIndex !== -1) {
				let isCheck = true;
				result[taskIndex].parameters.forEach((parameter) => {
					if (parameter.name === parameterName) {
						parameter.defaultValue = e.target.value;
						const checkResult =
							getCustomTemplateParameterCheckResult(parameter);
						parameter.error = checkResult.error;
						parameter.helperText = checkResult.helperText;
					}
					if (getCustomTemplateParameterCheckResult(parameter).error === true) {
						isCheck = false;
					}
				});
				result[taskIndex].isCheck = isCheck;
			}
			setTemplateConfigInfo(result);
		},
		[templateConfigInfo, setTemplateConfigInfo, taskId]
	);

	// 文件夹路线选择确认回调
	const onFileSelectConfirm = (path: string) => {
		setFileSelectOpen(false);
		handleParameterChange(
			{
				target: {
					value: `ProjectData${path === "/" ? "" : path}`,
				},
			},
			parameterName
		);
	};

	// 渲染当个表单项
	const renderInput = useCallback(
		(parameter: IParameter) => {
			return (
				<MyTooltip
					title={parameter.description || parameter.name}
					placement="right"
				>
					<div>
						{(parameter.domType || "").toLowerCase() === "file" && (
							<MyInput
								value={parameter.defaultValue || ""}
								onClick={() => {
									if (parameter.parameterGroup === "out") {
										return;
									}
									setFileSelectType("file");
									handleOpenFileSelect(parameter.name);
								}}
								InputProps={{
									endAdornment: (
										<img
											src={fileSelectIcon}
											alt=""
											className={styles.fileSelectImg}
										/>
									),
								}}
								placeholder="请选择"
								error={parameter.error || false}
								helperText={parameter.helperText}
								disabled={parameter.parameterGroup === "out"}
							></MyInput>
						)}
						{(parameter.domType || "").toLowerCase() === "path" && (
							<MyInput
								value={parameter.defaultValue || ""}
								onClick={() => {
									if (parameter.parameterGroup === "out") {
										return;
									}
									setFileSelectType("path");
									handleOpenFileSelect(parameter.name);
								}}
								InputProps={{
									endAdornment: (
										<img
											src={fileSelectIcon}
											alt=""
											className={styles.fileSelectImg}
										/>
									),
								}}
								placeholder="请选择"
								error={parameter.error || false}
								helperText={parameter.helperText}
								disabled={parameter.parameterGroup === "out"}
							></MyInput>
						)}
						{(parameter.domType || "").toLowerCase() === "dataset" && (
							<MyInput
								value={parameter.defaultValue || ""}
								onClick={() => {
									if (parameter.parameterGroup === "out") {
										return;
									}
									setFileSelectType("dataset");
									handleOpenFileSelect(parameter.name);
								}}
								InputProps={{
									endAdornment: (
										<img
											src={fileSelectIcon}
											alt=""
											className={styles.fileSelectImg}
										/>
									),
								}}
								placeholder="请选择"
								error={parameter.error || false}
								helperText={parameter.helperText}
								disabled={parameter.parameterGroup === "out"}
							></MyInput>
						)}
						{(parameter.domType || "").toLowerCase() === "input" && (
							<MyInput
								value={parameter.defaultValue || ""}
								onChange={(e: any) =>
									handleParameterChange(e, parameter.name || "")
								}
								placeholder="可输入默认值"
								error={parameter.error || false}
								helperText={parameter.helperText}
								disabled={parameter.parameterGroup === "out"}
							></MyInput>
						)}
						{(parameter.domType || "").toLowerCase() === "select" && (
							<MySelect
								value={parameter.defaultValue}
								onChange={(e: any) =>
									handleParameterChange(
										{
											target: {
												value: e,
											},
										},
										parameter.name || ""
									)
								}
								error={parameter.error || false}
								helpertext={parameter.helperText}
								options={parameter?.choices || []}
								disabled={parameter.parameterGroup === "out"}
							></MySelect>
						)}
						{(parameter.domType || "").toLowerCase() === "multipleselect" && (
							<MySelect
								value={parameter.defaultValue}
								onChange={(e: any) =>
									handleParameterChange(
										{
											target: {
												value: e,
											},
										},
										parameter.name || ""
									)
								}
								multiple={true}
								error={parameter.error || false}
								helpertext={parameter.helperText}
								options={parameter?.choices || []}
								disabled={parameter.parameterGroup === "out"}
							></MySelect>
						)}
						{(parameter.domType || "").toLowerCase() === "radio" && (
							<MyRadio
								value={parameter.defaultValue}
								onChange={(e: any) =>
									handleParameterChange(e, parameter.name || "")
								}
								options={parameter?.choices || []}
								error={parameter.error || false}
								helperText={parameter.helperText}
							></MyRadio>
						)}
						{(parameter.domType || "").toLowerCase() === "checkbox" && (
							<MyCheckBox
								value={parameter.defaultValue}
								onChange={(e: any) =>
									handleParameterChange(
										{
											target: {
												value: e,
											},
										},
										parameter.name || ""
									)
								}
								options={parameter?.choices || []}
								error={parameter.error || false}
								helperText={parameter.helperText}
							></MyCheckBox>
						)}
					</div>
				</MyTooltip>
			);
		},
		[handleParameterChange]
	);

	// 输入参数
	const inParameters: Array<IParameter> = useMemo(() => {
		if (!taskInfo) {
			return [];
		} else {
			if (taskInfo.type === "BATCH") {
				return taskInfo.parameters.filter(
					(parameter) => parameter.parameterGroup === "in" && !parameter.thrown
				);
			} else {
				return taskInfo.parameters.filter(
					(parameter) => parameter.parameterGroup === "in"
				);
			}
		}
	}, [taskInfo]);

	// 输出参数
	const outParameters: Array<IParameter> = useMemo(() => {
		if (!taskInfo) {
			return [];
		} else {
			if (taskInfo.type === "BATCH") {
				return taskInfo.parameters.filter(
					(parameter) => parameter.parameterGroup === "out" && !parameter.thrown
				);
			} else {
				return taskInfo.parameters.filter(
					(parameter) => parameter.parameterGroup === "out"
				);
			}
		}
	}, [taskInfo]);

	// 基础参数
	const basisParameters: Array<IParameter> = useMemo(() => {
		if (!taskInfo) {
			return [];
		} else {
			return taskInfo.parameters.filter(
				(parameter) => parameter.parameterGroup === "basis"
			);
		}
	}, [taskInfo]);

	// 高级选项
	const seniorParameters: Array<IParameter> = useMemo(() => {
		if (!taskInfo) {
			return [];
		} else {
			return taskInfo.parameters.filter(
				(parameter) => parameter.parameterGroup === "senior"
			);
		}
	}, [taskInfo]);

	// 硬件配置
	const hardwareParameters: Array<IParameter> = useMemo(() => {
		if (!taskInfo) {
			return [];
		} else {
			return taskInfo.parameters.filter(
				(parameter) => parameter.parameterGroup === "hardware"
			);
		}
	}, [taskInfo]);

	// 某种类型的参数组渲染
	const randerParameters = useCallback(
		(parameters: Array<IParameter>) => {
			return (
				<div className={styles.parameters}>
					{parameters.map((parameter, parameterIndex) => {
						return (
							<div
								className={styles.parameter}
								key={`${parameter.name}${parameterIndex}`}
							>
								<div className={styles.parameterTop}>
									<div className={styles.parameterLeft}>
										<div
											className={classNames({
												[styles.parameterName]: true,
												[styles.required]: parameter.required,
											})}
										>
											{parameter.title}
										</div>
										<div className={styles.parameterClassTypeName}>
											{parameter.classTypeName}
										</div>
									</div>
									<MySwitch
										value={!parameter.hidden}
										onChange={(e: any) =>
											handleHiddenChange(e, parameter.name || "")
										}
									></MySwitch>
								</div>
								<div className={styles.parameterContent}>
									{renderInput(parameter)}
								</div>
							</div>
						);
					})}
				</div>
			);
		},
		[renderInput, handleHiddenChange]
	);

	// 显示文件夹路径选择弹窗
	const handleOpenFileSelect = (parameterName: string = "") => {
		setParameterName(parameterName);
		setFileSelectOpen(true);
	};

	// 参数组tabs
	const paramsTabList = useMemo(() => {
		return [
			{
				label: "基础参数",
				value: "basis",
				component: randerParameters(basisParameters),
				disabled: basisParameters.length === 0,
			},
			{
				label: "高级选项",
				value: "senior",
				component: randerParameters(seniorParameters),
				disabled: seniorParameters.length === 0,
			},
			{
				label: "硬件配置",
				value: "hardware",
				component: randerParameters(hardwareParameters),
				disabled: hardwareParameters.length === 0,
			},
		];
	}, [basisParameters, seniorParameters, hardwareParameters, randerParameters]);

	// 激活的参数组tab
	useEffect(() => {
		if (basisParameters.length !== 0) {
			setActiveParamsTab("basis");
		} else if (seniorParameters.length !== 0) {
			setActiveParamsTab("senior");
		} else if (hardwareParameters.length !== 0) {
			setActiveParamsTab("hardware");
		}
	}, [basisParameters, seniorParameters, hardwareParameters]);

	return (
		<div className={styles.parameterSetting}>
			{taskInfo && (
				<div className={styles.taskInfo}>
					<div className={styles.taskTitle}>{taskInfo.title || "-"}</div>
					<div className={styles.taskVersion}>
						版本：{taskInfo.version || "-"}
					</div>
					<div className={styles.taskDescriptionHeight} id="descHeight">
						{taskInfo.description || "-"}
					</div>
					<div
						ref={resizeRef}
						className={classNames({
							[styles.taskDescriptionAll]: isShowAllDese,
							[styles.taskDescription]: !isShowAllDese,
						})}
					>
						{taskInfo.description || "-"}
						{size && size?.height >= 60 && (
							<span
								className={styles.descButton}
								onClick={() => setIsShowAllDese(!isShowAllDese)}
							>
								{isShowAllDese ? "收起" : "展开"}
							</span>
						)}
					</div>
				</div>
			)}
			{inParameters.length > 0 && (
				<div className={styles.inOutBox}>
					<div className={styles.paramsTitle}>
						输入
						<MyTooltip
							title="当某个输入项为启用状态时，代表该输入将由模板使用者在使用的时候填写赋值；当为关闭状态时，代表该输入不需要使用者来填写赋值，而是将其它流程的结果传入。"
							placement="right"
						>
							<img
								className={styles.paramsTitleDesc}
								src={questionMark}
								alt=""
							/>
						</MyTooltip>
					</div>
					<div className={styles.paramsList}>
						{inParameters.map((parameter, index) => {
							return (
								<div
									className={styles.inOutParameterBox}
									key={`${parameter.name}${index}`}
								>
									<div className={styles.inOutParameterTop}>
										<div className={styles.inOutParameterleft}>
											<div
												className={classNames({
													[styles.inOutParameterName]: true,
													[styles.required]: parameter.required,
												})}
											>
												{parameter.title}
											</div>
											<div className={styles.inOutParameterdataType}>
												{parameter.classTypeName}
											</div>
										</div>
										<div className={styles.inOutParameterRight}>
											<MySwitch
												value={!parameter.hidden}
												onChange={(e: any) =>
													handleHiddenChange(e, parameter.name || "")
												}
												disabled={true}
											></MySwitch>
										</div>
									</div>
									{parameter.error && parameter.helperText && (
										<div className={styles.inOutParameterHelperText}>
											{parameter.helperText}
										</div>
									)}
									{/* {renderInput(parameter)} */}
								</div>
							);
						})}
					</div>
				</div>
			)}
			{outParameters.length > 0 && (
				<div className={styles.inOutBox}>
					<div className={styles.paramsTitle}>输出</div>
					<div className={styles.paramsList}>
						{outParameters.map((parameter, index) => {
							return (
								<div
									className={styles.inOutParameterBox}
									key={`${parameter.name}${index}`}
								>
									<div className={styles.inOutParameterTop}>
										<div className={styles.inOutParameterleft}>
											<div
												className={classNames({
													[styles.inOutParameterName]: true,
													[styles.required]: parameter.required,
												})}
											>
												{parameter.title}
											</div>
											<div className={styles.inOutParameterdataType}>
												{parameter.classTypeName}
											</div>
										</div>
										<div className={styles.inOutParameterRight}></div>
									</div>
									{renderInput(parameter)}
								</div>
							);
						})}
					</div>
				</div>
			)}
			{taskInfo && (
				<div className={styles.paramsGroup}>
					<div className={styles.paramsTitle}>
						参数组
						<MyTooltip
							title="当某个参数项为启用状态时，代表该参数将由模板使用者在使用的时候填写赋值；当为关闭状态时，代表该参数不需要使用者来填写赋值。"
							placement="right"
						>
							<img
								className={styles.paramsTitleDesc}
								src={questionMark}
								alt=""
							/>
						</MyTooltip>
					</div>
					<Tabs
						tabList={paramsTabList}
						value={activeParamsTab}
						onChange={(val) => setActiveParamsTab(val)}
						allowNullValue={true}
						tabPanelSx={{ padding: "7px 0" }}
					/>
					{basisParameters.length === 0 &&
						seniorParameters.length === 0 &&
						hardwareParameters.length === 0 && (
							<div className={styles.noParameters}>暂无可设置参数</div>
						)}
				</div>
			)}
			{!taskInfo && (
				<div className={styles.noData}>
					<img src={noTemplate} alt="" className={styles.noDataImg} />
					<span className={styles.noDataText}>选中任意算子进行参数设置</span>
				</div>
			)}
			{fileSelectOpen && (
				<FileSelect
					onClose={handleFileSelectOnClose}
					open={fileSelectOpen}
					onConfirm={onFileSelectConfirm}
					type={fileSelectType}
				/>
			)}
		</div>
	);
};

export default ParameterSetting;
