// 单独写上传的处理函数
import { addOrUpdateDisplayTemp } from "@/api/display";
import bizUploadFunctions from "@/utils/bizUploadFunctions";
import bizTransform from "@/utils/bizTransform";
import { file, uploadV1 } from "@/utils/file";
import { Message } from 'element-ui'
const { getNeedUploadFormData, isFileRaw, isFormDataHasData, handleDeleteFiles, getMediaFile } =
  bizUploadFunctions;

const { getDeptIdStr } = bizTransform;

const mediaKeys = ["faceImage", "images", "videos", "audios"];

// 新增和修改提交时表单需要删除的字段，因为后端没有做更新
const needDelete = ['culturalRelicVo', 'imagesVo', 'videosVo', 'audiosVo', 'literatureVo', 'virtualVo', 'literatureVo', 'faceImageMiddleUrl', 'faceImagePressUrl', 'faceImageUrl']

const getUnitData = ($el) => {
  const units = $el.$refs["exhibitionUnits"].getUnitData();
  return units;
};

/**
 * 添加展览单元的媒体文件至formData
 * @param {*} $el 当前this对象
 * @param {FormData} formData 当前this对象
 * @returns {Object} form 表单对象
 */
const getFormDataUnits = ($el, formData) => {
  const units = getUnitData($el);
  appendUnitToForm(units, formData);
  return formData;
};

const appendUnitToForm = (arr, formData) => {
  arr.forEach((item) => {
    if (item.imagesVo && item.imagesVo.length > 0) {
      item.imagesVo.forEach((imgFile) => {
        if (isFileRaw(imgFile)) {
          const { euId } = item;
          const { raw } = imgFile;
          formData.append(`unit-images-${euId}`, raw);
        }
      });
    }
    if (item.children && item.children.length > 0) {
      appendUnitToForm(item.children, formData);
    }
  });
};

/**
 * 上传文件
 * @param {*} $el 当前this对象
 * @returns {Object} form 表单对象
 */
const uploadFile = ($el) => {
  return new Promise(async (resolve, reject) => {
    const formData = getNeedUploadFormData($el, mediaKeys);
    const formDataFull = getFormDataUnits($el, formData);
    try {
      if (isFormDataHasData(formDataFull)) {
        const res = await uploadV1(formDataFull);
        if (res.code == 0) {
          resolve(res);
        } else {
          Message.error('文件上传失败：' + res.msg)
          reject(res.msg)
        }
      } else {
        resolve({});
      }
    } catch (error) {
      reject(error);
    }
  });
};

const getUnitRemovedIds = ($el) => {
  return $el.$refs["exhibitionUnits"].removedIds;
};


//获取布展单元媒体文件中仍然需要保留的文件id
const getUnitExsitedObj = ($el, units) => {
  const obj = {};
  loopUnits(units, obj);
  return obj;
  function loopUnits(arr, obj) {
    arr.forEach((item) => {
      if (item.imagesVo) {
        const { euId } = item;
        const key = `unit-images-${euId}`;
        const ids = item.imagesVo.filter((file) => {
          return !isFileRaw(file);
        }).map(file => {
          return file.fileId
        });
        obj[key] = ids;
      }

      if (item.children && item.children.length > 0) {
        loopUnits(item.children, obj);
      }
    });
  }
};

const getUploadedIdByKey = (key, res) => {
  if (!res.data) {
    return [];
  }
  const items = res.data.filter((item) => {
    return item.fileKey == key;
  });
  if (items.length > 0) {
    return items.map((item) => {
      return item.fileId;
    });
  } else {
    return [];
  }
};
// 获取已经上传了的文件的id集合
const getUnitUploadedObj = ($el, units, res) => {
  const obj = {};
  loopUnits(units, obj, res);
  return obj;
  function loopUnits(arr, obj, res) {
    arr.forEach((item) => {
      // 只有图片长度大于0的才会有新上传的
      if (item.imagesVo && item.imagesVo.length) {
        // 通过key去查找res中的fileId
        const { euId } = item;
        const key = `unit-images-${euId}`;
        const idsArr = getUploadedIdByKey(key, res);
        obj[key] = idsArr;
      }
      if (item.children && item.children.length > 0) {
        loopUnits(item.children, obj, res);
      }
    });
  }
};

/**
 * 获取form中媒体文件最终需要传到后台的文件ID
 * @param {Object} oldObj 遗留的媒体文件id
 * @param {Object} newObj 新添加的文件，上传后回填的 包含所有mediaKeys键名
 * @returns {Object}最终需要传到后台的文件ID
 */
const mergeObjects = (oldObj, newObj) => {
  let result = {};
  for (const key in newObj) {
    const oldArr = oldObj[key] || []
    const newArr = [...oldArr, ...newObj[key]]
    result[key] = newArr
  }
  return result;
};
// 获取最终的布展单元
const getUploadedUnits = ($el, res) => {
  const units = getUnitData($el);
  const exsitedObj = getUnitExsitedObj($el, units);
  const uploadedObj = getUnitUploadedObj($el, units, res);
  //   将存在的和新上传的取交集，因为当key重复时，已存在的会被新上传的覆盖，因此需要再和已存在的进行取并集
  const mergeObj = mergeObjects(exsitedObj, uploadedObj);
  loopUnits(units);
  return units;
  function loopUnits(arr) {
    arr.forEach((item) => {
      const { euId } = item;
      const key = `unit-images-${euId}`;
      if (mergeObj[key] && mergeObj[key].length > 0) {
        item.images = mergeObj[key].join(",");
      } else {
        item.images = ''
      }
      //   处理关联文物
      if (item.crIds && item.crIds instanceof Array) {
        item.crIds = item.crIds.join(",");
      }
      //   删除imagesVo不要传到后台
      delete item.imagesVo;
      if (item.children && item.children.length > 0) {
        loopUnits(item.children);
      }
    });
  }
};

/**
 * 获取表单中仍然还需要保留的媒体文件的文件ID
 * @param {*} $el infoEditDialog的this对象
 * @returns {Object}  形如{faceImage:[1,2,3],imagesVo:[4,5,6]}
 */
const getFormExsitedObj = ($el) => {
  const obj = {};
  mediaKeys.forEach((key) => {
    // 已存在的不为空再继续
    const files = getMediaFile($el, key)
    if (files && files.length > 0) {
      const ids = files.filter((item) => {
        return !isFileRaw(item)
      }).map(item => {
        return item.fileId
      })
      obj[key] = ids
    }
  });
  return obj;
};

// 获取已经上传了的文件的id集合
const getFormUploadedObj = ($el, res) => {
  const obj = {};
  mediaKeys.forEach((key) => {
    // 通过key去查找res中的fileId
    const idsArr = getUploadedIdByKey(key, res);
    // 获取本来还没被删除的id
    obj[key] = idsArr;
  });
  return obj;
};

const getLtStrByArr = (arr) => {
  if (arr.length == 0) {
    return "";
  }
  return arr.join(",");
};

const getStatusNumByBool = (bool) => {
  if (!bool instanceof Boolean) {
    return;
  }
  return bool ? 1 : 0;
};

// 获取最终的展览表单
const getUploadedForm = ($el, res, submitFlag) => {
  const form = JSON.parse(JSON.stringify($el.dialogForm));
  // 不需要上传，仍然需要保留的
  const exsitedObj = getFormExsitedObj($el);
  // 需要新上传的
  const uploadedObj = getFormUploadedObj($el, res);
  //   将存在的和新上传的取交集，因为当key重复时，已存在的会被新上传的覆盖，因此需要再和已存在的进行取并集
  const mergeObj = mergeObjects(exsitedObj, uploadedObj);
  mediaKeys.forEach((key) => {
    form[key] = mergeObj[key].join(",")
  });
  form.literature = getLtStrByArr($el.literatureIdArr); //文献
  form.status = getStatusNumByBool($el.dialogForm.status);
  form.crIds = $el.crIds?.join(",");
  form.bvIds = $el.vrIds?.join(",");
  form.displayCharacter = 1; //传布展
  form.submitFlag = submitFlag;
  form.deptId = getDeptIdStr(form.deptId);
  return form;
};

/**
 *
 * @param {Boolean} submitFlag 上传的类别，是仅保存还是
 * @param {*} $el 当前this对象
 */
const submit = (submitFlag, $el) => {
  $el.submitLoading = true;
  $el.$refs.form.validate(async (valid) => {
    if (valid) {
      try {
        const res = await uploadFile($el);
        if (res.code == 0) {
          const unitsUploaded = getUploadedUnits($el, res);
          const formUploaded = getUploadedForm($el, res, submitFlag);
          const params = {
            ...formUploaded,
            exhibitionUnits: unitsUploaded,
          };
          // 重传时需要加入flowId
          if ($el.flowId) {
            params.flowId = $el.flowId;
          }
          // 删除一些需要删除的字段
          needDelete.forEach(key => {
            delete params[key]
          })
          const unitDeleteIds = getUnitRemovedIds($el)
          const formDeleteIds = $el.removedIds
          const removedIds = [...new Set([...unitDeleteIds, ...formDeleteIds])]
          addOrUpdateDisplayTemp(params)
            .then((res) => {
              if (res.code == 0) {
                setTimeout(() => {
                  $el.$emit("refresh");
                  $el.resetData();
                  $el.submitLoading = false;
                  $el.$message.success("提交成功！");
                  $el.visible = false;
                  handleDeleteFiles(removedIds)
                }, 1000);
              }
            })
            .catch((err) => {
              $el.submitLoading = false;
            });
        }
      } catch (error) {
        console.log(error);
        $el.submitLoading = false;
      }


    }
  });
};

export default submit;
