<template>
  <div class="track-wrapper">
    <div class="track-header flex">
      <div class="manageTitle">运单轨迹地图</div>
      <div class="search flex">
        <el-form ref="formRef" :model="formData" :rules="formRule">
          <el-form-item prop="waybillNO">
            <el-input
              v-model.trim="formData.waybillNO"
              class="search-input"
              size="default"
              placeholder="请输入运单号"
              :prefix-icon="Search"
              clearable
              @keyup.enter="searchHandler"
              @clear="clearHandler"
            />
          </el-form-item>
        </el-form>
        <el-button
          v-permission="['waybill_query_button']"
          class="search-button"
          size="default"
          type="primary"
          @click="searchHandler"
          >运单查询</el-button
        >
      </div>
    </div>
    <div class="track-map-wrapper">
      <div ref="trackMap" class="track-map" />
    </div>
  </div>
</template>
<script lang="ts" setup>
import _ from 'lodash'
import { Query } from '@/api/webApi'
import { Search } from '@element-plus/icons-vue'
import { init, ECharts } from 'echarts'
import { ElMessage, FormInstance } from 'element-plus'

const trackNodesMap = {
  departure: [
    {
      name: '收运核单',
      nodeCode: 'DEH',
    },
    {
      name: '收运核查',
      nodeCode: 'ACC_CHECK',
    },
    {
      name: '安检',
      nodeCode: '安检',
    },
    {
      name: '加货',
      nodeCode: 'ACC_BUP',
    },
    {
      name: '预配载',
      nodeCode: 'LS_CARGO',
    },
    // {
    //   name: '货站交接(离港)',
    //   nodeCode: 'CARGOS_HANDOVER_STATUS_02',
    // },
    {
      name: '交接复核',
      nodeCode: 'CARGOS_HANDOVER_STATUS_03',
    },
    {
      name: '机下交接(出港)',
      nodeCode: '出港货邮',
    },
    {
      name: '装机',
      nodeCode: '装载完成',
    },
    {
      name: '关闭舱门',
      nodeCode: '关闭舱门',
    },
    {
      name: '拉下登记',
      nodeCode: 'CARGOS_OFFLOAD',
    },
    {
      name: '拉回确认',
      nodeCode: 'OFFLOAD_CONFIRM',
    },
    {
      name: '退运',
      nodeCode: 'BILL_RETURN',
    },
  ],
  arrival: [
    {
      name: '卸机',
      nodeCode: 'CARGOS_ARR_HANDOVER',
    },
    {
      name: '库区到达',
      nodeCode: 'CARGOS_HANDOVER_STATUS_01',
    },
    {
      name: '货站交接(进港)',
      nodeCode: 'CARGOS_HANDOVER_STATUS_99',
    },
    {
      name: '理货',
      nodeCode: 'IMP_TALLY',
    },
    {
      name: '出库',
      nodeCode: 'FSUDLV',
    },
  ],
  internationalDeparture: [
    {
      name: '入园',
      nodeCode: 'EPORTREL',
    },
    {
      name: '海关',
      nodeCode: 'MTREL_out',
    },
    {
      name: '运抵',
      nodeCode: 'FOH',
    },
    {
      name: '安检',
      nodeCode: 'REH',
    },
    {
      name: '收运核单',
      nodeCode: 'RCS',
    },
    {
      name: '理货',
      nodeCode: 'ACC_BUP',
    },
    {
      name: '拉下',
      nodeCode: 'CARGOS_OFFLOAD',
    },
    {
      name: '待运区',
      nodeCode: 'WAT_LOC',
    },
    {
      name: '预配载',
      nodeCode: 'LS_CARGO',
    },
    // {
    //   name: '货站交接',
    //   nodeCode: 'CARGOS_HANDOVER_STATUS_02',
    // },
    {
      name: '交接复核',
      nodeCode: 'CARGOS_HANDOVER_STATUS_03',
    },
    {
      name: '机下交接',
      nodeCode: '出港货邮',
    },
    {
      name: '装机',
      nodeCode: '装载完成',
    },
  ],
  internationalArrival: [
    {
      name: '卸机',
      nodeCode: 'FFM',
    },
    {
      name: '机下交接',
      nodeCode: 'CARGOS_HANDOVER_STATUS_01',
    },
    {
      name: '货站交接',
      nodeCode: 'CARGOS_HANDOVER_STATUS_99',
    },
    {
      name: '理货',
      nodeCode: 'RCF报',
    },
    {
      name: '海关放行',
      nodeCode: 'MTREL_in',
    },
    {
      name: '出库',
      nodeCode: 'DLV报',
    },
  ],
}

const formRef = ref<FormInstance | null>(null)
const waybillValidator = (rule: any, value: any, callback: any) => {
  if (!value) {
    return callback(new Error('请输入运单号'))
  }
  const reg = /^[0-9]{3}\-[0-9]{8}$/
  if (!reg.test(value)) {
    return callback(new Error('请输入正确的运单号'))
  }
  callback()
}
const formRule = {
  waybillNO: [{ validator: waybillValidator, trigger: 'blur' }],
}
const formData = reactive({
  waybillNO: '',
})
const searchHandler = () => {
  formRef.value?.validate(valid => {
    if (valid) {
      getTrackNodes()
    }
  })
}
const clearHandler = () => {}
const getTrackNodes = async () => {
  try {
    const {
      code,
      returnData: { listValues },
      message,
    } = await Query({
      id: DATACONTENT_ID.trackMapNode,
      dataContent: [formData.waybillNO],
    })
    if (Number(code) !== 0) {
      throw new Error(message || '失败')
    }
    if (!listValues.length) {
      ElMessage.info('未查询到运单跟踪信息')
      return
    }
    const isInternational = listValues[0].DIType !== 'DOM'
    const isDeparture = listValues[0].IOType === '离港'
    const trackNodes: {
      name: string
      nodeCode: string
      value?: string
      label?: any
      itemStyle?: any
    }[] = isInternational
      ? isDeparture
        ? trackNodesMap.internationalDeparture
        : trackNodesMap.internationalArrival
      : isDeparture
      ? [...trackNodesMap.departure, ...trackNodesMap.arrival]
      : [...trackNodesMap.arrival, ...trackNodesMap.departure]
    listValues.forEach(
      ({
        nodeCode,
        execPosition,
        ConsignmentItemPackagingQuantityQuantity,
        execResult,
        execTime,
      }) => {
        const sameNode = trackNodes.find(node => node.nodeCode === nodeCode)
        if (sameNode) {
          Object.assign(sameNode, {
            value:
              execResult ?? '' !== ''
                ? `${execPosition ?? ' '}/${String(
                    ConsignmentItemPackagingQuantityQuantity ?? ' '
                  )}\n${!!Number(execResult) ? '通过' : '未通过'}/${
                    String(execTime ?? '').split('T')[1] ?? ' '
                  }`
                : '',
          })
          if (!Number(execResult)) {
            Object.assign(sameNode, {
              label: {
                backgroundColor: inActiveColor,
              },
              itemStyle: {
                color: '#FFFFFF',
                borderColor: inActiveColor,
                borderWidth: 3,
              },
            })
          } else {
            delete sameNode.label
            delete sameNode.itemStyle
          }
        }
      }
    )
    option.series[0].data = trackNodes.map((node, index, arr) => {
      const length = arr.length
      const resultNode = {
        ...node,
        x: index <= length / 2 ? index * 140 : (length - index) * 140,
        y:
          index <= length / 2 ? 500 + (index % 2 ? 0 : 50) : index % 2 ? 0 : 50,
      }
      if (!resultNode.value) {
        Object.assign(resultNode, {
          value: '',
          label: {
            backgroundColor: inActiveColor,
          },
          itemStyle: {
            color: '#FFFFFF',
            borderColor: inActiveColor,
            borderWidth: 3,
          },
        })
      }
      return resultNode
    })
  } catch (error) {
    console.error(error)
  }
}

const activeColor = '#AC014D'
const inActiveColor = '#9C9FA5'
const trackMap = ref<HTMLElement | null>(null)
let trackMapCharts: ECharts
const option = reactive({
  tooltip: {
    show: false,
  },
  animationDurationUpdate: 1500,
  animationEasingUpdate: 'quinticInOut',
  series: [
    {
      type: 'graph',
      layout: 'none',
      top: 150,
      bottom: 80,
      symbolSize: 24,
      itemStyle: {
        color: activeColor,
      },
      label: {
        show: true,
        offset: [0, -70],
        width: 130,
        height: 90,
        lineHeight: 24,
        backgroundColor: activeColor,
        borderRadius: 4,
        align: 'center',
        color: '#FFFFFF',
        fontSize: 16,
        fontFamily: 'Microsoft YaHei',
        fontWeight: 'bold',
        formatter: '{b}\n{c}',
      },
      data: [] as any[],
      links: [] as any[],
      lineStyle: {
        width: 6,
        color: activeColor,
        opacity: 1,
        curveness: 0,
      },
    },
  ],
})
watch(
  () => option.series[0].data,
  array => {
    option.series[0].links = array.reduce(
      (preArray, currentData, currentIndex, orginArray) => {
        if (currentIndex > 0) {
          const preData = orginArray[currentIndex - 1]
          const link = {
            source: preData.name,
            target: currentData.name,
          }
          if (
            !preData.value ||
            preData.value.includes('未通过') ||
            !currentData.value ||
            currentData.value.includes('未通过')
          ) {
            Object.assign(link, {
              lineStyle: {
                color: inActiveColor,
              },
            })
          }
          preArray.push(link)
        }
        return preArray
      },
      []
    )
    trackMapCharts.setOption(option)
  },
  { deep: true }
)
onMounted(() => {
  trackMapCharts = init(trackMap.value as HTMLElement)
  window.addEventListener('resize', resizeHandler)
})
onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeHandler)
})
const resizeHandler = _.debounce(() => {
  trackMapCharts.resize()
}, 300)
</script>
<style lang="scss" scoped>
.track-wrapper {
  width: 100%;
  height: 100%;
  .track-header {
    margin-bottom: 16px;
    .search {
      &-input {
        width: 240px;
        margin-right: 12px;
        box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.06);
      }
      &-button {
        background: #d5327b;
        border-radius: 4px;
        border: none;
      }
    }
  }
  .track-map-wrapper {
    width: 100%;
    height: calc(100% - 32px - 16px);
    background: url('@/assets/bg_map.jpg') no-repeat center/100% 100%;
    .track-map {
      height: 100%;
    }
  }
}
</style>
