import { useEffect, useState, useCallback } from "react";
import MyInput from "@/components/mui/MyInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import style from "./index.module.css";
import useMyRequest from "@/hooks/useMyRequest";
import { urlToken } from "@/api/fileserver/raysyncApi";
import * as tus from "tus-js-client";
import { useDropzone } from "react-dropzone";
import SwitchBatchFolw from "@/views/ResourceCenter/components/SwitchBatchFolw";
import { getLoaclStorageOfKey } from "@/api/fileserver/utils";
import Code from "@/components/CommonComponents/Code";
import * as Base64 from "js-base64";
import { getDataFileToken, hpczone } from "@/api/project_api";
import {
	getPublicEnv,
	getPublicProject,
	addActorenvBuildenv,
} from "@/api/resourceCenter";
import classNames from "classnames";
import { getTokenInfo } from "@/utils/util";

type IAddEnvironmentProps = {
	setAddopen: any;
};

const AddEnvironment = (props: IAddEnvironmentProps) => {
	const { setAddopen } = props;
	let tokenInfo = getTokenInfo();
	const [hpczoneList, setHpczoneList] = useState<Array<any>>([]);
	const [publicProjectId, setPublicProjectId] = useState("");
	const [publicZoneId, setPublicZoneId] = useState("");
	const [computeType, setComputeType] = useState("");
	const [fileToken, setFileToken] = useState("");
	const [taskType, setTaskType] = useState<"BATCH" | "FLOW">("BATCH");
	const [name, setName] = useState("");
	const [desc, setDesc] = useState("");
	const [baseEnvId, setBaseEnvId] = useState("");
	const [filePaths, setFilePaths] = useState<Array<string>>([]);
	// const [bashScript, setBashScript] = useState('');
	const [envList, setEnvList] = useState<Array<any>>([]);
	const [progress, setProgress] = useState("0%");
	const [code, setCode] = useState("");
	console.log(code);
	const [nameHelper, setNameHelper] = useState({
		error: false,
		text: "30字符以内，仅限字母、数字、中文",
	});
	const onDrop = useCallback(
		(acceptedFiles: any) => {
			let origin = "";
			hpczoneList.forEach((item) => {
				if (item.id === publicZoneId) {
					origin = item?.storageConfig?.fileServerEndPoint;
				}
			});
			const fileInfo = acceptedFiles[0];
			const { path } = fileInfo;
			const userInfo = getLoaclStorageOfKey("userInfo");
			const homeDirectoryMountPoint = userInfo?.homeDirectoryMountPoint;
			const url =
				origin + "/parallelupload/" + urlToken(fileToken, publicProjectId);
			let headers = {
				username: publicProjectId,
				token: tokenInfo?.access_token || "",
				filetoken: fileToken,
				share: false,
				project: true,
			};
			let upload = new tus.Upload(fileInfo, {
				endpoint: url,
				parallelUploads: 1,
				chunkSize: 5 * 1024 * 1024,
				metadata: {
					filepath: "/" + homeDirectoryMountPoint + "/" + path,
				},
				retryDelays: [0, 3000, 5000, 10000, 20000],
				headers: headers,
				onbeforeunload: () => {
					setProgress(`0%`);
				},
				onError: function (error: string) {
					console.log("Failed because: " + error);
				},
				onProgress: function (bytesUploaded: number, bytesTotal: number) {
					setProgress(`${bytesUploaded / bytesTotal}%`);
					console.log(`${bytesUploaded / bytesTotal}%`);
				},
				onSuccess: function () {
					setFilePaths([`/ProjectData/${homeDirectoryMountPoint}/${path}`]);
				},
			});
			upload.start();
		},
		[
			fileToken,
			publicProjectId,
			tokenInfo?.access_token,
			hpczoneList,
			publicZoneId,
		]
	);
	const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

	const { run: getPublicEnvFn } = useMyRequest(getPublicEnv, {
		onSuccess: (res: any) => {
			console.log(res);
			let arr = res.data.map((item: any) => {
				return {
					label: item.title,
					value: item.id,
					computeType: item.computeType,
				};
			});
			setEnvList(arr);
			if (arr.length >= 1) {
				setBaseEnvId(arr[0].value);
				setComputeType(arr[0].computeType);
			}
		},
	});

	const { run: getPublicProjectFn } = useMyRequest(getPublicProject, {
		onSuccess: (res: any) => {
			console.log(res);
			setPublicProjectId(res.data[0].id);
			setPublicZoneId(res.data[0].zoneId);
			getDataFileTokenFn({ id: res.data[0].id });
		},
	});

	const { run: getDataFileTokenFn } = useMyRequest(getDataFileToken, {
		onSuccess: (res: any) => {
			console.log(res);
			setFileToken(res.data);
		},
	});

	const { run: addActorenvBuildenvFn } = useMyRequest(addActorenvBuildenv, {
		onSuccess: (res: any) => {
			console.log(res);
		},
	});

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

	useEffect(() => {
		getPublicEnvFn({ taskType });
	}, [getPublicEnvFn, taskType]);

	const { run: hpczoneFn } = useMyRequest(hpczone, {
		onSuccess: (res: any) => {
			setHpczoneList(res.data);
		},
	});

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

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

	const handleDescChange = (e: any) => {
		setDesc(e.target.value);
	};
	const handelBaseEnvIdChange = (e: any) => {
		setBaseEnvId(e);
		let index = envList.findIndex((item) => {
			return item.value === e;
		});
		setComputeType(envList[index].computeType);
	};

	const handleSubmit = () => {
		addActorenvBuildenvFn({
			title: name,
			desc,
			baseEnvId,
			type: taskType,
			filePaths,
			bashScript: Base64.encode(code),
			publicProjectId,
			computeType,
		});
	};

	return (
		<div className={style.addEnvironment}>
			<div className={style.left}>
				<SwitchBatchFolw
					active={taskType}
					setActive={setTaskType}
					goBack={() => setAddopen(false)}
				></SwitchBatchFolw>
			</div>
			<div className={style.right}>
				<div className={style.title}>
					{taskType === "BATCH" ? "批式环境信息" : "流式环境信息"}
				</div>
				<div className={style.content}>
					<div className={style.form}>
						<div className={style.label}>
							环境名称<span className={style.required}>*</span>
						</div>
						<div
							className={classNames({
								[style.formItem]: true,
								[style.formItemHaveHelperText]: nameHelper.text,
							})}
						>
							<MyInput
								value={name}
								onChange={handleNameChange}
								error={nameHelper.error}
								helperText={nameHelper.text}
								placeholder="给环境起个名称"
							></MyInput>
						</div>
						<div className={style.label}>
							描述<span className={style.required}>*</span>
						</div>
						<div className={style.formItem}>
							<MyInput
								value={desc}
								id="desc"
								// label="项目描述"
								multiline
								rows={4}
								placeholder="请输入项目描述"
								onChange={handleDescChange}
							/>
							<span
								style={{
									position: "absolute",
									fontSize: "14px",
									bottom: "7px",
									right: "12px",
									color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC",
								}}
							>
								{desc.length}/300
							</span>
						</div>
						<div className={style.label}>
							基础环境<span className={style.required}>*</span>
						</div>
						<div className={style.formItem}>
							<MySelect
								options={envList}
								fullWidth
								value={baseEnvId}
								onChange={(e) => handelBaseEnvIdChange(e)}
							></MySelect>
						</div>
						<div className={style.label}>
							上传环境压缩包<span className={style.zipText}>（.zip）</span>
							<span className={style.required}>*</span>
							<span className={style.download}>下载模板</span>
						</div>
						<div className={style.formItem}>
							<div
								className={classNames({
									[style.uploadBox]: true,
									[style.isDragActive]: isDragActive,
								})}
								{...getRootProps()}
							>
								<input {...getInputProps()} />
								<span>点击选择环境包或将文件</span>
								<span>拖到此处上传</span>
							</div>
						</div>
					</div>
					<div className={style.codeBox}>
						<div className={style.codeTitle}>
							{taskType === "BATCH" ? "Shell脚本" : "Python脚本"}
						</div>
						<div className={style.code}>
							<Code
								value={code}
								onChange={(e: string) => setCode(e)}
								height="535px"
							/>
						</div>
					</div>
				</div>
				<div className={style.button}>
					<MyButton text="开始构建" onClick={() => handleSubmit()}></MyButton>
				</div>
			</div>
		</div>
	);
};
export default AddEnvironment;
