import React, { Fragment, useEffect, useState } from "react";
import { Box, Button, DialogContentText } from "@mui/material";
import PageHeader from "../Common/PageHeader/PageHeader";
import PageLayout from "../Common/Layout/PageLayout";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import { CopyIcon, FileBookIcon, PasswordKeyIcon } from "../../../icons";
import ModalWrapper from "../Common/ModalWrapper/ModalWrapper";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import {
  deleteDialogStyles,
  modalStyleUtils,
} from "../Common/FormComponents/common/styleLibrary";
import withStyles from "@mui/styles/withStyles";
import { setErrorSnackMessage } from "../../../actions";
import { connect } from "react-redux";
import HelpBox from "../../../common/HelpBox";
import {
  deleteCookie,
  getCookieValue,
  performDownload,
} from "../../../common/utils";
import DistributedOnly from "../Common/DistributedOnly/DistributedOnly";
import { AppState } from "../../../store";
import { InspectMenuIcon } from "../../../icons/SidebarMenus";

const styles = (theme: Theme) =>
  createStyles({
    switchLabel: {
      fontWeight: "normal",
    },
    ...deleteDialogStyles,
    ...modalStyleUtils,
  });

const KeyRevealer = ({ value }: { value: string }) => {
  const [shown, setShown] = React.useState(false);

  return (
    <Box
      sx={{
        display: "flex",
        alignItems: "center",
        flexFlow: {
          sm: "row",
          xs: "column",
        },
      }}
    >
      <InputBoxWrapper
        id="inspect-dec-key"
        name="inspect-dec-key"
        placeholder=""
        label=""
        type={shown ? "text" : "password"}
        onChange={() => {}}
        value={value}
        overlayIcon={<CopyIcon />}
        extraInputProps={{
          readOnly: true,
        }}
        overlayAction={() => navigator.clipboard.writeText(value)}
      />

      <Button
        sx={{
          marginLeft: "10px",
        }}
        variant="contained"
        onClick={() => setShown(!shown)}
      >
        Show/Hide
      </Button>
    </Box>
  );
};

const mapState = (state: AppState) => ({
  distributedSetup: state.system.distributedSetup,
});

const mapDispatchToProps = {
  setErrorSnackMessage,
};
const connector = connect(mapState, mapDispatchToProps);

const Inspect = ({
  classes,
  setErrorSnackMessage,
  distributedSetup,
}: {
  classes: any;
  setErrorSnackMessage: any;
  distributedSetup: boolean;
}) => {
  const [volumeName, setVolumeName] = useState<string>("");
  const [inspectPath, setInspectPath] = useState<string>("");
  const [isEncrypt, setIsEncrypt] = useState<boolean>(true);

  const [decryptionKey, setDecryptionKey] = useState<string>("");

  const [insFileName, setInsFileName] = useState<string>("");

  const [isFormValid, setIsFormValid] = useState<boolean>(false);
  const [volumeError, setVolumeError] = useState<string>("");
  const [pathError, setPathError] = useState<string>("");

  /**
   * Validation Effect
   */
  useEffect(() => {
    let isVolValid;
    let isPathValid;

    isVolValid = volumeName.trim().length > 0;
    if (!isVolValid) {
      setVolumeError("此字段必填");
    } else if (volumeName.slice(0, 1) === "/") {
      isVolValid = false;
      setVolumeError("Volume/Bucket name cannot start with /");
    }
    isPathValid = inspectPath.trim().length > 0;
    if (!inspectPath) {
      setPathError("此字段必填");
    } else if (inspectPath.slice(0, 1) === "/") {
      isPathValid = false;
      setPathError("Path cannot start with /");
    }
    const isValid = isVolValid && isPathValid;

    if (isVolValid) {
      setVolumeError("");
    }
    if (isPathValid) {
      setPathError("");
    }

    setIsFormValid(isValid);
  }, [volumeName, inspectPath]);

  const makeRequest = async (url: string) => {
    return await fetch(url, { method: "GET" });
  };

  const performInspect = async () => {
    const file = encodeURIComponent(inspectPath);
    const volume = encodeURIComponent(volumeName);

    const urlOfInspectApi = `/api/v1/admin/inspect?volume=${volume}&file=${file}&encrypt=${isEncrypt}`;

    makeRequest(urlOfInspectApi)
      .then(async (res) => {
        if (!res.ok) {
          const resErr: any = await res.json();

          setErrorSnackMessage({
            errorMessage: resErr.message,
            detailedError: resErr.code,
          });
        }
        const blob: Blob = await res.blob();

        //@ts-ignore
        const filename = res.headers.get("content-disposition").split('"')[1];
        const decryptKey = getCookieValue(filename) || "";

        performDownload(blob, filename);
        setInsFileName(filename);
        setDecryptionKey(decryptKey);
      })
      .catch((err) => {
        setErrorSnackMessage(err);
      });
  };

  const resetForm = () => {
    setVolumeName("");
    setInspectPath("");
    setIsEncrypt(true);
  };

  const onCloseDecKeyModal = () => {
    deleteCookie(insFileName);
    setDecryptionKey("");
    resetForm();
  };

  return (
    <Fragment>
      <PageHeader label={"检查"} />
      <PageLayout>
        {!distributedSetup ? (
          <DistributedOnly
            iconComponent={<InspectMenuIcon />}
            entity={"检查"}
          />
        ) : (
          <Fragment>
            <Box
              sx={{
                border: "1px solid #eaeaea",
                padding: "25px",
              }}
            >
              <form
                noValidate
                autoComplete="off"
                onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
                  e.preventDefault();
                  performInspect();
                }}
              >
                <Box>
                  <InputBoxWrapper
                    id="inspect_volume"
                    name="inspect_volume"
                    extraInputProps={{
                      "data-test-id": "inspect_volume",
                    }}
                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                      setVolumeName(e.target.value);
                    }}
                    label="卷或存储桶名称"
                    value={volumeName}
                    error={volumeError}
                    required
                    placeholder={"测试存储桶"}
                  />
                </Box>
                <Box
                  sx={{
                    marginTop: "15px",
                  }}
                >
                  <InputBoxWrapper
                    id="inspect_path"
                    name="inspect_path"
                    extraInputProps={{
                      "data-test-id": "inspect_path",
                    }}
                    error={pathError}
                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                      setInspectPath(e.target.value);
                    }}
                    label="要检查的文件或路径"
                    value={inspectPath}
                    required
                    placeholder={"test*/xl.meta"}
                  />
                </Box>
                <Box
                  sx={{
                    marginTop: "25px",
                  }}
                >
                  <FormSwitchWrapper
                    classes={{
                      inputLabel: classes.switchLabel,
                    }}
                    extraInputProps={{
                      "data-test-id": "inspect_encrypt",
                    }}
                    label="加密"
                    indicatorLabels={["是", "否"]}
                    checked={isEncrypt}
                    value={"true"}
                    id="inspect_encrypt"
                    name="inspect_encrypt"
                    onChange={(e) => {
                      setIsEncrypt(!isEncrypt);
                    }}
                  />
                </Box>
                <Box
                  sx={{
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "flex-end",
                    marginTop: "55px",
                  }}
                >
                  <Button
                    sx={{
                      marginRight: "15px",
                    }}
                    type="button"
                    color="primary"
                    variant="outlined"
                    data-test-id="inspect-clear-button"
                    onClick={resetForm}
                  >
                    清除
                  </Button>
                  <Button
                    type="submit"
                    variant="contained"
                    color="primary"
                    data-test-id="inspect-submit-button"
                    disabled={!isFormValid}
                  >
                    检查
                  </Button>
                </Box>
              </form>
            </Box>
            <Box
              sx={{
                marginTop: "55px",
              }}
            >
              <HelpBox
                title={"Inspect"}
                iconComponent={<FileBookIcon />}
                help={
                  <Fragment>
                    <Box
                      sx={{
                        marginTop: "15px",
                      }}
                    >
                      检查土星云服务器上的文件
                    </Box>

                    <Box
                      sx={{
                        marginTop: "15px",
                        fontWeight: 500,
                      }}
                    >
                      例子
                    </Box>

                    <Box
                      sx={{
                        display: "flex",
                        flexFlow: "column",
                        flex: "2",
                        marginTop: "15px",
                        "& .step-number": {
                          color: "#ffffff",
                          height: "25px",
                          width: "25px",
                          background: "#081C42",
                          marginRight: "10px",
                          textAlign: "center",
                          fontWeight: 600,
                          borderRadius: "50%",
                        },

                        "& .step-row": {
                          fontSize: "16px",
                          display: "flex",
                          marginTop: "15px",
                          marginBottom: "15px",
                        },

                        "& code": {
                          paddingLeft: "10px",
                          paddingRight: "10px",
                          paddingTop: "4px",
                          paddingBottom: "3px",
                          borderRadius: "2px",
                          backgroundColor: "#eaeaea",
                          color: "#082146",
                        },
                        "& .spacer": {
                          marginBottom: "5px",
                        },
                      }}
                    >
                      <Box>
                        <Box className="step-row">
                          <div className="step-text">
                          下载'xl。“元”用于所有特定对象zip文件中的磁盘:
                          </div>
                        </Box>

                        <Box
                          sx={{
                            flex: "1",
                            marginTop: "15px",
                            marginLeft: "35px",
                            "& input": {
                              color: "#737373",
                            },
                          }}
                        >
                          <Box>
                            <label>卷/存储桶名称 :</label>{" "}
                            <code>test-bucket</code>
                            <div className="spacer" />
                            <label>路径 : </label>
                            <code>test*/xl.meta</code>
                          </Box>
                        </Box>
                      </Box>

                      <Box>
                        <Box className="step-row">
                          <div className="step-text">
                          下载特定应用程序的所有组成部分对象，并可选地加密下载的zip：
                          </div>
                        </Box>

                        <Box
                          sx={{
                            flex: "1",
                            marginTop: "15px",
                            marginLeft: "35px",
                            "& input": {
                              color: "#737373",
                            },
                          }}
                        >
                          <Box>
                            <label>卷/存储桶名称: </label>
                            <code>test-bucket</code>
                            <div className="spacer" />
                            <label>路径 :</label> <code>test*/*/part.*</code>
                          </Box>
                        </Box>
                      </Box>
                      <Box>
                        <Box className="step-row">
                          <div className="step-text">
                          以前缀递归下载所有对象。
                            <br />
                            注意：这可能是一项昂贵的操作，请谨慎使用。
                          </div>
                        </Box>

                        <Box
                          sx={{
                            flex: "1",
                            marginTop: "15px",
                            marginLeft: "35px",
                            "& input": {
                              color: "#737373",
                            },
                          }}
                        >
                          <Box>
                            <label>Volume/bucket Name : </label>
                            <code>test-bucket</code>
                            <div className="spacer" />
                            <label>路径 :</label> <code>test/**</code>
                          </Box>
                        </Box>
                      </Box>
                    </Box>

                    <Box
                      sx={{
                        marginTop: "30px",
                      }}
                    >
                      {/* 您可以在我们的文档中了解更多信息。 */}
                    </Box>
                  </Fragment>
                }
              />
            </Box>
          </Fragment>
        )}
        {decryptionKey ? (
          <ModalWrapper
            modalOpen={true}
            title="Inspect Decryption Key"
            onClose={onCloseDecKeyModal}
            titleIcon={<PasswordKeyIcon />}
          >
            <DialogContentText>
              <Box>
              这将只显示一次。它无法恢复。
                <br />
                使用安全介质共享此密钥。
              </Box>
              <Box>
                <KeyRevealer value={decryptionKey} />
              </Box>
            </DialogContentText>
          </ModalWrapper>
        ) : null}
      </PageLayout>
    </Fragment>
  );
};

export default withStyles(styles)(connector(Inspect));
