<template>
  <form-item-wrapper
    :designer="designer"
    :field="field"
    :rules="rules"
    :design-state="designState"
    :parent-widget="parentWidget"
    :parent-list="parentList"
    :index-of-parent-list="indexOfParentList"
    :sub-form-row-index="subFormRowIndex"
    :sub-form-col-index="subFormColIndex"
    :sub-form-row-id="subFormRowId"
  >
    <div id="uploadImage" class="upload-img" v-if="designState">
      <div
        class="el-upload el-upload--picture"
        style="vertical-align: middle; display: inline-block; float: left"
      >
        <button type="button" class="avatar-uploader">
          <i class="el-icon-plus avatar-uploader-icon"></i>
        </button>
      </div>
    </div>
    <template v-else>
      <div id="uploadImage" class="widgetSize2">
        <div
          class="upload-list"
          model="singer"
          v-for="(attachment, index) in fieldModel"
          :key="index"
          style="display: inline-block; vertical-align: middle; float: left"
        >
          <div class="upload-box">
            <ul class="el-upload-list el-upload-list--picture">
              <li tabindex="0" class="el-upload-list__item">
                <div>
                  <div class="el-upload-list__item-thumbnail">
                    <div
                      class="show-video"
                      v-if="hasPreview(attachment)"
                      @click="openPreview(attachment, index)"
                    >
                      <i class="icon-chakan"></i>
                    </div>
                    <p>
                      <el-image
                        :src="getShowUrl(attachment)"
                        @click="openPreview(attachment, index)"
                        :z-index="999999"
                      />
                    </p>
                  </div>
                  <div class="el-upload-list__item-name">
                    <el-tooltip
                      :enterable="false"
                      class="item"
                      effect="dark"
                      :content="attachment.name"
                      placement="top"
                    >
                      <p v-if="$attrs.hideName !== true">
                        {{ attachment.name }}
                      </p>
                    </el-tooltip>
                  </div>
                  <div class="el-upload-list__item-status-label">
                    <i class="el-icon-upload-success el-icon-check"></i>
                  </div>
                  <div
                    class="el-icon-close"
                    @click="deleteFile(index)"
                    v-if="!field.options.disabled && !field.options.hideRemoveButton"
                  >
                    <i
                      class="el-tooltip iconfont iconshanchu"
                      aria-describedby="el-tooltip-6144"
                      tabindex="0"
                    ></i>
                  </div>
                  <div class="el-icon-tagEdit">
                    <el-tooltip
                      class="item"
                      effect="dark"
                      :content="$t2('下载', 'system.button.download')"
                      placement="top"
                    >
                      <i class="el-icon-download" @click="downloadFile(attachment)"></i>
                    </el-tooltip>
                  </div>
                </div>
              </li>
            </ul>
          </div>
        </div>
        <div
          v-if="!field.options.disabled"
          class="el-upload el-upload--picture"
          style="vertical-align: middle; display: inline-block; float: left"
        >
          <el-upload
            ref="upload"
            class="upload-demo"
            action="https://jsonplaceholder.typicode.com/posts/"
            :http-request="uploadSectionFile"
            :limit="1"
          >
            <button type="button" class="avatar-uploader">
              <i class="el-icon-plus avatar-uploader-icon"></i>
            </button>
            <div slot="file" slot-scope="{ file }"></div>
          </el-upload>
        </div>
      </div>
      <el-image-viewer
        v-if="showViewer"
        :on-close="closeViewer"
        :initial-index.sync="chooseIndex"
        :url-list="imageRows"
      />
    </template>
  </form-item-wrapper>
</template>

<script>
import FormItemWrapper from "./form-item-wrapper";
import emitter from "../../../../../components/xform/utils/emitter";
import i18n from "../../../../../components/xform/utils/i18n";
import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";

export default {
  name: "vabUpload2-widget",
  componentName: "FieldWidget", //必须固定为FieldWidget，用于接收父级组件的broadcast事件
  mixins: [emitter, fieldMixin, i18n],
  props: {
    field: Object,
    parentWidget: Object,
    parentList: Array,
    indexOfParentList: Number,
    designer: Object,

    designState: {
      type: Boolean,
      default: false,
    },

    subFormRowIndex: {
      /* 子表单组件行索引，从0开始计数 */ type: Number,
      default: -1,
    },
    subFormColIndex: {
      /* 子表单组件列索引，从0开始计数 */ type: Number,
      default: -1,
    },
    subFormRowId: {
      /* 子表单组件行Id，唯一id且不可变 */ type: String,
      default: "",
    },
    responseAdapter: {
      type: Function,
      default(responseData, file) {
        // 默认适配器：假设返回格式为
        /* {
          "code": 1000,
          "message": "ok",
          "data": "{\"name\":\"8aafaaad-f033-4f46-a8f3-fe2639204f6a-source.jpg\",\"size\":186847,\"date\":1754711199966,\"id\":\"f3056c29-f65a-4d1b-8778-c2df5fa53775\",\"filename\":\"f3056c29-f65a-4d1b-8778-c2df5fa53775.jpg\",\"user\":\"1\",\"type\":\"工单\",\"url\":\"\"}"
        } */
        let data = null;
        if (responseData.code === 1000 && responseData.data) {
          data = JSON.parse(responseData.data);
        }
        return {
          success: responseData.code === 1000,
          // url: responseData.objx?.url,
          message: responseData.message || "success",
          fullResponse: responseData,
          data: data,
        };
      },
    },
  },
  components: {
    FormItemWrapper,
    ElImageViewer: () => import("@base/components/VabUpload/image-viewer"),
  },
  inject: ["refList", "globalOptionData", "globalModel", "getFormConfig"],
  data() {
    return {
      oldFieldValue: [], //field组件change之前的值
      fieldModel: [],
      rules: [],
      isH5: false,

      uploadUrl: null,

      token: null,
      deleteUrl: null,
      viewApiUrl: null,
      imageMap: {},
      imageRows: [],
      chooseIndex: -1,
      showViewer: false,
    };
  },
  watch: {
    fieldModel(val) {
      this.handleChangeEvent(val);
    },
  },
  computed: {
    formDataId() {
      let formRef = this.getFormRef();
      return formRef.dataId;
    },
  },
  beforeCreate() {
    /* 这里不能访问方法和属性！！ */
  },

  created() {
    /* 注意：子组件mounted在父组件created之后、父组件mounted之前触发，故子组件mounted需要用到的prop
       需要在父组件created中初始化！！ */

    this.isH5 = this.getFormConfig().layoutType === "H5";

    this.initFieldModel();
    this.registerToRefList();
    this.initEventHandler();
    this.buildFieldRules();

    this.handleOnCreated();
  },

  mounted() {
    this.initUploadInfo();
    this.handleOnMounted();
  },

  beforeDestroy() {
    this.unregisterFromRefList();
  },
  methods: {
    //begin
    closeViewer() {
      this.showViewer = false;
    },
    hasPreview(attachment) {
      return this.$commonFileUtil.isPictureFile(attachment.filename);
    },
    openPreview(attachment, index) {
      /* let typeStr = Object.prototype.toString.call(attachment);
      let url =
        typeStr == "[object Object]" ? attachment.domain + attachment.url : attachment; */
      if (this.$commonFileUtil.isPictureFile(attachment.filename)) {
        this.openImagePreView(index);
      }
    },
    openImagePreView(index) {
      // this.chooseIndex = index;
      let pictureIndex = -1;
      let rows = [];

      this.fieldModel.forEach((item, i) => {
        if (this.$commonFileUtil.isPictureFile(item.filename)) {
          rows.push(item.showUrl);
        }
      });
      this.fieldModel.find((item, i) => {
        if (this.$commonFileUtil.isPictureFile(item.filename)) {
          pictureIndex++;
        }
        return index == i;
      });
      let attachment = this.fieldModel[index];
      const toDo = () => {
        this.chooseIndex = 0;
        this.imageRows = [attachment.showUrl];
        this.showViewer = true;
      };

      if (!attachment.showUrl) {
        this.initShowImageUrl(attachment, () => {
          toDo();
        });
      } else {
        toDo();
      }
    },
    getAttachmentName(attachment) {
      let name = null;
      let typeStr = Object.prototype.toString.call(attachment);
      if (typeStr == "[object Object]") {
        name = attachment.name;
      } else {
        let url = attachment;
        if (url) {
          var i = url.lastIndexOf("/");
          if (i >= 0) {
            name = url.substring(i + 1, url.length);
          }
        }
      }
      return name;
    },
    getShowUrl(attachment) {
      return this.$commonFileUtil.getFileIconRequire(attachment.filename);
      /* if (this.$commonFileUtil.isPictureFile(attachment.name)) {
        return attachment.showUrl;
      } else {
        return this.$commonFileUtil.getFileIconRequire(attachment.name);
      } */
    },
    initShowUrl() {
      let rows = this.fieldModel;
      rows.forEach((row) => {
        if (!row.showUrl) {
          this.initShowImageUrl(row);
        }
      });
    },
    deleteFile(index) {
      let attachment = this.fieldModel[index];
      let filename = attachment.filename;
      if (!filename || !this.deleteUrl) return;
      let entityId = this.formDataId;

      let reqData = {
        entityName: "msdyn_workorder",
        entityId,
        backendwriteback: "10",
      };

      let param = {
        row: attachment,
        rowIndex: index,
      };
      let deleteParam =
        this.handleCustomEvent(
          this.field.options.vabupload2_deleteParam,
          ["param"],
          [param]
        ) || {};
      Object.assign(reqData, deleteParam);

      // let url = this.deleteUrl + "?fileName=" + filename;

      var form = new FormData();
      form.append("fileName", filename);
      Object.keys(reqData).forEach((key) => {
        let value = reqData[key];
        form.append(key, value);
      });

      this.getFormRef().$http({
        url: this.deleteUrl,
        method: "post",
        // data: reqData,
        data: form,
        // responseType: "RAW",
        headers: {
          // "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
          "Content-Type": "multipart/form-data",
          Authorization: `Bearer ${this.token}`,
        },
        useToken: false,
        // responseType: "blob",
        resultType: "other",
        isLoading: true,
        callback: (res, response) => {
          if (res.code === 1000) {
            this.fieldModel.splice(index, 1);
          } else {
            this.$baseAlert(res.message);
          }
        },
      });
    },
    getDownloadName(attachment){
      let suffix = this.$commonFileUtil.getFileSuffix(attachment.filename)
      let fileName = attachment.name;
      if(fileName.lastIndexOf(`.${suffix}`)<0){
        fileName = fileName + "." + suffix;
      }
      return fileName
    },
    downloadFile(attachment) {
      const toDo = () => {
        const a = document.createElement("a");
        a.download = this.getDownloadName(attachment);
        a.href = attachment.showUrl;
        a.click();
      };
      if (!attachment.showUrl) {
        this.initShowImageUrl(attachment, () => {
          toDo();
        });
      } else {
        toDo();
      }

      // this.$commonFileUtil.downloadFile(attachment.showUrl);
    },
    initUploadInfo() {
      if(this.designState)return
      this.getHxFileUploadConfig({
        success: (res) => {
          // {"apiToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5YzcyNTE5OS00NDdlLTQ5OTMtOGRjYy1iMWM2NjY0YmJhNDAiLCJuYW1lIjoiOWM3MjUxOTktNDQ3ZS00OTkzLThkY2MtYjFjNjY2NGJiYTQwIiwibmJmIjoxNzU0NjE1ODE1LCJleHAiOjE3NTQ3MDIyMTUsImlzcyI6IlB3YyIsImF1ZCI6IkFTLkNSTS5TZXJ2aWNlLkFwaSJ9.CX2oy7P2PPwCPy-UdhNGaTiSfBHUiVgeK13N91NRcMc","domain":"https://crm-dev.hisense.com","uploadApi":"/api/v1.0/fileoperation/UploadFilesFromPortal","deleteApi":"/api/v1.0/fileoperation/delfile"}
          let objx = res.objx || {};
          let token = objx.apiToken;
          if (token) {
            this.token = token;
            this.uploadUrl = objx.domain + objx.uploadApi;
            this.deleteUrl = objx.domain + objx.deleteApi;
            // https://crm-dev.hisense.com/api/v1.0/fileoperation/GetFile?fileName=e24a1ad9-6821-41c3-957c-0916077bb97f.jpg
            this.viewApiUrl = objx.domain + objx.viewApi;
            // this.initShowUrl();
            // this.initCustomConfig();
          }
        },
      });
    },
    getHxFileUploadConfig(option) {
      let scriptCode =
        this.field.options.vabupload2_scriptCode || "/intf/getHxFileUploadConfig";
      return this.formHttp({
        scriptCode,
        data: {},
        ...option,
      });
    },
    initHttpToekn() {
      return this.getHxFileUploadConfig({
        success: (res) => {
          // {"apiToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5YzcyNTE5OS00NDdlLTQ5OTMtOGRjYy1iMWM2NjY0YmJhNDAiLCJuYW1lIjoiOWM3MjUxOTktNDQ3ZS00OTkzLThkY2MtYjFjNjY2NGJiYTQwIiwibmJmIjoxNzU0NjE1ODE1LCJleHAiOjE3NTQ3MDIyMTUsImlzcyI6IlB3YyIsImF1ZCI6IkFTLkNSTS5TZXJ2aWNlLkFwaSJ9.CX2oy7P2PPwCPy-UdhNGaTiSfBHUiVgeK13N91NRcMc","domain":"https://crm-dev.hisense.com","uploadApi":"/api/v1.0/fileoperation/UploadFilesFromPortal","deleteApi":"/api/v1.0/fileoperation/delfile"}
          let objx = res.objx || {};
          let token = objx.apiToken;
          if (token) {
            this.token = token;
          }
        },
      });
    },
    initCustomConfig() {
      // let paramCode = this.moduleType;
      let paramCode = "haixin";
      this.getFormRef().$http({
        url: USER_PREFIX + "/logic_param/getParamValue",
        method: "post",
        data: {
          paramCode,
          paramType: 2,
        },
        success: (res) => {
          let logic_param = res.objx;
          let customConfig = logic_param?.paramValue
            ? JSON.parse(logic_param.paramValue)
            : null;
          this.customConfig = customConfig;
        },
      });
    },
    generateId() {
      return Math.floor(
        Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000
      );
    },
    //自定义上传
    async uploadSectionFile(param, isCustom, uploadConfig) {
      let customConfig = this.customConfig || {};
      let customEnabled = this.customEnabled || false;
      /* if (customEnabled && !this.uploadUrl) {
        if(customConfig.uploadUrl){
          this.uploadUrl = customConfig.uploadUrl;
        }else{
          await this.initUploadUrl();
        }

      } */
      let that = this;
      var fileObj = param.file;

      let source;

      var form = new FormData();
      // 文件对象
      form.append("file", fileObj);

      let customParam = {};
      let entityId = this.formDataId;
      customParam = {
        fileName: fileObj.name,
        entityName: "msdyn_workorder",
        entityId,
        backendwriteback: "10",
        fileCategory: "工单",
        user: window.$vueRoot.$store.getters.nickName,
        // user: "1",
      };
      let uploadParam =
        this.handleCustomEvent(this.field.options.vabupload2_uploadParam) || {};
      Object.assign(customParam, uploadParam);
      if (customParam) {
        Object.keys(customParam).forEach((key) => {
          let value = customParam[key];
          form.append(key, value);
        });
      }

      let target = that.$refs.upload;
      let file = target ? target.getFile(fileObj) : null;
      if (file) {
        file.status = "uploading";
      }

      let isLoading = uploadConfig?.isLoading === true;
      var uploadUrl = this.uploadUrl;
      target.clearFiles();
      if (uploadUrl) {
        var abort;

        let config = {
          useToken: false,
          isLoading: true,
          headers: {
            "Content-Type": "multipart/form-data",
            Authorization: `Bearer ${this.token}`,
          },
          /*  cancelToken: new imFun.axios.CancelToken(function executor(c) {
            if (!isCustom) {
              abort = c;
              if (file) file.abort = c;
            }
          }), */
          onUploadProgress: (progressEvent) => {
            if (isCustom || file) {
              // progressEvent.loaded:已上传文件大小
              // progressEvent.total:被上传文件的总大小
              progressEvent.percent = Math.floor(
                (progressEvent.loaded * 100) / progressEvent.total
              );
            }
          },
          failMsg: false,
        }; //添加请求头

        if (customEnabled && config?.httpConfig) {
          config = extendDeeply(config, config.httpConfig);
        }

        let req = this.getFormRef()
          .$http.post(uploadUrl, form, config)
          .then((res1) => {
            uploadConfig && uploadConfig.callback && uploadConfig.callback(res1, fileObj);

            const adaptedResponse = this.responseAdapter(res1);

            if (!isCustom) {
              if (adaptedResponse.success) {
                // this.initShowImageUrl(adaptedResponse.data)
                if (adaptedResponse.data) {
                  let fileInfo = {
                    ...adaptedResponse.data,
                    showUrl: null,
                  };
                  this.fieldModel.push(fileInfo);
                  // this.initShowUrl();
                }
              } else {
                // param.onError(new Error(res1.content || '上传异常'));
                this.$baseAlert(adaptedResponse.message);
              }
            }
          });
      }
    },
    initShowImageUrl(attachment, callback) {
      let filename = attachment.filename;
      if (!filename || !this.viewApiUrl) return;
      this.getFormRef().$http({
        url: this.viewApiUrl + filename,
        method: "get",
        data: {},
        // responseType: "RAW",
        headers: {
          // "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
          Authorization: `Bearer ${this.token}`,
        },
        useToken: false,
        responseType: "blob",
        resultType: "other",
        isLoading: true,
        callback: (res, response) => {
          if (res.type === "application/json") {
            let reader = new FileReader();
            reader.readAsText(res, "utf-8");
            reader.onload = (e) => {
              // JSON.parse(reader.result) 转译后的json数据
              let result = JSON.parse(reader.result);
              this.$baseAlert(result.message);
              // 处理相关逻辑...
            };
          } else {
            const blobUrl = window.URL.createObjectURL(res);
            attachment.showUrl = blobUrl;
            attachment.url = blobUrl;
            callback && callback();
          }
        },
      });
    },
    //end

    setValue(val) {
      let data = val || [];
      data.forEach((item) => {
        if (!item.hasOwnProperty("showUrl")) {
          item.showUrl = null;
        }
      });
      this.fieldModel = data;
      this.getFormRef().formDataModel[this.fieldKeyName] = data;
      this.initShowUrl();
    },

    submitFile(rows, fileInfos) {
      // this.handlLineCode(fileInfos);
      let eventParamNames = ["attachments", "fileInfos"];
      let eventParamValues = [rows, fileInfos];
      this.handleCustomEvent(
        this.field.options.onAfterConfirmFile,
        eventParamNames,
        eventParamValues
      );
    },
    setValueByUrl(fileUrl) {
      let value = [];
      if (fileUrl) {
        let row = this.parseFileUrl(fileUrl);
        if (row) {
          value.push(row);
        }
      }
      this.setValue(value);
    },
    parseFileUrl(fileUrl) {
      if (!fileUrl) return null;
      let result = null;

      // 输入校验
      if (typeof fileUrl !== "string") {
        throw new TypeError("输入必须是字符串格式");
      }
      if (!fileUrl.trim()) {
        throw new Error("URL不能为空");
      }

      // 基本URL格式验证
      const urlRegex = /^(https?:\/\/)?([\w.-]+)(:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$/i;
      if (!urlRegex.test(fileUrl)) {
        throw new Error("无效的URL格式");
      }

      // 提取域名部分
      const domainRegex = /^(https?:\/\/[^\/]+)/i;
      const domainMatch = fileUrl.match(domainRegex);
      if (!domainMatch) {
        throw new Error("URL缺少协议或域名部分");
      }
      const domain = domainMatch[0];

      // 提取完整路径
      const url = fileUrl.substring(domain.length);
      if (!url || url === "/") {
        throw new Error("URL缺少文件路径部分");
      }

      // 提取带扩展名的文件名
      const filenameRegex = /[^\/]+$/;
      const filenameMatch = url.match(filenameRegex);
      if (!filenameMatch) {
        throw new Error("无法从路径中提取文件名");
      }
      const fullFilename = filenameMatch[0];

      // 验证文件名格式（至少1字符+扩展名）
      const nameFormat = /^.+\..+$/;
      if (!nameFormat.test(fullFilename)) {
        throw new Error(`无效的文件名格式: ${fullFilename}`);
      }

      // 修复点：更可靠的文件名和扩展名分离
      const lastDotIndex = fullFilename.lastIndexOf(".");
      const filenameBase = fullFilename.substring(0, lastDotIndex); // 点之前部分
      const extension = fullFilename.substring(lastDotIndex + 1).toLowerCase(); // 点之后部分

      // 扩展名验证
      /* const validExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'];
    if (!validExtensions.includes(extension)) {
      throw new Error(`不支持的扩展名类型: ${extension}`);
    } */

      let thumbnail = null,
        large = null,
        medium = null,
        source = null;
      if (this.$commonFileUtil.isPicture(extension)) {
        thumbnail = url;
        large = url;
        medium = url;
        source = url;
      }

      result = {
        extension,
        domain,
        url,
        thumbnail,
        large,
        medium,
        source,
        name: fullFilename,
      };

      // 返回结构化对象
      return result;
    },
  },
};
</script>

<style lang="scss" scoped>
@import "~@/styles/global.scss"; //* form-item-wrapper已引入，还需要重复引入吗？ *//

.full-width-input {
  width: 100% !important;
}

.hideUploadDiv {
  ::v-deep div.el-upload--picture-card {
    /* 隐藏最后的图片上传按钮 */
    display: none;
  }

  ::v-deep div.el-upload--text {
    /* 隐藏最后的文件上传按钮 */
    display: none;
  }

  ::v-deep div.el-upload__tip {
    /* 隐藏最后的文件上传按钮提示 */
    display: none;
  }
}
</style>
