<template>
  <SysDialog
    class="export-expense"
    :visible="dialog.visible"
    v-bind="getBindValue"
    @onClose="onClose"
  >
    <template #content>
      <el-form ref="exportExpenseRef" :model="stateExpense.form">
        <el-form-item>
          <el-alert type="info" show-icon>
            <div class="info-text">
              相同重量，重量单位，分区会直接覆盖更新
              <br />
              行头为重量段，列头为分区价
              <br />
              可直接复制excel文件报价
              <el-link>
                <el-button
                  link
                  type="primary"
                  @click="hanleOpenDownload"
                  :loading="templateLoading"
                >
                  分区费用模版下载
                </el-button>
              </el-link>
            </div>
          </el-alert>
        </el-form-item>
        <!-- <el-form-item>
          <el-button type="primary" link @click="hanleOpenDownload" :loading="templateLoading">分区费用模版导出</el-button>
        </el-form-item> -->
        <el-form-item label="计量单位" prop="originalCalculateUnit">
          <!-- <el-select v-model="stateExpense.form.originalCalculateUnit" filterable>
            <el-option v-for="item in calculateUnitList" :key="item.value" :value="item.value" :label="item.label" />
          </el-select> -->
          <span>{{ originalCalculateUnitLabel }}</span>
        </el-form-item>
        <el-form-item
          label="算法方式"
          prop="countType"
          :rules="stateExpense.rules"
        >
          <el-select v-model="stateExpense.form.countType" filterable>
            <el-option
              v-for="item in countTypeList"
              :key="item.value"
              :value="item.value"
              :label="item.label"
              @click="hanleClickCountType(item.value)"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          label="详细报价"
          prop="content"
          required
          :rules="stateExpense.rules"
          style="display: block"
        >
          <el-input
            v-model="stateExpense.form.content"
            :autosize="{ minRows: 22, maxRows: 22 }"
            type="textarea"
          />
        </el-form-item>
        <div class="flex justify-end">
          <el-button type="danger" @click="onClose"> 取消 </el-button>
          <el-button type="primary" @click="hanleSetZones"> 确定 </el-button>
        </div>
      </el-form>
    </template>
  </SysDialog>
  <!-- 计算公式-弹框 -->
  <FormulaModle 
    ref="formulaModle" 
    @save="hanleSaveFormula"
  />
</template>
<script lang="ts" setup>
import { ref, reactive, unref, computed, nextTick } from "vue";
import SysDialog from "@/components/SysDialog.vue";
import useDialog from "@/hooks/useDialog";
import { useMessage } from "@/hooks/useMessage";
import type { ListIitem } from "@/api/base/BaseDataModel";
import { useEleFormValidate } from "@/hooks/useEleFormValidate";
import { isArrayLength, isNonNegativeInteger, isNumber } from "@/utils/is";
import { api_DownloadFeeImport } from "@/api/customerfee/customerfeeset";
import { useApiDownTemplate } from "@/hooks/useApiDownTemplate";
import FormulaModle from "@/components/feeset/FormulaModle.vue";
import { BaseFormula } from "@/type/BaseFormula";
import { useDropDownData } from "@/hooks/useDropDownData";

const { parametersList } = useDropDownData()
const { formValidate, resetForm } = useEleFormValidate();
const props = defineProps<{
  zoneList: Recordable; //表格表头
  // calculateUnitList: ListIitem[],//计量单位列表
  countTypeList: ListIitem[]; //算法方式
  feeItemRow: Recordable; //当前行费用设置
  feesetSetingDataSource?: Recordable[]; //当前费用设置数据
  originalCalculateUnit?: ListIitem; //计量单位
}>();
const emit = defineEmits(["saveExpense"]);
const { ElMessageBox, createMessage } = useMessage();
// 模版下载
const { templateLoading, hanleOpenDownload } = useApiDownTemplate(
  api_DownloadFeeImport
);
//弹框属性
const { dialog, onClose, onShow } = useDialog();
// 弹框一些配置
const getBindValue = reactive({
  title: "导入分区费用",
  top: "6vh",
  width: "85%",
  height: 0,
  isFooter: true,
  closeOnClickModal: false,
});
// 表单ref
const exportExpenseRef = ref();
// 计算公式弹窗ref
const formulaModle = ref<{
  show: (unitTypes?: ListIitem[], row?: Recordable) => void;
}>();
// 基础数据
const stateExpense = reactive({
  form: {
    countType: "", //公式类型
    formula: "", //公式符号
    formulaExplain: "", //公式文本
    originalCalculateUnit: 0, //原计量单位
    content: "",
  },
  detailList: [] as Recordable[],
  rules: [{ required: true, message: "请输入内容" }],
});
// 当前费用数据
const currentFeesetState = ref<Recordable>({})
const zoneList = computed(() => props.zoneList);
const feeItemRow = computed(() => props.feeItemRow);
const feesetSetingDataSource = computed(() => props.feesetSetingDataSource);
const originalCalculateUnit = computed(() => props.originalCalculateUnit);
const originalCalculateUnitLabel = computed(() => {
  return props.originalCalculateUnit?.label || "";
});

const show = () => {
  onShow();
  nextTick(() => {
    const feeItemId = unref(feeItemRow).id;
    // 查找当前费用设置数据
    const findObj = unref(feesetSetingDataSource)?.find(
      (item) => item.feeItemId === feeItemId
    );
    if (findObj) {
      currentFeesetState.value = findObj;
      stateExpense.form.countType = findObj.countModel.countType;
      // stateExpense.form.originalCalculateUnit = isNumber(findObj.originalCalculateUnit) ? findObj.originalCalculateUnit : ''
      stateExpense.form.originalCalculateUnit = unref(originalCalculateUnit)
      ?.value as number;
      hanleSaveFormula()
    }
  });
};

// 改变的公式数据
const hanleSaveFormula = () => {
  const data = unref(currentFeesetState)
  if (data && data.countModel) {
    stateExpense.form.formula = data.countModel.formula;
    stateExpense.form.formulaExplain = data.countModel.formulaExplain;
  }
}
// 点击算法方式
const hanleClickCountType = (val: number | string) => {
  if (val === BaseFormula.FORMULA) {
    formulaModle.value?.show(unref(parametersList), unref(currentFeesetState))
  } else {
    stateExpense.form.formula = "";
    stateExpense.form.formulaExplain = "";
  }
}

// 导入费用
const hanleSetZones = async () => {
  const isValidate = await formValidate(exportExpenseRef.value);
  if (!isValidate) return;
  const content = stateExpense.form.content;
  const zoneList_ = unref(zoneList);
  const feeItemRow_ = unref(feeItemRow);
  if (!isNonNegativeInteger(feeItemRow_.id)) {
    createMessage.warning("请添加费用设置中数据，且费用类型不能为空！");
    return false;
  }
  // if (content) {
  // 拆行数据并且过滤
  const itemList = content.split(/[\r\n]+/).filter((item) => item);
  // 表头
  const headers = itemList[0].split("\t");
  // 判断表格是否对齐
  const notAligned = itemList.filter((x) => {
    return x.split("\t").length != headers.length;
  });
  if (notAligned.length > 0) {
    // 表格未对齐
    ElMessageBox.alert(
      "当前报价内容表格未对齐<br/>" + notAligned.join("<br/>"),
      { dangerouslyUseHTMLString: true }
    );
    return false;
  }
  // 判断表格内容是否为全数字
  const regext = /^\d+(\.\d+)?$/;
  const notNumber = itemList.filter((x, i) => {
    return (
      i > 0 &&
      x.split("\t").filter((y) => {
        const t = y ? y.trim() : y;
        return !regext.test(t);
      }).length > 0
    );
  });
  if (notNumber.length > 0) {
    const headerList = itemList[0].split('\t')
    const resultMessage = getNonNumericIndexes(notNumber, headerList)
    ElMessageBox.alert(resultMessage, "当前报价内容非纯数字", {
      dangerouslyUseHTMLString: true,
    });
    return false;
  }
  // 匹配是否可用的分区
  const contentZones: Recordable[] = [];
  for (let i = 1; i < headers.length; i++) {
    // 根据名称查找
    const fzone = zoneList_.filter((y) => y.label == headers[i].trim());
    if (fzone.length == 0) {
      ElMessageBox.alert("当前费用没有包含报价内容中的分区:" + headers[i]);
      return false;
    } else {
      contentZones[i] = fzone[0];
    }
  }
  for (let rowIndex = 1; rowIndex < itemList.length; rowIndex++) {
    // 按行添加
    const row = itemList[rowIndex].split("\t").map(Number);
    // 整合费用明细数据
    const insertDto = {
      originalBeginWeight:
        rowIndex === 1 ? 0 : itemList[rowIndex - 1].split("\t").map(Number)[0], //起始重量
      originalEndWeight: row[0], //结束重量
      originalCalculateUnit: stateExpense.form.originalCalculateUnit, //计量单位
      countModel: {
        countType: stateExpense.form.countType,
        formula: stateExpense.form.formula,
        formulaExplain: stateExpense.form.formulaExplain,
      }, //算法
      feeItemId: feeItemRow_.id,
      feeItemSpecialFlag: feeItemRow_.feeItemSpecialFlag,
      feeItemName: feeItemRow_.itemName,
      id: Math.ceil(Math.random() * 1000000),
    };
    for (let columnIndex = 1; columnIndex < row.length; columnIndex++) {
      // 设置分区值
      const column = contentZones[columnIndex];
      insertDto[column.prop.toString()] = row[columnIndex];
    }
    stateExpense.detailList.push(insertDto);
  }
  ElMessageBox.confirm("是否确定快速导入").then(() => {
    emit("saveExpense", stateExpense.detailList);
    clear();
  });
  // } else {
  //   ElMessageBox.alert("请输入详细报价");
  // }
};

// 获取ElMessageBox.alert显示message
const getNonNumericIndexes = (notNumber, headerList) => {
  if (!isArrayLength(notNumber)) return '暂无数据！'
  const list = notNumber.map(item => 
    item.split('\t').map(value => parseFloat(value.trim()))
  );
  const nonNumericIndexes: Recordable[] = [];
  list.forEach((array, rowIndex) => {
    array.forEach((value, colIndex) => {
      if (value === null || isNaN(value)) {
        nonNumericIndexes.push({ headValue: array[0] || '为空！', rowIndex, colIndex });
      }
    });
  });

  // 按 rowIndex 分组
  const groupedByRow = nonNumericIndexes.reduce((acc, { headValue, rowIndex, colIndex }) => {
    if (!acc[rowIndex]) {
      acc[rowIndex] = [];
    }
    acc[rowIndex].push({ headValue, colIndex });
    return acc;
  }, {});

  const message = Object.entries(groupedByRow).map(([rowIndex, items]) => {
    const rowDetails = items.map(item => `${headerList[item.colIndex]}`).join('、');
    return `公斤/区间名（${items[0].headValue}）: <br/><div style="color: red;">${rowDetails}</div>`;
  }).join('<br/>');
  return message
}

// 清空数据
const clear = () => {
  resetForm(exportExpenseRef.value);
  stateExpense.detailList = [];
  currentFeesetState.value = {};
  onClose();
};

//父组件调用子组件显示弹框
//暴露出去给外部使用
defineExpose({
  show,
});
</script>
<style scoped>
.info-text {
  font-size: 13px;
}
</style>
