/*
 * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
 * @Date: 2022-06-21 20:03:56
 * @LastEditors: 吴永生 15770852798@163.com
 * @LastEditTime: 2022-09-06 10:54:40
 * @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { useEffect, useState, useMemo, useCallback } from "react";
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import classNames from "classnames";
import { useLocation, useNavigate } from "react-router-dom";

import MyButton from "@/components/mui/MyButton";
import TaskInfo from "./TaskInfo";
import useMyRequest from "@/hooks/useMyRequest";
import {
	fetchWorkFlowJob,
	getworkFlowTaskInfo,
	fetchFlowOutputNumber,
} from "@/api/project_api";
import { IResponse } from "@/api/http";
import jobSue from "@/assets/project/jobSue.svg";
import jobRun from "@/assets/project/jobRun.svg";
import fullScreen from "@/assets/project/fullScreen.svg";
import partialScreen from "@/assets/project/partialScreen.svg";
import goback from "@/assets/project/goback.svg";
import CloudEController from "@/api/fileserver/CloudEController";
import jobFail from "@/assets/project/jobFail.svg";
import { useStores } from "@/store";
import { ITaskInfo } from "../ProjectSubmitWork/interface";
import Flow from "../components/Flow";
import { cancelWorkflowJob, deleteWorkflowJob } from "@/api/workbench_api";
import { useMessage } from "@/components/MySnackbar";
import MyPopconfirm from "@/components/mui/MyPopconfirm";
import SeeDataset from "../ProjectData/SeeDataset";
import { getToken, storageUnitFromB } from "@/utils/util";
import LogView from "./LogView";
import usePass from "@/hooks/usePass";
import { IFlowNodeTransmissionNum } from "./interface";
import {
	getConnectionArr,
	getDatasetName,
	getDatasetPath,
	getSameBatch,
} from "./utils";
import MyTooltip from "@/components/mui/MyTooltip";

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

const statusMap = {
	Done: "运行完成",
	Running: "正在运行",
	Failed: "运行失败",
	Pending: "等待运行",
};

type IStatus = "Done" | "Running" | "Failed" | "Pending";
let randerOutputs: Array<any> = [];

const ProjectSubmitWork = observer(() => {
	const { currentProjectStore } = useStores();
	const fileToken = toJS(currentProjectStore.currentProjectInfo.filetoken);
	const projectId = toJS(currentProjectStore.currentProjectInfo.id);
	const productId = toJS(currentProjectStore.currentProductInfo.id);
	const [workFlowJobInfo, setWorkFlowJobInfo] = useState<ITaskInfo>();
	const [patchInfo, setPatchInfo] = useState<any>();
	const [overviewInfo, setOverviewInfo] = useState<any>();

	const [overviewActive, setOverviewActive] = useState(true);
	/** 选中的node Id */
	const [activeFlowIndex, setActiveFlowIndex] = useState<string>("");
	// const [showOptions, setShowOptions] = useState<boolean>(false);
	const [randerOutputs1, setRanderOutputs] = useState<Array<any>>([]);
	const locationInfo: any = useLocation()?.state;
	// const locationInfo: any = location?.state;
	const navigate = useNavigate();
	const message = useMessage();
	const isPass = usePass();
	const [fullScreenShow, setFullScreenShow] = useState<boolean>(false);
	// 查看日志弹框显示
	const [showLogView, setShowLogView] = useState<boolean>(false);
	// 日志信息
	const [logs, setLogs] = useState<Array<any>>([]);

	const { name, state } = workFlowJobInfo || {};
	// 查看数据集（数据集详情）显示控制
	const [showSeeDataset, setShowSeeDataset] = useState(false);
	// 查看的数据集的数据集名称
	const [seeDatasetName, setSeeDatasetName] = useState("");
	// 查看的数据集的数据集路径
	const [seeDatasetPath, setSeeDatasetPath] = useState("");

	/** 获取模版数据 */
	const { run } = useMyRequest(fetchWorkFlowJob, {
		pollingInterval: 1000 * 20,
		pollingWhenHidden: false,
		onSuccess: (res: IResponse<ITaskInfo>) => {
			getOutouts(res.data.outputs);
			getLogs(res.data);
			setWorkFlowJobInfo(res.data);
			const newWorkflowId = locationInfo?.taskId?.replaceAll("-", "");
			getFlowNumber({
				projectId,
				workflowId: newWorkflowId,
				filetoken: fileToken,
				token: getToken(),
			});
		},
	});

	// 处理日志数据
	const getLogs = (data: any) => {
		let logs = [{ logName: "workflow.log", logPath: data.logPath }];
		data.tasks.forEach((i: any) => {
			if (i.outLog) {
				logs.push({ logName: `${i.title}.log`, logPath: i.outLog });
			}
		});
		setLogs(logs);
	};

	/** 更新流节点传输数据 */
	const updateFlowNodeEdgeLabel = useCallback(
		(flowNodeInfo: IFlowNodeTransmissionNum[]) => {
			const newTasks =
				workFlowJobInfo &&
				workFlowJobInfo?.tasks?.length &&
				workFlowJobInfo?.tasks.map((item) => {
					if (getSameBatch(flowNodeInfo, item)) {
						const newEdges =
							item?.edges?.length &&
							item.edges.map((edgeItem) => {
								const connectionArr = getConnectionArr(flowNodeInfo, edgeItem);
								if (connectionArr?.length) {
									return {
										...edgeItem,
										label: String(connectionArr[0]?.value),
									};
								} else {
									return edgeItem;
								}
							});
						return {
							...item,
							edges: newEdges || [],
						};
					} else {
						return item;
					}
				});
			if (workFlowJobInfo) {
				setWorkFlowJobInfo({
					...workFlowJobInfo,
					tasks: newTasks || [],
				});
			}
		},
		[workFlowJobInfo]
	);

	/** 获取流节点数据 */
	const { run: getFlowNumber } = useMyRequest(fetchFlowOutputNumber, {
		pollingInterval: 1000 * 20,
		pollingWhenHidden: false,
		onSuccess: (res: IResponse<IFlowNodeTransmissionNum[]>) => {
			if (res?.data?.length) {
				updateFlowNodeEdgeLabel(res.data);
			}
		},
	});

	useEffect(() => {
		run({
			id: locationInfo.taskId,
		});
	}, [locationInfo.taskId, run]);

	const { run: getworkFlowTaskInfoRun } = useMyRequest(getworkFlowTaskInfo, {
		onSuccess: (res) => {
			setPatchInfo(res.data);
		},
	});

	// 前往数据管理页面
	const goToProjectData = (path: string) => {
		path = path.slice(12);
		if (path) {
			navigate(`/product/${productId || "cadd"}/projectData`, {
				state: { pathName: path },
			});
		} else {
			navigate(`/product/${productId || "cadd"}/projectData`, {
				state: { pathName: "/" },
			});
		}
	};

	// 下载任务结果
	const handleDownLoadOutput = (item: any) => {
		// 是文件下载
		if (item.type !== "dataset") {
			CloudEController.JobFileDownload(
				item.path.slice(12),
				fileToken as string,
				projectId as string
			);
		} else {
			// 是数据集 查看数据集
			setSeeDatasetPath(getDatasetPath(item.path));
			setSeeDatasetName(getDatasetName(item.path));
			setShowSeeDataset(true);
		}
	};

	/** 返回事件 */
	const onBack = useCallback(() => {
		if (locationInfo.from === "projectOverview") {
			navigate(`/product/${productId || "cadd"}/projectOverview`);
		} else {
			navigate(`/product/${productId || "cadd"}/projectWorkbench`, {
				state: { type: "workbenchList" },
			});
		}
	}, [navigate, locationInfo.from, productId]);

	const getOutouts = (outputs: any) => {
		if (outputs) {
			let result = Object.keys(outputs);
			let arr = result.map((item) => {
				let type = "file";
				if (outputs[item].indexOf("dataset") !== -1) {
					type = "dataset";
				}
				return {
					name: item,
					type,
					path: outputs[item],
					size: 0,
				};
			});
			arr.forEach(async (item, index) => {
				if (item.type === "dataset") {
					await getDataSetSize(item, index);
				} else {
					await getFileSize(item, index);
				}
			});
			randerOutputs = arr;
			setRanderOutputs([...randerOutputs]);
		} else {
			randerOutputs = [];
			setRanderOutputs([]);
		}
	};

	const getDataSetSize = async (item: any, index: number) => {
		CloudEController.GetDatasetSize({
			type: productId,
			projectId: projectId as string,
			token: getToken(),
			filetoken: fileToken as string,
			path: getDatasetPath(item.path),
			name: getDatasetName(item.path),
		})
			?.then((res) => {
				randerOutputs[index].size = `${res.data}条`;
				setRanderOutputs([...randerOutputs]);
			})
			?.catch(() => {
				message.error("获取数据集大小失败");
			});
	};

	const getFileSize = (item: any, index: number) => {
		let path = item.path.slice(12);
		const lastIndex = path.lastIndexOf("/");
		if (lastIndex === -1) {
			path = "/";
		} else {
			path = path.slice(0, lastIndex + 1);
		}
		CloudEController.JobOutFileList(
			path,
			fileToken as string,
			projectId as string,
			false
		)?.then((res) => {
			if (Array.isArray(res.data)) {
				res.data.forEach((item1) => {
					if (item1.name === item.path.slice(item.path.lastIndexOf("/") + 1)) {
						randerOutputs[index].size = `${
							item1.size ? storageUnitFromB(Number(item1.size)) : "-"
						}`;
						setRanderOutputs([...randerOutputs]);
					}
				});
			}
		});
	};

	// 取消作业
	const { run: cancelWorkJob } = useMyRequest(cancelWorkflowJob, {
		onSuccess: (res: IResponse<boolean>) => {
			const { errorCode } = res;
			if (errorCode === 0) {
				message.success("操作成功！");
			}
			onBack();
		},
	});

	// 取消作业
	const { run: deleteWorkJob } = useMyRequest(deleteWorkflowJob, {
		onSuccess: (res: IResponse<boolean>) => {
			const { errorCode } = res;
			if (errorCode === 0) {
				message.success("操作成功！");
			}
			onBack();
		},
	});

	const setExternalSelectedNodeId = (id: string) => {
		setActiveFlowIndex(id);
		workFlowJobInfo?.tasks &&
			workFlowJobInfo?.tasks?.forEach((item) => {
				if (item.id === id) {
					getworkFlowTaskInfoRun({
						jobId: workFlowJobInfo?.id as string,
						taskId: item.parentNode || item.id,
					});
				}
			});
	};

	const selectedParameter = useCallback(
		(list: any) => {
			let result: any = [];
			list?.length &&
				list?.forEach((item: any) => {
					if (item.id === activeFlowIndex) {
						setOverviewInfo(item);
						result = item.parameters;
					}
				});
			return result;
		},
		[activeFlowIndex]
	);

	const randerParameters = useMemo(() => {
		if (patchInfo?.id === activeFlowIndex) {
			setOverviewInfo(patchInfo);
			return patchInfo?.parameters;
		} else {
			return selectedParameter(patchInfo?.children);
		}
	}, [activeFlowIndex, patchInfo, selectedParameter]);

	const handleParams = () => {
		setOverviewActive(false);
	};

	/** 终止任务 */
	const onStopJob = useCallback(() => {
		cancelWorkJob({
			jobid: workFlowJobInfo?.id || "",
		});
	}, [cancelWorkJob, workFlowJobInfo?.id]);

	/** 删除任务 */
	const onDeleteJob = useCallback(() => {
		deleteWorkJob({
			id: workFlowJobInfo?.id || "",
		});
	}, [deleteWorkJob, workFlowJobInfo?.id]);

	const returnPermission = useMemo(() => {
		if (["SUBMITTED", "RUNNING"].includes(state || "")) {
			return isPass("PROJECT_WORKBENCH_JOBS_STOP", "USER");
		} else {
			return isPass("PROJECT_WORKBENCH_JOBS_DELETE", "MANAGER");
		}
	}, [isPass, state]);

	const [goToProjectDataPath, setGoToProjectDataPath] = useState("");
	const [popperTitle, setPopperTitle] = useState(
		"正在运行的任务终止后将无法重新运行，确认继续吗？"
	);
	const [placement, setPlacement] = useState<"bottom" | "bottom-start">(
		"bottom"
	);
	const [anchorEl, setAnchorEl] = useState<any>(null);
	const handleCancel = () => {
		setAnchorEl(null);
	};

	const handleShowPopper = (
		e: any,
		title: string,
		placementParams: "bottom" | "bottom-start"
	) => {
		setPlacement(placementParams);
		setPopperTitle(title);
		setAnchorEl(e.currentTarget);
	};

	const handleConfirm = () => {
		if (popperTitle === "正在运行的任务终止后将无法重新运行，确认继续吗？") {
			onStopJob();
		} else if (popperTitle === "任务被删除后将无法恢复，确认继续吗？") {
			onDeleteJob();
		} else {
			goToProjectData(goToProjectDataPath);
		}
	};

	const handleClose = () => {
		setShowLogView(false);
	};

	return (
		<div className={styles.swBox}>
			{fullScreenShow ? null : (
				<div className={styles.swHeader}>
					<div className={styles.swHeaderLeft}>
						<div className={styles.goBackIconBox}>
							<img
								onClick={onBack}
								className={styles.goBackIcon}
								src={goback}
								alt=""
							/>
						</div>
						<div className={styles.swTemplateTitle}>{name}</div>
					</div>
					{returnPermission && (
						<div className={styles.swHeaderRight}>
							<MyButton
								text={
									["SUBMITTED", "RUNNING"].includes(state || "")
										? "终止"
										: "删除"
								}
								variant="outlined"
								color="error"
								onClick={(e: any) =>
									handleShowPopper(
										e,
										["SUBMITTED", "RUNNING"].includes(state || "")
											? "正在运行的任务终止后将无法重新运行，确认继续吗？"
											: "任务被删除后将无法恢复，确认继续吗？",
										"bottom-start"
									)
								}
							></MyButton>
						</div>
					)}
				</div>
			)}
			<div className={styles.swContent}>
				{fullScreenShow ? null : (
					<div className={styles.swFormBox}>
						{!activeFlowIndex && (
							<TaskInfo
								workFlowJobInfo={workFlowJobInfo as ITaskInfo}
								randerOutputs1={randerOutputs1}
								handleDownLoadOutput={handleDownLoadOutput}
								handleShowPopper={handleShowPopper}
								setGoToProjectDataPath={setGoToProjectDataPath}
								setShowLogView={setShowLogView}
								state={state}
								name={name}
							/>
						)}
						{activeFlowIndex && (
							<div className={styles.suanziInfo}>
								<MyTooltip>
									<div className={styles.title}>{overviewInfo?.title}</div>
								</MyTooltip>
								<div className={styles.tabs}>
									<div
										className={classNames({
											[styles.tabLi]: true,
											[styles.tabLiAcitve]: overviewActive,
										})}
										onClick={() => setOverviewActive(true)}
									>
										概览
									</div>
									<div
										className={classNames({
											[styles.tabLi]: true,
											[styles.tabLiAcitve]: !overviewActive,
										})}
										// onClick={() => setOverviewActive(false)}
										onClick={() => handleParams()}
									>
										参数
									</div>
								</div>
								{overviewActive && (
									<div className={styles.overview}>
										<div className={styles.taskInfoLi}>
											<div className={styles.taskInfoParams}>描述</div>
											<div
												className={classNames({
													[styles.taskInfoValue]: true,
													[styles.taskInfoValueShowAll]: true,
												})}
											>
												{overviewInfo?.description}
											</div>
										</div>
										<div className={styles.taskInfoLi}>
											<div className={styles.taskInfoParams}>算子版本</div>
											<div className={styles.taskInfoValue}>
												{overviewInfo?.version || "-"}
											</div>
										</div>
										<div className={styles.taskInfoLi}>
											<div className={styles.taskInfoParams}>算子状态</div>
											<div className={styles.taskInfoValue}>
												{overviewInfo?.status === "Done" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobSue}
														alt=""
													/>
												)}
												{overviewInfo?.status === "Running" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobRun}
														alt=""
													/>
												)}
												{overviewInfo?.status === "Failed" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobFail}
														alt=""
													/>
												)}
												{statusMap[overviewInfo?.status as IStatus]}
											</div>
										</div>
									</div>
								)}
								{!overviewActive && (
									<div className={styles.params}>
										{randerParameters?.map((parameter: any) => {
											return (
												<div className={styles.taskInfoLi} key={parameter.name}>
													<div className={styles.taskInfoParams}>
														{parameter.name}
													</div>
													<div className={styles.taskInfoValue}>
														{parameter.value || "-"}
													</div>
												</div>
											);
										})}
									</div>
								)}
							</div>
						)}
					</div>
				)}
				<div
					className={styles.swFlowBox}
					style={fullScreenShow ? { height: "100vh" } : undefined}
				>
					<Flow
						externalSelectedNodeId={activeFlowIndex}
						tasks={workFlowJobInfo?.tasks}
						setExternalSelectedNodeId={setExternalSelectedNodeId}
					/>
				</div>
			</div>
			<img
				className={styles.fullScreenBox}
				src={fullScreenShow ? partialScreen : fullScreen}
				onClick={() => setFullScreenShow(!fullScreenShow)}
				alt="全屏"
			/>
			<MyPopconfirm
				title={popperTitle}
				anchorEl={anchorEl}
				onCancel={handleCancel}
				onConfirm={handleConfirm}
				placement={placement}
			/>
			{showSeeDataset && (
				<SeeDataset
					handleClose={() => setShowSeeDataset(false)}
					name={seeDatasetName}
					path={seeDatasetPath}
					fileToken={fileToken as string}
					projectId={projectId as string}
				></SeeDataset>
			)}
			{showLogView && <LogView logs={logs} setShowLogView={handleClose} />}
		</div>
	);
});

export default ProjectSubmitWork;
