<script setup lang="ts">
import { computed, ref, unref, watch } from "vue";
import { dayjs, ElForm, ElInput, ElMessage, UploadProps } from "element-plus";
import { useResponseHandle } from "/@/hooks/core/useAsync";
import { httpImageUpload, baseUrl } from "/@/api/other";
import { useUserStore } from "/@/store/modules/user";
import { ticketFormItems } from "../config/_details";
import { INPUT_MAX_LENGTH } from "/@/utils/global";
import { cg_inv_type_list } from "/@/utils/status";
import { invoceRules } from "../config/_rules";

const emit = defineEmits(["change"]);

const visible = ref(false);
const fileList = ref([]);

//支持的图片格式
const imgs = ref<any[]>([]);
const invType = ref("1");
const loading = ref(false);
const types = ["png", "jpg", "bmp", "jpeg"].map(format => "image/" + format);
const rules = ref({ ...invoceRules });
const formRef = ref<InstanceType<typeof ElForm>>(null);
const showScanInput = computed(() => invType.value === "1");
const scanInputValue = ref("");
const formData = ref<Record<string, string>>({
  currentValue: ""
});

const userStore = useUserStore();
const responseHandle = useResponseHandle();
const electronicsHiddens = ["invCode", "checkNumber"];
const formItems = computed(() => ticketFormItems[invType.value] || []);

//图片上传前判断类型大小尺寸
const onBeforeReturnImageUpload: UploadProps["beforeUpload"] = ({
  type,
  size
}) => {
  if (!types.includes(type)) {
    ElMessage.error("请上传jpg.png.bmp.jpeg类型图片");
    return false;
  }

  if (size / 1024 / 1024 > 1) {
    ElMessage.error("图片大小超过1M");
    return false;
  }
};

function handleClose() {
  imgs.value = [];
  fileList.value = [];
  formData.value = {};
}

//保存采购回票
function handleSave() {
  formRef.value.validate(async isValid => {
    if (!isValid) return;
    if (!invType.value) return ElMessage.error("请选择申请类型");

    if (invType.value === "2") {
      if (!imgs.value.length) return ElMessage.error("请选择上传的图片");
      if (imgs.value.length > 100)
        return ElMessage.error("上传图片不能超过100张");
    }

    emit(
      "change",
      invType.value === "2"
        ? imgs.value
        : {
            ...unref(formData),
            invType: unref(invType)
          }
    );

    visible.value = false;
  });
}

function handlCurrentSave() {
  formRef.value.validate(async isValid => {
    if (!isValid) return;
    if (!invType.value) return ElMessage.error("请选择申请类型");

    if (invType.value === "2") {
      if (!imgs.value.length) return ElMessage.error("请选择上传的图片");
      if (imgs.value.length > 100)
        return ElMessage.error("上传图片不能超过100张");
    }

    emit(
      "change",
      invType.value === "2"
        ? imgs.value
        : {
            ...unref(formData),
            invType: unref(invType)
          }
    );

    formData.value = {};
  });
}

function handleScanKeydown(evt: KeyboardEvent) {
  const { keyCode } = evt;

  if (keyCode !== 13) return;

  //校验扫描枪值是否含有中文逗号
  if (scanInputValue.value.indexOf("，") >= 0) {
    ElMessage.error("不能包含中文逗号");
    return (scanInputValue.value = "");
  }

  const result = scanInputValue.value.split(",");

  if (result.length !== 8 && result.length !== 9) {
    ElMessage.error("扫码枪识别数据格式不正确,请重新扫描。");
    return;
  }

  let [_, invoiceType, ...chunks] = result;
  const [invCode, invNumber, subtotal_amount, open_time, checkNumber] = chunks;

  let _open_time = "";
  if (open_time) {
    const year = open_time.slice(0, 4);
    const month = open_time.slice(4, 6);
    const day = open_time.slice(6);
    _open_time = dayjs(`${year}-${month}-${day}`).format("YYYY-MM-DD HH:mm:ss");
  }

  formData.value = {
    invoiceType,
    invCode,
    subtotal_amount,
    open_time: _open_time,
    invNumber,
    checkNumber
  };

  scanInputValue.value = "";
}

const is_Electronics = computed(() => {
  const { invoiceType } = formData.value;
  return invoiceType === "32" || invoiceType === "31";
});

const handleRequeset: UploadProps["httpRequest"] = async ({ file }) => {
  const _formData = new FormData();
  _formData.append("img", file);
  _formData.append("token", userStore.token);
  const { message, code, data } = await httpImageUpload(_formData);

  responseHandle({
    message,
    code,
    handler: () => {
      data.forEach(({ url, name }) => {
        imgs.value.push({
          inv_img: baseUrl + "/" + url,
          invName: name,
          invType: "2"
        });
      });
    }
  });
};

const handleRemove = uploadFile => {
  const delIndex = fileList.value.findIndex(
    ({ uid }) => uid === uploadFile.uid
  );
  imgs.value.splice(delIndex, 1);
  return true;
};

watch(
  () => formItems.value,
  newVal => {
    const newFormData: Record<string, string> = {};
    newFormData.payNo = formData.value.payNo;
    newVal.forEach(item => {
      if (item.prop !== "payNo") newFormData[item.prop] = "";
    });
    formData.value = newFormData;
  }
);

watch(
  () => formData.value.invoiceType,
  () => {
    if (rules.value.checkNumber) {
      rules.value.checkNumber[0].required = ["04", "10"].includes(
        formData.value.invoiceType
      );
    }
  }
);

const disabledDate = time => {
  return time.getTime() > Date.now();
};

defineExpose({
  onDisplay: () => (visible.value = true)
});

electronicsHiddens;
</script>

<template>
  <el-dialog v-model="visible" @close="handleClose" title="上传发票" center>
    <el-form
      label-width="100px"
      :model="formData"
      :rules="rules"
      ref="formRef"
      size="small"
    >
      <!-- <el-form-item label="发票上传方式">
        <el-select v-model="invType" disabled>
          <el-option label="手工添加" value="1" />
          <el-option label="ocr识别" value="2" />
        </el-select>
      </el-form-item> -->

      <!-- 扫码枪识别 -->
      <el-form-item label="扫码枪" v-if="showScanInput">
        <el-input
          type="textarea"
          placeholder="请在扫码完成后手动回车"
          @keydown="handleScanKeydown"
          v-model="scanInputValue"
          v-bind="INPUT_MAX_LENGTH"
        />
      </el-form-item>

      <template v-for="(item, index) in formItems" :key="index">
        <el-form-item
          v-if="
            !is_Electronics ||
            (is_Electronics && !electronicsHiddens.includes(item.prop))
          "
          :label="
            is_Electronics && item.prop === 'subtotal_amount'
              ? '税后金额'
              : item.label
          "
          :prop="item.prop"
        >
          <template v-if="item.prop === 'invoiceType'">
            <el-select
              v-model="formData[item.prop]"
              placeholder="请选择发票类型"
              w-750px
            >
              <el-option
                v-for="(type, index) in cg_inv_type_list"
                :label="type.label"
                :value="type.scanValue"
                :key="index"
              />
            </el-select>
          </template>

          <template v-else-if="item.prop === 'inv_img'">
            <div w-full>
              <el-upload
                class="upload-demo"
                v-model:file-list="fileList"
                :before-upload="onBeforeReturnImageUpload"
                :before-remove="handleRemove"
                :http-request="handleRequeset"
                multiple
              >
                <el-button type="primary">上传图片</el-button>
              </el-upload>
            </div>
          </template>

          <template v-else-if="item.prop === 'open_time'">
            <el-date-picker
              v-model="formData[item.prop]"
              :disabled-date="disabledDate"
              value-format="YYYY-MM-DD HH:mm:ss"
              placeholder="请输入开票日期"
            />
          </template>

          <template v-else>
            <el-input v-model="formData[item.prop]" v-bind="INPUT_MAX_LENGTH" />
          </template>
        </el-form-item>
      </template>

      <el-form-item>
        <div class="justify-end flex w-full">
          <el-button type="primary" :loading="loading" @click="handlCurrentSave"
            >保存当前发票</el-button
          >

          <el-button type="primary" :loading="loading" @click="handleSave"
            >保存并关闭</el-button
          >
        </div>
      </el-form-item>
    </el-form>
  </el-dialog>
</template>

<style lang="scss" scoped>
.upload {
  width: 178px;
  height: 178px;
  display: block;
  border: 1px dashed var(--el-border-color);

  .icon {
    font-size: 24px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
  }

  .text {
    font-size: 20px;
    line-height: 178px;
    width: 178px;
    text-align: center;
  }

  &:hover {
    border-color: #409eff;
  }
}
</style>
