import moment from "moment";
import classnames from "classnames";
import { useState, useMemo, useImperativeHandle } from "react";

import { ITemplateConfig, IRenderTasks } from "../interface";
import MyInput from "@/components/mui/MyInput";
import FileSelect, {
	FileSelectType,
} from "@/components/BusinessComponents/FileSelect";
import MySelect from "@/components/mui/MySelect";
import MyCheckBox from "@/components/mui/MyCheckBox";
import MyRadio from "@/components/mui/MyRadio";
import { getCheckResult } from "../util";
import fileSelectIcon from "@/assets/project/fileSelect.svg";
import tipsIcon from "@/assets/project/tipsIcon.svg";
import jobSueIcon from "@/assets/project/jobSue.svg";
import { IParameter } from "../interface";
import MyTooltip from "@/components/mui/MyTooltip";

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

type ConfigFormProps = {
	templateConfigInfo?: ITemplateConfig;
	setParameter: any;
	onRef?: React.Ref<any>;
	setExternalSelectedNodeId: (val: string) => void;
};

const ConfigForm = (props: ConfigFormProps) => {
	const { templateConfigInfo, setParameter, setExternalSelectedNodeId } = props;
	const [name, setName] = useState<string>(""); // 任务名称
	const [fileSelectType, setFileSelectType] = useState<FileSelectType>("path");

	const [nameHelp, setNameHelp] = useState({
		error: false,
		helperText: "",
	});
	const [outputPath, setOutputPath] = useState<string>("ProjectData"); // 输出路径
	const [outputPathHelp, setOutputPathHelp] = useState({
		error: false,
		helperText: "",
	});
	const getNameAndPath = () => {
		return {
			name,
			outputPath,
			nameAndOutputPathCheck: !(checkName(name) || checkOutputPath(outputPath)), // 任务名称、输出路径是否通过校验
		};
	};

	const setInitName = (name: string) => {
		setName(`${name}_${moment(new Date()).format("YYYY_MM_DD_HH_mm")}`);
	};
	useImperativeHandle(props.onRef, () => {
		return {
			getNameAndPath: getNameAndPath,
			setInitName: setInitName,
		};
	});

	const [fileSelectOpen, setFileSelectOpen] = useState(false); // 选择输出路径的弹窗显示控制

	const [fileSelectObject, setFileSelectObject] = useState({
		taskId: "",
		parameterName: "",
	});

	const onFileSelectConfirm = (path: string) => {
		setFileSelectOpen(false);
		if (fileSelectObject.taskId) {
			setParameter(
				`ProjectData${path === "/" ? "" : path}`,
				fileSelectObject.taskId,
				fileSelectObject.parameterName
			);
		} else {
			setOutputPath(`ProjectData${path === "/" ? "" : path}`);
			checkOutputPath(`ProjectData${path === "/" ? "" : path}`);
		}
	};

	const handleFileSelectOnClose = () => {
		setFileSelectOpen(false);
	};

	const handleOpenFileSelect = (
		taskId: string = "",
		parameterName: string = ""
	) => {
		setFileSelectObject({
			taskId,
			parameterName,
		});
		setFileSelectOpen(true);
	};

	const handleNameChange = (e: any) => {
		setName(e.target.value);
		checkName(e.target.value);
	};

	const checkName = (name: string = "") => {
		const reg = new RegExp(/^[a-zA-Z0-9\u4e00-\u9fa5-_]{3,50}$/);
		if (!name) {
			setNameHelp({
				error: true,
				helperText: "任务名称不能为空",
			});
			return true;
		} else if (reg.test(name)) {
			setNameHelp({
				error: false,
				helperText: "",
			});
			return false;
		} else {
			setNameHelp({
				error: true,
				helperText:
					"请输入正确任务名称（3~50字符，可包含大小写字母、数字、中文、特殊符号“-”、“_”）",
			});
			return true;
		}
	};

	const checkOutputPath = (outputPath: string = "") => {
		if (outputPath) {
			setOutputPathHelp({
				error: false,
				helperText: "",
			});
			return false;
		} else {
			setOutputPathHelp({
				error: true,
				helperText: "请选择输出路径",
			});
			return true;
		}
	};

	const renderTasks: IRenderTasks = useMemo(() => {
		const result: IRenderTasks = [];
		templateConfigInfo?.tasks.forEach((task, taskIndex) => {
			if (task.type === "BATCH") {
				result.push({ ...task, flows: [], isCheck: true });
			} else {
				result[result.length - 1]?.flows.push({ ...task });
			}
		});
		result.forEach((task) => {
			let isCheck = true;
			if (task.parameters.length > 0) {
				task.parameters
					.filter((parameter) => parameter.hidden === false)
					.forEach((parameter) => {
						const { error } = getCheckResult(parameter, parameter.value);
						if (error) {
							isCheck = false;
							return;
						}
					});
			}
			if (task.flows.length > 0) {
				task.flows.forEach((flow) => {
					if (flow.parameters.length > 0) {
						flow.parameters
							.filter((parameter) => parameter.hidden === false)
							.forEach((parameter) => {
								const { error } = getCheckResult(parameter, parameter.value);
								if (error) {
									isCheck = false;
									return;
								}
							});
					}
				});
			}
			task.isCheck = isCheck;
		});
		return result;
	}, [templateConfigInfo]);

	const handleParameterChange = (
		e: any,
		taskId: string,
		parameterName: string
	) => {
		setParameter(e.target.value, taskId, parameterName);
	};

	const randerParameters = (
		parameters: Array<IParameter>,
		taskId: string,
	) => {
		return parameters
			.filter((parameter) => parameter.hidden === false)
			.map((parameter, parameterIndex) => {
				return (
					<div
						className={styles.parameter}
						key={parameter.id || "" + parameterIndex}
					>
						<div
							className={classnames({
								[styles.parameterTitle]: true,
								[styles.required]: parameter.required,
							})}
						>
							{parameter.title}
							<span className={styles.parameterDataType}>
								{parameter.classTypeName}
							</span>
						</div>
						<MyTooltip
							title={parameter.description || parameter.name}
							placement="right"
						>
							<div className={styles.parameterContent}>
								{(parameter.domType || "").toLowerCase() === "file" && (
									<MyInput
										onClick={() => {
											setExternalSelectedNodeId(taskId || "");
											setFileSelectType("file");
											handleOpenFileSelect(taskId, parameter.name);
										}}
										value={parameter.value || ""}
										InputProps={{
											endAdornment: (
												<img
													src={fileSelectIcon}
													alt=""
													className={styles.fileSelectImg}
												/>
											),
										}}
										placeholder="请选择"
										error={parameter.error || false}
										helperText={parameter.helperText}
										size="medium"
									></MyInput>
								)}
								{(parameter.domType || "").toLowerCase() === "path" && (
									<MyInput
										onClick={() => {
											setExternalSelectedNodeId(taskId || "");
											setFileSelectType("path");
											handleOpenFileSelect(taskId, parameter.name);
										}}
										value={parameter.value || ""}
										InputProps={{
											endAdornment: (
												<img
													src={fileSelectIcon}
													alt=""
													className={styles.fileSelectImg}
												/>
											),
										}}
										placeholder="请选择"
										error={parameter.error || false}
										helperText={parameter.helperText}
										size="medium"
									></MyInput>
								)}
								{(parameter.domType || "").toLowerCase() === "dataset" && (
									<MyInput
										onClick={() => {
											setExternalSelectedNodeId(taskId);
											setFileSelectType("dataset");
											handleOpenFileSelect(taskId, parameter.name);
										}}
										value={parameter.value || ""}
										InputProps={{
											endAdornment: (
												<img
													src={fileSelectIcon}
													alt=""
													className={styles.fileSelectImg}
												/>
											),
										}}
										placeholder="请选择"
										error={parameter.error || false}
										helperText={parameter.helperText}
										size="medium"
									></MyInput>
								)}
								{(parameter.domType || "").toLowerCase() === "input" && (
									<MyInput
										onFocus={() => {
											setExternalSelectedNodeId(taskId || "");
										}}
										onBlur={() => setExternalSelectedNodeId("")}
										value={parameter.value || ""}
										onChange={(e: any) =>
											handleParameterChange(e, taskId, parameter.name || "")
										}
										placeholder="请输入"
										error={parameter.error || false}
										helperText={parameter.helperText}
										size="medium"
									></MyInput>
								)}
								{(parameter.domType || "").toLowerCase() === "select" && (
									<MySelect
										onFocus={() => setExternalSelectedNodeId(taskId || "")}
										onBlur={() => setExternalSelectedNodeId("")}
										value={parameter.value}
										onChange={(e: any) =>
											handleParameterChange(
												{
													target: {
														value: e,
													},
												},
												taskId,
												parameter.name || ""
											)
										}
										error={parameter.error || false}
										helpertext={parameter.helperText}
										options={parameter?.choices || []}
										fullWidth
									></MySelect>
								)}
								{(parameter.domType || "").toLowerCase() ===
									"multipleselect" && (
									<MySelect
										onFocus={() => setExternalSelectedNodeId(taskId || "")}
										onBlur={() => setExternalSelectedNodeId("")}
										value={parameter.value}
										onChange={(e: any) =>
											handleParameterChange(
												{
													target: {
														value: e,
													},
												},
												taskId,
												parameter.name || ""
											)
										}
										multiple={true}
										error={parameter.error || false}
										helpertext={parameter.helperText}
										options={parameter?.choices || []}
										fullWidth
									></MySelect>
								)}
								{(parameter.domType || "").toLowerCase() === "radio" && (
									<MyRadio
										value={parameter.value}
										onChange={(e: any) =>
											handleParameterChange(e, taskId, parameter.name || "")
										}
										onFocus={() => setExternalSelectedNodeId(taskId || "")}
										onBlur={() => setExternalSelectedNodeId("")}
										options={parameter?.choices || []}
										error={parameter.error || false}
										helperText={parameter.helperText}
									></MyRadio>
								)}
								{(parameter.domType || "").toLowerCase() === "checkbox" && (
									<MyCheckBox
										value={parameter.value}
										onChange={(e: any) =>
											handleParameterChange(
												{
													target: {
														value: e,
													},
												},
												taskId,
												parameter.name || ""
											)
										}
										options={parameter?.choices || []}
										onFocus={() => setExternalSelectedNodeId(taskId || "")}
										onBlur={() => setExternalSelectedNodeId("")}
										error={parameter.error || false}
										helperText={parameter.helperText}
									/>
								)}
							</div>
						</MyTooltip>
					</div>
				);
			});
	};

	return (
		<div className={styles.formBox}>
			<div className={styles.templateDescBox}>
				<div className={styles.templateDescTitle}>模板描述</div>
				<div className={styles.templateDesc}>
					{templateConfigInfo?.description || ""}
				</div>
			</div>
			<div className={styles.formItemBox}>
				<div
					className={classnames({
						[styles.backgroundTitle]: true,
					})}
				>
					<span className={styles.backgroundTitleText}>基础信息</span>
					<img
						className={classnames({
							[styles.backgroundTitleTextIcon]: true,
							[styles.backgroundTitleTextIconShow]: !nameHelp.error,
						})}
						src={jobSueIcon}
						alt=""
					/>
				</div>
				<div className={styles.formItems}>
					<div className={styles.formItem}>
						<div
							className={classnames({
								[styles.formItemLable]: true,
								[styles.required]: true,
							})}
						>
							任务名称
						</div>
						<div className={styles.formItem}>
							<MyInput
								value={name}
								onChange={handleNameChange}
								placeholder="请输入任务名称"
								error={nameHelp.error}
								helperText={nameHelp.helperText}
							></MyInput>
						</div>
					</div>
					<div className={styles.formItem}>
						<div
							className={classnames({
								[styles.formItemLable]: true,
								[styles.required]: true,
							})}
						>
							输出路径
						</div>
						<div className={styles.formItem}>
							<MyInput
								value={outputPath || ""}
								onClick={() => {
									setExternalSelectedNodeId("");
									setFileSelectType("path");
									handleOpenFileSelect();
								}}
								InputProps={{
									endAdornment: (
										<img
											src={fileSelectIcon}
											alt="选择输出路径"
											className={styles.fileSelectImg}
										/>
									),
								}}
								error={outputPathHelp.error}
								helperText={outputPathHelp.helperText}
							></MyInput>
						</div>
					</div>
				</div>
			</div>
			{renderTasks.map((task, taskIndex) => {
				return (
					<div className={styles.formItemBox} key={task.id + taskIndex}>
						<div
							className={classnames({
								[styles.backgroundTitle]: true,
							})}
						>
							<span
								id={`point${task.id}`}
								className={styles.backgroundTitleText}
							>
								{task.title}
							</span>
							{task.description && (
								<MyTooltip title={task.description} placement="top">
									<img className={styles.taskDescIcon} src={tipsIcon} alt="" />
								</MyTooltip>
							)}
							<img
								className={classnames({
									[styles.backgroundTitleTextIcon]: true,
									[styles.backgroundTitleTextIconShow]: task.isCheck,
								})}
								src={jobSueIcon}
								alt=""
							/>
						</div>
						<div className={styles.taskConfigBox}>
							{randerParameters(
								task.parameters.filter((parameter) => !parameter?.thrown),
								task.id,
							)}
							{task.flows.map((flow) => {
								if (
									flow.parameters.filter(
										(parameter) => parameter.hidden === false
									).length === 0
								) {
									return null;
								}
								return (
									<div className={styles.flowConfigBox} key={flow.id} id={`point${flow.id}`}>
										<div className={styles.flowTitle}>
											{flow.title}
											{flow.description && (
												<MyTooltip title={flow.description} placement="top">
													<img
														className={styles.flowDescIcon}
														src={tipsIcon}
														alt=""
													/>
												</MyTooltip>
											)}
										</div>
										{randerParameters(
											flow.parameters,
											flow.id,
										)}
									</div>
								);
							})}
						</div>
					</div>
				);
			})}
			{fileSelectOpen && (
				<FileSelect
					onClose={handleFileSelectOnClose}
					open={fileSelectOpen}
					onConfirm={onFileSelectConfirm}
					type={fileSelectType}
				/>
			)}
		</div>
	);
};

export default ConfigForm;
