/*
 * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
 * @Date: 2022-06-21 20:03:56
 * @LastEditors: 吴永生 15770852798@163.com
 * @LastEditTime: 2022-08-15 17:18:49
 * @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 ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import IconButton from "@mui/material/IconButton";

import MyButton from "@/components/mui/MyButton";
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 jobStop from "@/assets/project/jobStop.svg";
import jobRun from "@/assets/project/jobRun.svg";
import fullScreen from "@/assets/project/fullScreen.svg";
import partialScreen from "@/assets/project/partialScreen.svg";
import CloudEController from "@/api/fileserver/CloudEController";
import jobFail from "@/assets/project/jobFail.svg";
import fileIcon from "@/assets/project/fileIcon.svg";
import dataSetIcon from "@/assets/project/dataSetIcon.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 styles from "./index.module.css";

const stateMap = {
	RUNNING: "正在运行",
	ABORTED: "运行终止",
	FAILED: "运行失败",
	SUCCEEDED: "运行成功",
};

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 [activePatchId, setActivePatchId] = useState<string>("");
	const [overviewActive, setOverviewActive] = useState(true);
	const [activeFlowIndex, setActiveFlowIndex] = useState<number>(0);
	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 * 60,
		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/cadd/projectData`, {
				state: { pathName: path },
			});
		} else {
			navigate(`/product/cadd/projectData`, {
				state: { pathName: "/" },
			});
		}
	};

	// 通过文件路径获取文件所在文件夹路径  如 输入 /ProjectData/task_a.out  输出/ProjectData/
	// const getFolderPath = (path: string) => {
	// 	const lastIndex = path.lastIndexOf("/");
	// 	if (lastIndex !== -1) {
	// 		path = path.slice(0, lastIndex);
	// 	}
	// 	return path;
	// };

	// 下载任务结果
	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/cadd/projectOverview");
		} else {
			navigate("/product/cadd/projectWorkbench", {
				state: { type: "workbenchList" },
			});
		}
	}, [navigate]);

	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 handleBatch = (id: string) => {
		setActivePatchId(id);
		if (id) {
			setActiveFlowIndex(0);
			getworkFlowTaskInfoRun({
				jobId: workFlowJobInfo?.id as string,
				taskId: id,
			});
		}
	};

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

	const handleParams = () => {
		setOverviewActive(false);
		setShowOptions(!showOptions);
	};

	const handleDownLoad = (path: string) => {
		if (path.indexOf("/ProjectData") !== -1) {
			path = path.slice(12);
		}
		CloudEController.JobFileDownload(
			path,
			fileToken as string,
			projectId as string
		);
	};

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

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

	const returnPermission = useMemo(() => {
		if (state === "RUNNING") {
			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 [anchorEl, setAnchorEl] = useState<any>(null);
	const handleCancel = () => {
		setAnchorEl(null);
	};

	const handleShowPopper = (e: any, title: string) => {
		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}>
						<IconButton
							color="primary"
							onClick={onBack}
							aria-label="upload picture"
							component="span"
							size="small"
						>
							<ArrowBackIosNewIcon
								sx={{
									color: "rgba(194, 198, 204, 1)",
									width: "12px",
									height: "12px",
								}}
							/>
						</IconButton>

						<div className={styles.swTemplateTitle}>{name}</div>
					</div>
					{returnPermission && (
						<div className={styles.swHeaderRight}>
							{/* <MyPopconfirm
								title={
									state === "RUNNING"
										? "正在运行的任务终止后将无法重新运行，确认继续吗？"
										: "任务被删除后将无法恢复，确认继续吗？"
								}
								onConfirm={() => {
									state === "RUNNING" ? onStopJob() : onDeleteJob();
								}}
							> */}
							<MyButton
								text={state === "RUNNING" ? "终止" : "删除"}
								variant="outlined"
								color="secondary"
								onClick={(e: any) =>
									handleShowPopper(
										e,
										state === "RUNNING"
											? "正在运行的任务终止后将无法重新运行，确认继续吗？"
											: "任务被删除后将无法恢复，确认继续吗？"
									)
								}
							// click={onStopJob}
							></MyButton>
							{/* </MyPopconfirm> */}
						</div>
					)}
				</div>
			)}
			<div className={styles.swContent}>
				{fullScreenShow ? null : (
					<div className={styles.swFormBox}>
						{!activePatchId && (
							<div className={styles.taskInfo}>
								<div className={styles.title}>任务结果</div>
								{workFlowJobInfo?.outputs &&
									Object.keys(workFlowJobInfo?.outputs).length > 0 && (
										<div className={styles.taskResults}>
											{randerOutputs1.map((item, index) => {
												return (
													<div key={index} className={styles.outputLi}>
														<div
															className={styles.outputLiLeft}
															onClick={(e: any) => {
																handleDownLoadOutput(item);
																// goToProjectData(getFolderPath(item.path));
															}}
														>
															<img
																className={styles.outputLiLeftImg}
																src={
																	item.type === "file" ? fileIcon : dataSetIcon
																}
																alt=""
															/>
															{item.name}
														</div>
														{/* </MyPopconfirm> */}
														<span className={styles.outputLiRight}>
															{item.size}
														</span>
													</div>
												);
											})}
										</div>
									)}
								{(!workFlowJobInfo?.outputs ||
									Object.keys(workFlowJobInfo?.outputs).length === 0) && (
										<div className={styles.notResults}>暂无结果文件</div>
									)}
								<div className={styles.title}>任务信息</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>任务名称</div>
									<div className={styles.taskInfoValue} title={name}>
										{name || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>任务ID</div>
									<div
										className={styles.taskInfoValue}
										title={workFlowJobInfo?.id}
									>
										{workFlowJobInfo?.id || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>输出路径</div>
									<div
										className={classNames({
											[styles.taskInfoValue]: true,
											[styles.taskInfoValueClick]: true,
										})}
										onClick={(e: any) => {
											handleShowPopper(
												e,
												"即将跳转至项目数据内该任务的输出路径，确认继续吗？"
											);
											setGoToProjectDataPath(
												workFlowJobInfo?.outputPath as string
											);
										}}
									>
										{workFlowJobInfo?.outputPath || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>运行状态</div>
									<div className={styles.taskInfoValue}>
										{state === "SUCCEEDED" && (
											<img
												className={styles.taskInfoValueIcon}
												src={jobSue}
												alt=""
											/>
										)}
										{state === "RUNNING" && (
											<img
												className={styles.taskInfoValueIcon}
												src={jobRun}
												alt=""
											/>
										)}
										{state === "ABORTED" && (
											<img
												className={styles.taskInfoValueIcon}
												src={jobStop}
												alt=""
											/>
										)}
										{state === "FAILED" && (
											<img
												className={styles.taskInfoValueIcon}
												src={jobFail}
												alt=""
											/>
										)}
										{state ? stateMap[state] : "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>源模板</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.specTitle || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>源模板版本</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.specVersion || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>花费（元）</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.jobCost || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>创建人</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.creator || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>创建时间</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.createTime || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>运行时间</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.costTime || "-"}
									</div>
								</div>
								<div className={styles.taskInfoLi}>
									<div className={styles.taskInfoParams}>日志文件</div>
									<div className={styles.taskInfoValue}>
										{workFlowJobInfo?.logPath && (
											<>
												{/* <span
												className={styles.taskInfoDownload}
												onClick={() => handleDownLoad(workFlowJobInfo?.logPath)}
											>
												下载
											</span> */}
												<span
													className={styles.taskInfoDownload}
													onClick={() => setShowLogView(true)}
												>
													查看
												</span>
											</>
										)}
										{!workFlowJobInfo?.logPath && "-"}
									</div>
								</div>
							</div>
						)}
						{activePatchId && (
							<div className={styles.suanziInfo}>
								<div className={styles.title}>{patchInfo?.title}</div>
								<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()}
									>
										{patchInfo?.children.length > 0
											? patchInfo?.children[activeFlowIndex].title
											: patchInfo?.title}
										{showOptions && patchInfo?.children.length > 0 && (
											<div className={styles.options}>
												{patchInfo?.children.map((item: any, index: number) => {
													return (
														<div
															key={index}
															className={classNames({
																[styles.option]: true,
																[styles.optionActive]:
																	activeFlowIndex === index,
															})}
															onClick={() => setActiveFlowIndex(index)}
														>
															{item.title}
														</div>
													);
												})}
											</div>
										)}
									</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,
												})}
											>
												{patchInfo?.description}
											</div>
										</div>
										<div className={styles.taskInfoLi}>
											<div className={styles.taskInfoParams}>算子版本</div>
											<div className={styles.taskInfoValue}>
												{patchInfo?.version || "-"}
											</div>
										</div>
										<div className={styles.taskInfoLi}>
											<div className={styles.taskInfoParams}>算子状态</div>
											<div className={styles.taskInfoValue}>
												{patchInfo?.status === "Done" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobSue}
														alt=""
													/>
												)}
												{patchInfo?.status === "Running" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobRun}
														alt=""
													/>
												)}
												{patchInfo?.status === "Failed" && (
													<img
														className={styles.taskInfoValueIcon}
														src={jobFail}
														alt=""
													/>
												)}
												{statusMap[patchInfo?.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 tasks={workFlowJobInfo?.tasks} onBatchClick={handleBatch} />
				</div>
			</div>
			<img
				className={styles.fullScreenBox}
				src={fullScreenShow ? partialScreen : fullScreen}
				onClick={() => setFullScreenShow(!fullScreenShow)}
				alt="全屏"
			/>
			<MyPopconfirm
				title={popperTitle}
				anchorEl={anchorEl}
				onCancel={handleCancel}
				onConfirm={handleConfirm}
			/>
			{showSeeDataset && (
				<SeeDataset
					handleClose={() => setShowSeeDataset(false)}
					name={seeDatasetName}
					path={seeDatasetPath}
					fileToken={fileToken as string}
					projectId={projectId as string}
				></SeeDataset>
			)}
			<LogView
				isshow={showLogView}
				handleClose={handleClose}
				logs={logs}
			/>
		</div>
	);
});

export default ProjectSubmitWork;
