<template>
  <div class="card-edit">
    <component
      v-if="dataReady"
      :is="editComp"
      ref="CardDesign"
      :content="cardContent"
      @on-preview="toPreview"
      @on-save="toSave"
      @on-submit="toSubmit"
      @on-exit="toExit"
    ></component>

    <!-- card-preview-dialog -->
    <card-preview-dialog
      ref="CardPreviewDialog"
      :cardData="cardData"
      :view-type="viewType"
      @confirm="previewConfirm"
    ></card-preview-dialog>
  </div>
</template>

<script>
import { cardConfigInfos, cardDetail, saveCard } from "../api";
import CardDesign from "../../../../card/components/CardDesign.vue";
import CardFreeDesign from "../../../../card/modules/free/components/CardFreeDesign";
import CardPreviewDialog from "../components/CardPreviewDialog.vue";
import { examRuleDetail } from "../../base/api";
import { getEnums } from "../../login/api";
import timeMixin from "@/mixins/timeMixin";
import { MD5 } from "@/plugins/md5";
import { getBase64Barcode } from "@/plugins/utils";

export default {
  name: "card-edit",
  components: {
    CardDesign,
    CardFreeDesign,
    CardPreviewDialog,
  },
  props: {
    isDialog: {
      type: Boolean,
      default: false,
    },
  },
  mixins: [timeMixin],
  data() {
    return {
      cardId: this.$route.params.cardId || this.$ls.get("cardId"),
      prepareTcPCard: this.$ls.get("prepareTcPCard", {}),
      cardType: "CUSTOM",
      cardCreateMethod: "STANDARD",
      cardContent: {},
      cardName: "", // 题卡自定义名称
      cardPreviewUrl: "",
      canSave: false,
      dataReady: false,
      lastStageCardContent: "",
      sysCardSize: "",
      // card-preview-dialog
      viewType: "view",
      cardData: null,
    };
  },
  computed: {
    isEdit() {
      return !!this.cardId;
    },
    editComp() {
      return this.cardCreateMethod === "STANDARD"
        ? "card-design"
        : "card-free-design";
    },
    IS_GENERIC() {
      return this.cardType === "GENERIC";
    },
  },
  mounted() {
    this.cardCreateMethod = this.prepareTcPCard.createMethod || "STANDARD";
    this.cardId = this.cardId || this.prepareTcPCard.id;
    this.cardType = this.prepareTcPCard.type || "CUSTOM";
    this.sysCardSize = this.$ls.get("schoolInfo", { cardSize: "A3" }).cardSize;
    this.initCard();
    this.openAutoSave();
  },
  methods: {
    openAutoSave() {
      this.clearSetTs();

      this.addSetTime(async () => {
        await this.$refs.CardDesign.toSave();
        this.openAutoSave();
      }, 1 * 60 * 1000);
    },
    async initCard() {
      this.dataReady = false;
      if (this.isEdit) {
        await this.getCardTempDetail();
      } else {
        let cardConfig = await this.getCardConfig();
        if (this.IS_GENERIC) {
          cardConfig.cardTitle = this.prepareTcPCard.title;
          this.cardName = this.prepareTcPCard.title;
        } else {
          this.cardName = this.prepareTcPCard.cardName;
        }
        this.cardContent = {
          pages: [],
          cardConfig,
        };
      }

      // 设置默认的课程代码条码信息
      if (!this.cardContent.cardConfig.courseCodeBarcodeSrc) {
        this.cardContent.cardConfig.courseCodeBarcodeSrc =
          getBase64Barcode("123456789");
        this.cardContent.cardConfig.courseCodeBarcodeName = "123456789";
      }
      this.dataReady = true;
    },
    getCardTitle(titleRule) {
      const fieldMap = {
        courseCode: this.prepareTcPCard.courseCode || "",
        courseName: this.prepareTcPCard.courseName || "",
        schoolName: this.prepareTcPCard.schoolName || "",
      };
      Object.entries(fieldMap).forEach(([key, val]) => {
        titleRule = titleRule.replace("${" + key + "}", val);
      });
      return titleRule;
    },
    async getCardTempDetail() {
      const detData = await cardDetail(
        this.cardId,
        this.prepareTcPCard.isModel4
      );
      // 可能存在题卡内容没有记录的情况
      if (detData.content || detData.stageContent) {
        const content = detData.stageContent || detData.content;
        this.cardContent = JSON.parse(content);
        this.cardName = detData.title;
        this.lastStageCardContent = content;
      } else {
        let cardConfig = await this.getCardConfig();
        // 没有题卡内容时，直接创建新的内容
        if (detData.makeMethod === "CUST" || detData.type === "GENERIC") {
          cardConfig.cardTitle = detData.title;
          this.cardName = detData.title;
        } else {
          this.cardName = "";
        }
        this.cardContent = {
          pages: [],
          cardConfig,
        };
      }

      if (detData.courseCode) {
        this.cardContent.cardConfig.courseCodeBarcodeSrc = getBase64Barcode(
          detData.courseCode
        );
        this.cardContent.cardConfig.courseCodeBarcodeName = detData.courseCode;
      }
    },
    async getCardConfig() {
      if (this.cardCreateMethod === "STANDARD") {
        const data = await cardConfigInfos(this.prepareTcPCard.cardRuleId);
        if (!data) {
          this.$message.error("找不到题卡规则！");
          return Promise.reject();
        }
        let config = {
          ...data,
          ...{
            pageSize: this.sysCardSize,
            columnNumber: 2,
            columnGap: 20,
            showForbidArea: false,
            makeMethod: this.prepareTcPCard.makeMethod,
            courseCodeBarcodeSrc: "",
            courseCodeBarcodeName: "",
          },
        };
        config.fillNumber = data.examNumberDigit;
        config.aOrB = Boolean(this.prepareTcPCard.openAb);
        config.requiredFields = JSON.parse(config.requiredFields);
        config.extendFields = JSON.parse(config.extendFields);
        config.relationList = JSON.parse(config.relationList || "[]");
        config.cardTitle = this.getCardTitle(config.titleRule);
        config.firstLevelSubheading = this.getCardTitle(
          config.firstLevelSubheading
        );
        config.secondLevelSubheading = this.getCardTitle(
          config.secondLevelSubheading
        );
        return config;
      } else {
        let requiredFields = await getEnums("REQUIRED_FIELDS");
        requiredFields = requiredFields
          .filter((item) => item.enable)
          .map((item) => {
            return {
              code: item.code,
              name: item.name,
              enable: item.enable,
            };
          });
        const examRule = await examRuleDetail();
        const extendFields = examRule.extendFields || "[]";
        const config = {
          pageSize: this.sysCardSize,
          columnNumber: 2,
          columnGap: 20,
          showForbidArea: false,
          requiredFields,
          courseCodeBarcodeSrc: "",
          courseCodeBarcodeName: "",
          extendFields: JSON.parse(extendFields),
        };
        return config;
      }
    },
    // 操作
    getRequestConfig() {
      return this.prepareTcPCard.makeMethod === "CUST"
        ? {
            headers: {
              schoolId: this.prepareTcPCard.schoolId,
            },
          }
        : {};
    },
    getCardInfo(data) {
      let cardInfo = {
        ...data,
        ...this.prepareTcPCard,
        title: this.cardName,
      };
      // openAb以参数信息为主
      cardInfo.openAb = data.openAb || false;
      if (this.cardId) cardInfo.id = this.cardId;
      return cardInfo;
    },
    // card preview dialog
    dialogClosed() {
      this.cardDialogPreviewUrl = "";
    },
    toPreview(cardData) {
      this.cardData = {
        ...cardData,
        createMethod: this.cardCreateMethod,
        type: this.cardType,
      };
      this.viewType = "view";
      this.$refs.CardPreviewDialog.open();
    },
    // save
    async toSave(datas) {
      let cardInfo = this.getCardInfo(datas);
      cardInfo.status = "STAGE";
      if (MD5(cardInfo.content) === MD5(this.lastStageCardContent)) return;

      const result = await saveCard(cardInfo, this.getRequestConfig()).catch(
        () => {}
      );
      this.lastStageCardContent = cardInfo.content;
      this.$refs.CardDesign.updateUnsubmitStatus(true);
      if (!result) return;
      this.cardId = result.id;
      this.$ls.set("cardId", this.cardId);
    },
    async toSubmit(cardData) {
      const res = await this.$prompt("", "提示", {
        type: "warning",
        showInput: true,
        inputPlaceholder: "请输入题卡名称",
        inputValue: this.cardName,
        inputValidator: (val) => {
          if (!val) return "请输入题卡名称！";
          if (val.length > 50) return "题卡名称不得超过50个字符！";
          return true;
        },
      }).catch(() => {});
      if (!res || res.action !== "confirm") return;
      this.cardName = res.value;

      this.$refs.CardDesign.loading();
      this.cardData = {
        ...cardData,
        createMethod: this.cardCreateMethod,
        type: this.cardType,
      };
      this.viewType = "print";
      this.$refs.CardPreviewDialog.open();
    },
    async previewConfirm(content) {
      if (!content) {
        this.$refs.CardDesign.unloading();
        this.cardData = null;
        this.$message.error("错误：预览，提交失败，请重新尝试！");
        return;
      }
      const { htmlContent, model } = content;
      const datas = this.$refs.CardDesign.getCardData(htmlContent, model);
      const cardInfo = this.getCardInfo(datas);
      cardInfo.status = "SUBMIT";
      const result = await saveCard(cardInfo, this.getRequestConfig()).catch(
        () => {}
      );
      this.$refs.CardDesign.unloading();
      if (result) {
        this.cardId = result.id;
        this.$ls.set("cardId", this.cardId);
        this.$refs.CardDesign.updateUnsubmitStatus(false);
        this.$message.success("提交成功！");
        this.goback();
      } else {
        this.$message.error("提交失败，请重新尝试！");
      }
    },
    toExit() {
      this.$confirm(
        "请确保当前题卡已经正常保存，确定要退出当前题卡编辑吗?",
        "提示",
        {
          type: "warning",
        }
      )
        .then(() => {
          this.goback();
        })
        .catch(() => {});
    },
    goback() {
      if (this.isDialog) {
        this.$emit("exit", { id: this.cardId, title: this.cardName });
      } else {
        this.$router.go(-1);
      }
    },
  },
  beforeDestroy() {
    this.$ls.remove("cardId");
    this.$ls.remove("prepareTcPCard");
    this.clearSetTs();
  },
};
</script>
