<template>
  <el-dialog :append-to-body="appendToBody" class="dialog" title="数据查询" :model-value='visible' @close="close"
             v-bind="dialogBig" :draggable="false">
    <div class="data-check-dialog">
      <div class="data-check-head">
        <el-form :model='formContent' label-width="auto" class="form-three ">
          <el-form-item label="检测脚本">
            <el-input v-model='formContent.scriptName' :disabled="true"/>
          </el-form-item>
          <el-form-item label="误差体系">
            <el-input v-model='formContent.errorSysName' :disabled="true"/>
          </el-form-item>
          <el-form-item label="数据原则">
            <el-input v-model='formContent.dataRule' :disabled="true"/>
          </el-form-item>
          <el-form-item label="设备名称">
            <el-input v-model='formContent.deviceName' :disabled="true"/>
          </el-form-item>
          <el-form-item label='通道号'>
            <el-select v-model="formContent.chnNum">
              <el-option v-for="item in chnList" :key="item.value" :label="item.label" :value="item.value"/>
            </el-select>
          </el-form-item>
        </el-form>
      </div>

      <div class="data-check-body">
        <div class="content-left-tree">
          <div style="width: 99%;">
            <el-input
                placeholder='请输入测试项名称'
                clearable
                v-model='searchValue'
            ></el-input>
          </div>
          <div class="content-tree">
            <el-tree :filter-node-method='filterNode' :highlight-current="true" :default-expanded-keys="defaultExpandedKeys"
                     node-key="index"
                     :data="treeDataAll"
                     :props="defaultProps"
                     @node-click="handleNodeClick" class="custom-tree" ref="treeRef">
              <template #default="{ node, data }">
                <el-tooltip effect="dark" :content="data.scriptTypeName" placement="top">
                  <span class="custom-tree-node" :style="data.fly===2? 'color: #F56C6C;':data.fly===4? 'color: #e6a23c;':''">{{
                      data.scriptTypeName
                    }}</span>
                </el-tooltip>
              </template>
            </el-tree>
          </div>
        </div>

        <div class="content-right">
          <div class="content-right-title">
            <div style="width: 750px;">
              <span class="content-right-title-text">当前检测项目：
                  <el-popover trigger="hover" :content="currentDesc" :width="popoverWidth" placement="right">
                    <template #reference>
                      <el-button type="text" style="font-size: 14px;">
                        {{ currentScriptTypeName }}
                      </el-button>
                    </template>
                  </el-popover>
              </span>
            </div>
            <!--            <el-form-item style="margin-left: 0px;margin-bottom:0px !important;width: 210px;" v-if="harmNumList.length" label='次数'>-->
            <!--              <el-select v-model="currentHarmNum">-->
            <!--                <el-option v-for="item in harmNumList" :key="item.value" :label="item.label" :value="item.value"/>-->
            <!--              </el-select>-->
            <!--            </el-form-item>-->
            <el-form-item style="margin-left: 0px;margin-bottom:0px !important;width: 230px;" v-if="checkList.length" label='测试项'>
              <el-select v-model="currentCheckItem">
                <el-option v-for="item in checkList" :key="item.value" :label="item.label" :value="item.value"/>
              </el-select>
            </el-form-item>
          </div>
          <div class="content-right-Tabs">
            <el-tabs type="border-card" v-model="activeTab">
              <el-tab-pane label="检测结果" name="resultTab">
                <DataCheckResultTable :tableData="checkResultData" :currentScriptTypeName="currentScriptTypeName"/>
              </el-tab-pane>
              <el-tab-pane label="原始数据" name="rawDataTab">
                <DataCheckRawDataTable :tableData="rawTableData" :currentScriptTypeName="currentScriptTypeName" @exportRawDataHandler="exportRawDataHandler"/>
              </el-tab-pane>
            </el-tabs>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>

</template>
<script setup lang='ts'>
import {dialogBig} from '@/utils/elementBind'
import {reactive, ref, watch} from 'vue'
import DataCheckResultTable from './dataCheckResultTable.vue'
import DataCheckRawDataTable from './dataCheckRawDataTable.vue'
import {CheckData} from "@/api/check/interface";
import {useDictStore} from "@/stores/modules/dict";
import {useCheckStore} from "@/stores/modules/check";
import {getFormData, getTreeData, getTableData} from "@/api/check/test";
import {useDownload} from "@/hooks/useDownload";
import {exportRawData} from "@/api/check/test"

const {appendToBody} = withDefaults(defineProps<{
  appendToBody: boolean
}>(), {appendToBody: true})

const defaultProps = {
  label: "scriptTypeName",
  children: "children",
};

const dictStore = useDictStore()
const checkStore = useCheckStore()

const visible = ref(false)
const treeRef = ref()
const searchValue = ref<string>('')
watch(searchValue, (val) => {
  treeRef.value!.filter(val)
})

// 格式化数字
const fixed = 4;

// 表单数据
const formContent = reactive<CheckData.DataCheck>({
  scriptName: '',
  errorSysName: '',
  dataRule: '',
  deviceName: '',
  chnNum: '',
})
// 当前选中的谐波次数
// const currentHarmNum = ref<string>("-1")
// 谐波次数列表
// const harmNumList = reactive<{ value: string, label: string }[]>([])
// 当前选中的检测项
const currentCheckItem = ref<string>("")
// 检测项列表
const checkList = reactive<{ value: string, label: string }[]>([])

let deviceId: string = ''
let originScriptType: string | null = null
let scriptType: string | null = null

// 通道下拉列表
let chnList: any[] = []


// 左侧树数据
const treeDataAll = reactive<CheckData.TreeItem[]>([])

// 左侧树被选中的叶子节点id
const checkIndex = ref<string>('')

// 当前检测项目名称
const currentScriptTypeName = ref('')
// 当前检测项目描述
const currentDesc = ref('');
// 右侧Tab选中项
const activeTab = ref<string>('resultTab')

//存放相应的表格数据
let resTableData: { resultData: Map<string, any>, rawData: Map<string, any> } = {resultData: new Map(), rawData: new Map()}

// 检测结果表格数据
const checkResultData = reactive<CheckData.CheckResult[]>([])

const popoverWidth: ComputedRef<string> = computed(() => {
  // return `${940 - (currentScriptTypeName.value.length + 7) * 14 - (harmNumList.length || checkList.length ? 160 : 0)}px`
  return `${940 - (currentScriptTypeName.value.length + 7) * 14 - (checkList.length ? 220 : 0)}px`
})


// 原始数据表格数据
const rawTableData = reactive<CheckData.RawDataItem[]>([])

// 左侧树默认展开节点id
let defaultExpandedKeys: string[] = []

const filterNode = (value: string, data: any) => {
  if (!value) return true
  return data.scriptTypeName.includes(value)
}

// 点击左侧树节点触发事件
const handleNodeClick = async (data: any) => {
  if (!data.children) {
    checkIndex.value = data.index
    currentScriptTypeName.value = data.scriptTypeName
    currentDesc.value = data.sourceDesc
    scriptType = data.scriptType ?? scriptType

    if (checkIndex.value) {
      await updateTableData()
      activeTab.value = 'resultTab'
    }
  }
};

watch(() => formContent.chnNum, async (newVal, oldVal) => {
  // console.log("通道号", newVal);

  if (newVal) {
    // 发起请求，查询该测试项的检测结果
    const {data: resTreeDataTemp}: { data: CheckData.TreeItem[] } = await getTreeData({
      scriptId: checkStore.plan.scriptId,
      devId: deviceId,
      devNum: formContent.chnNum + '',
      scriptType: originScriptType,
      code: parseInt(checkStore.plan.code)
    })
    updateTreeFly(resTreeDataTemp, 4)
    updateTreeFly(resTreeDataTemp, 2)

    treeDataAll.length = 0

    Object.assign(treeDataAll, resTreeDataTemp)

    defaultOperate()
    await updateTableData()
  }
  activeTab.value = 'resultTab'
})

// watch(currentHarmNum, (newVal, oldVal) => {
//   console.log("谐波次数", newVal);
//   if (newVal !== '-1') {
//     let resCheckResult: CheckData.ResCheckResult = resTableData.resultData.get(newVal.toString())
//     setCheckResultData(resCheckResult)
//
//     let tempRawData = resTableData.rawData.get(newVal.toString())
//     if (tempRawData) {
//       setRawData(tempRawData)
//     } else {
//       setRawData([])
//     }
//   }
//   activeTab.value = 'resultTab'
// })


watch(currentCheckItem, (newVal, oldVal) => {
  console.log("当前检测项", newVal);
  if (newVal) {
    doCurrentCheckItemUpdate(newVal)
  } else {
    activeTab.value = 'resultTab'
  }
})

// 默认操作
const defaultOperate = () => {
  let node = getDefaultNode(treeDataAll)

  if (node) {
    currentScriptTypeName.value = node.scriptTypeName
    currentDesc.value = node.sourceDesc
    checkIndex.value = node.index
    defaultExpandedKeys = [node.index]

    treeRef.value?.setCurrentKey(node.index);
    scriptType = node.scriptType ?? scriptType
  } else {
    currentScriptTypeName.value = ''
    currentDesc.value = ''
    checkIndex.value = ''
    defaultExpandedKeys = []
  }
}

const updateTableData = async () => {
  // console.log("左侧树被选中的叶子节点checkIndex", checkIndex.value);
  if (checkIndex.value) {
    //  console.log("更新表格数据");
    // 发起请求，查询该测试项的检测结果
    const {data} = await getTableData({
      scriptType,
      scriptId: checkStore.plan.scriptId,
      devId: deviceId,
      devNum: formContent.chnNum + '',
      code: parseInt(checkStore.plan.code),
      index: parseInt(checkIndex.value),
    })

    let keys1 = Object.keys(data.resultData)
    let resultData = new Map()
    for (let key of keys1) {
      resultData.set(key, data.resultData[key])
    }

    let keys2 = Object.keys(data.rawData)
    let rawData = new Map()
    for (let key of keys2) {
      rawData.set(key, data.rawData[key])
    }

    resTableData = {
      resultData,
      rawData
    }

    let resCheckResult: CheckData.ResCheckResult = {}
    let resRawData: CheckData.RawDataItem[] = []

    if (keys1.length === 0) {
      checkList.length = 0
      checkResultData.length = 0
      rawTableData.length = 0
      currentCheckItem.value = ''
    }

    if (keys1.length === 1) {
      resCheckResult = resTableData.resultData.get(keys1[0])
      resRawData = resTableData.rawData.get(keys2[0])

      resRawData = (resRawData == null || resRawData == undefined ? [] : resRawData)
      resCheckResult = (resCheckResult == null || resCheckResult == undefined ? {} : resCheckResult)
      setCheckResultData(resCheckResult)
      setRawData(resRawData)
      checkList.length = 0
      currentCheckItem.value = ''
    } else if (keys1.length != 0) {
      let tempCheckList = []
      for (let [key, value] of resTableData.resultData) {
        let hum = formatHarmNum(key)
        tempCheckList.push({
          value: key,
          label: value.isData === 1 ? hum : value.isData === 4 ? `${hum}（/）` : `${hum}（不符合）`
        })
      }

      toAngleLast(tempCheckList)
      checkList.length = 0
      Object.assign(checkList, tempCheckList)

      if (currentCheckItem.value == tempCheckList[0].value) {
        doCurrentCheckItemUpdate(tempCheckList[0].value)
      } else {
        currentCheckItem.value = tempCheckList[0].value
      }
    }
  }

  // setCheckResultData(resCheckResult)
  else {
    checkResultData.length = 0
    rawTableData.length = 0
  }
}

const doCurrentCheckItemUpdate = (newVal: string) => {
  let resCheckResult: CheckData.ResCheckResult = resTableData.resultData.get(newVal)
  setCheckResultData(resCheckResult)

  let tempRawData = resTableData.rawData.get(newVal)
  if (tempRawData) {
    setRawData(tempRawData)
  } else {
    setRawData([])
  }

  activeTab.value = 'resultTab'
}

const open = async (_deviceId: string, chnNum: string, _scriptType: string | null) => {
  deviceId = _deviceId
  originScriptType = _scriptType
  scriptType = _scriptType

  // 发起后端请求，查询详细信息 当chnNum为-1时，查询所有通道号
  const {data: resFormContent}: { data: any } = await getFormData({
    planId: checkStore.plan.id,
    deviceId,
    chnNum,
    scriptType
  })

  chnList = resFormContent.chnList.map((item: { value: string, label: string }) => ({
    value: item.value,
    label: item.value
    //label: item.label == '1' ? `${item.value}` : item.label == '2' ? `${item.value}（不符合）` : `${item.value}`
  }))

  let dataRuleName = dictStore.getDictData('Data_Rule').find(item => item.id == resFormContent.dataRule)?.name

  Object.assign(formContent, {
    ...resFormContent,
    dataRule: dataRuleName,
    chnNum: chnList.length > 0 ? chnList[0].value : '',
  })


  visible.value = true;
}

const close = () => {
  //数据清空
  Object.assign(formContent, {
    scriptName: '',
    errorSysName: '',
    dataRule: '',
    deviceName: '',
    chnNum: '',
  })
  treeDataAll.length = 0
  // harmNumList.length = 0
  // currentHarmNum.value = '-1'
  currentCheckItem.value = ''
  checkResultData.length = 0
  rawTableData.length = 0
  checkList.length = 0
  defaultExpandedKeys = []
  checkIndex.value = ''
  activeTab.value = 'resultTab'
  currentScriptTypeName.value = ''
  currentDesc.value = ''

  visible.value = false;
};

const setCheckResultData = (data: CheckData.ResCheckResult | null) => {
  // console.log("检测结果", data);
  let result: CheckData.CheckResult[] = []
  if (data == null || data == undefined) {
    Object.assign(checkResultData, [])
    return
  }
  if (data.dataA != null && data.dataB != null && data.dataC != null) {
    result.push({
      stdA: numberToFixed(data.dataA.resultData),
      dataA: numberToFixed(data.dataA.data),
      errorA: getError(data.dataA.resultData, data.dataA.data),
      maxErrorA: toMaxErrorStr(data.dataA.radius, data.unit),
      isDataA: data.dataA.isData,
      stdB: numberToFixed(data.dataB.resultData),
      dataB: numberToFixed(data.dataB.data),
      errorB: getError(data.dataB.resultData, data.dataB.data),
      maxErrorB: toMaxErrorStr(data.dataB.radius, data.unit),
      isDataB: data.dataB.isData,
      stdC: numberToFixed(data.dataC.resultData),
      dataC: numberToFixed(data.dataC.data),
      errorC: getError(data.dataC.resultData, data.dataC.data),
      maxErrorC: toMaxErrorStr(data.dataC.radius, data.unit),
      isDataC: data.dataC.isData,

      maxError: data.radius,
      unit: data.unit,
      result: data.isData,
    })
  }

  if (data.dataT != null) {
    result.push({
      stdT: numberToFixed(data.dataT.resultData),
      dataT: numberToFixed(data.dataT.data),
      errorT: getError(data.dataT.resultData, data.dataT.data),
      maxErrorT: toMaxErrorStr(data.dataT.radius, data.unit),
      isDataT: data.dataT?.isData,

      maxError: data.radius,
      unit: data.unit,
      result: data.isData,
    })
  }
  Object.assign(checkResultData, result)
}

const exportRawDataHandler = () => {
  useDownload(exportRawData, '原始数据.xlsx', {
    scriptType,
    scriptId: checkStore.plan.scriptId,
    devId: deviceId,
    devNum: formContent.chnNum + '',
    code: parseInt(checkStore.plan.code),
    index: parseInt(checkIndex.value),
  }, false, '.xlsx')
}

const formatHarmNum = (num: string) => {
  // debugger
  if (num.includes('.5')) {
    return num
  } else {
    num = num.replace('.0', '')
    return num
  }
}

const setRawData = (data: CheckData.RawDataItem[]) => {
  data.forEach((item: CheckData.RawDataItem) => {
    item.dataA = stringToFixed(item.dataA)
    item.dataB = stringToFixed(item.dataB)
    item.dataC = stringToFixed(item.dataC)
    item.dataT = stringToFixed(item.dataT)
  })
  Object.assign(rawTableData, data)
  console.log("原始数据", rawTableData)
}

const numberToFixed = (num: number): string => {
  if (num == null || num == undefined) {
    return '/'
  } else {
    let result = num.toFixed(fixed)
    if (result === "-0.0000") {
      return result.replace(/-/g, "")
    }
    return result
  }
}

const stringToFixed = (str: string): string => {
  if (str == null || str == undefined) {
    return '/'
  } else {
    let num = Number(str)
    if (isNaN(num)) {
      return '/'
    } else {
      let result = num.toFixed(fixed)
      if (result === "-0.0000") {
        return result.replace(/-/g, "")
      }
      return result
    }
  }
}

const getError = (num1: number, num2: number): string => {
  if (num1 == null || num1 == undefined || num2 == null || num2 == undefined) {
    return '/'
  }
  return Math.abs(Number(numberToFixed(num1)) - Number(numberToFixed(num2))).toFixed(fixed)
}

const toMaxErrorStr = (oldMaxErroe: any, unit: any) => {
  let result = oldMaxErroe ?? '/'
  let idx = result.indexOf('~');
  if (idx > 0) {
    let left = result.substring(0, idx)
    let right = result.substring(idx, result.length)
    result = left + unit + right + unit;
  }
  return result;
}

const findFirstLeafNode = (node: any): any => {
  if (!node.children || node.children.length === 0) {
    return node;
  }

  return findFirstLeafNode(node.children[0]);
}
const getDefaultNode = (data: any[]) => {
  if (!data || data.length === 0) {
    return null;
  }

  const firstElement = data[0];

  return findFirstLeafNode(firstElement);
}

const toAngleLast = (data: any[]) => {
  let angleIndex = -1
  for (let i = 0; i < data.length; i++) {
    if (data[i].value.toString().includes('相角')) {
      angleIndex = i
      break
    }
  }
  if (angleIndex != -1) {
    let temp = data[angleIndex]
    data.splice(angleIndex, 1)
    data.push(temp)
  }
}

// fly: 1合格 2不合格 4数据错误
const filterTree = (treeData: any[], fly: number): any[] => {
  if (!treeData || treeData.length === 0) {
    return []
  }
  filter(treeData, fly)
  return treeData
}

const filter = (treeData: any[], fly: number) => {
  for (let i = treeData.length - 1; i >= 0; i--) {
    let node = treeData[i]
    if (node.fly !== fly) {
      if (node.children && node.children.length > 0) {
        filter(node.children, fly)
        // 检查 children 是否被全部移除
        if (node.children.length === 0) {
          treeData.splice(i, 1);
        }
      } else {
        treeData.splice(i, 1)
      }
    }
  }
}

const updateTreeFly = (treeData: any[], fly: number) => {
  // 递归函数
  function recursiveUpdate(node: any, targetFly: number) {
    //if (!node) return false; // 如果节点不存在，返回 false

    // 如果当前节点是叶子节点且 fly 字段等于 targetFly
    if (!node.children || node.children.length === 0) {
      if (node.fly === targetFly) {
        node.fly = targetFly; // 确保叶子节点的 fly 字段被设置为 targetFly
        return true; // 返回 true 表示找到并更新了
      }
      return false; // 否则返回 false
    }

    // 递归更新子节点
    let updated = false;
    for (let child of node.children) {
      if (recursiveUpdate(child, targetFly)) {
        updated = true;
      }
    }

    // 如果有子节点被更新了，则更新当前节点的 fly 字段
    if (updated) {
      node.fly = targetFly;
    }
    return updated;
  }

  for (let i = 0; i < treeData.length; i++) {
    // 调用递归函数从根节点开始更新
    recursiveUpdate(treeData[i], fly);
  }
}


defineExpose({
  open
})
</script>

<style lang="scss" scoped>

.dialog {
  display: flex;
  flex-direction: column;
  overflow-y: hidden;
  overflow-x: hidden;


  .data-check-dialog {
    display: flex;
    flex-direction: column;
    overflow-y: hidden;

    .data-check-head {
      display: flex;
      flex-direction: row;
      width: 100%;
    }

    .data-check-body {
      height: 500px;
      width: 100%;
      display: flex;
      flex-direction: row;

      .content-left-tree {
        width: 18%;
        display: flex;
        flex-direction: column;
        align-items: center;
        max-height: 495px;

        padding: 10px 0.5% 0px 0.5%;
        border: 1px solid #ccc;
        overflow-y: auto;
        overflow-x: auto;

        .content-tree {
          width: 100%;
          height: 100%;
          margin-top: 10px;

          .custom-tree-node {
            overflow-x: hidden !important;
            white-space: nowrap !important;
            text-overflow: ellipsis !important;
          }
        }
      }

      .content-right {
        width: 82%;
        margin-left: 10px;
        flex: 1;

        .content-right-title {
          display: flex;
          padding: 10px 0;
          margin-top: 10px;
          line-height: 1.5;

          .content-right-title-text {
            font-size: 14px;
            font-weight: bold;
          }
        }

        //.el-divider--horizontal {
        //  //margin-top: 0px;
        //  margin-bottom: 5px;
        //  height: 20px;
        //}

        //.content-right-title-desc {
        //  font-size: 16px;
        //  height: 48px;
        //  max-height: 48px;
        //  overflow-y: auto;
        //}
      }

      .content-right-Tabs {
        box-sizing: border-box;
        margin-top: 10px;
        margin-bottom: 10px;
        max-height: 400px;
      }
    }
  }
}
</style>
<!--<style lang="scss">-->
<!--.el-popover.popover-class {-->
<!--  .el-popover__title {-->
<!--    color: #fff;-->
<!--    background-color: #003078 !important;-->
<!--  }-->
<!--}-->
<!--</style>-->