<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form ref="form" :inline="true" :model="form" size="mini">
          <el-form-item :label="$t(key('battery_id'))" prop="battery_id">
            <el-input
              v-model="form.battery_id"
              :placeholder="$t(key('enter_battery_id'))"
              clearable
              style="width:260px"
              @keyup.enter.native="fetchData"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" :disabled="loading" :loading="loading" @click="fetchData">
              {{ $t(key('query')) }}
            </el-button>
            <el-button icon="el-icon-download" :disabled="loading" @click="exportTree">
              {{ $t(key('export')) }}
            </el-button>
            <el-button icon="el-icon-refresh" :disabled="loading" @click="resetForm">
              {{ $t(key('reset')) }}
            </el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>

    <div v-loading="loading" class="traceability-page">
      <el-empty v-if="!hasGraph" :description="$t(key('enter_battery_id'))" />
      <RelationGraph
        v-else
        ref="graphRef"
        class="trace-graph"
        :options="currentGraphOptions"
        :on-node-click="onNodeClick"
      >
        <template #graph-plug>
          <div class="trace-panel">
            <div class="trace-panel__label">{{ $t(key('view_type')) }}:</div>
            <el-radio-group v-model="currentCase" size="small" @change="renderGraph">
              <el-radio-button label="horizontal">{{ $t(key('horizontal')) }}</el-radio-button>
              <el-radio-button label="vertical">{{ $t(key('vertical')) }}</el-radio-button>
            </el-radio-group>

            <div class="trace-panel__label trace-panel__label--spaced">{{ $t(key('position')) }}:</div>
            <div class="trace-panel__row">
              <el-input v-model.trim="locator.item_code" size="small" clearable :placeholder="$t(key('enter_item_code'))" />
              <el-button size="small" type="primary" @click="locateNode('item_code', locator.item_code)">
                {{ $t(key('confirm_position')) }}
              </el-button>
            </div>
            <div class="trace-panel__row">
              <el-input v-model.trim="locator.item_batch" size="small" clearable :placeholder="$t(key('enter_item_batch'))" />
              <el-button size="small" type="primary" @click="locateNode('item_batch', locator.item_batch)">
                {{ $t(key('confirm_position')) }}
              </el-button>
            </div>
            <div class="trace-panel__row">
              <el-input
                v-model.trim="locator.workingsubclass_code"
                size="small"
                clearable
                :placeholder="$t(key('enter_work_unit'))"
              />
              <el-button size="small" type="primary" @click="locateNode('workingsubclass_code', locator.workingsubclass_code, true)">
                {{ $t(key('confirm_position')) }}
              </el-button>
            </div>
          </div>
        </template>

        <template #node="{ node }">
          <div class="trace-node" :class="{ 'is-active': activeNodeId === String(node.id) }">
            <div class="trace-node__tag">
              <el-tag type="warning" effect="dark" size="small">{{ node.data.type_name || '-' }}</el-tag>
            </div>
            <div class="trace-node__title">{{ node.text || node.id }}</div>
            <div class="trace-node__body">
              <div class="trace-node__line">{{ $t(key('item_name')) }}: {{ node.data.item_name || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('item_code')) }}: {{ node.data.item_code || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('item_batch')) }}: {{ node.data.item_batch || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('work_unit')) }}: {{ node.data.workingsubclass_code || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('work_unit_name')) }}: {{ node.data.workingsubclass_name || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('process_code')) }}: {{ node.data.process_code || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('start_time')) }}: {{ node.data.start_time || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('finish_time')) }}: {{ node.data.finish_time || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('inspection_person')) }}: {{ node.data.inspection_person || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('inspection_time')) }}: {{ node.data.inspection_time || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('quality_person')) }}: {{ node.data.quality_person || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('quality_time')) }}: {{ node.data.quality_time || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('device_name')) }}: {{ node.data.device_name || '-' }}</div>
              <div class="trace-node__line">{{ $t(key('device_code')) }}: {{ node.data.device_code || '-' }}</div>
            </div>
          </div>
        </template>
      </RelationGraph>
    </div>
  </d2-container>
</template>

<script>
import RelationGraph from 'relation-graph'
import { i18nMixin } from '@/composables/useI18n'
import {
  exportBackwardTraceabilityTree,
  getBackwardTraceabilityData
} from '@/api/data-platform/traceability/backward'

export default {
  name: 'data-platform-traceability-backward',
  components: {
    RelationGraph
  },
  mixins: [i18nMixin('page.data_platform.traceability.backward')],
  data () {
    return {
      loading: false,
      form: {
        battery_id: this.$route.params.battery_id || ''
      },
      traceData: {},
      currentCase: 'horizontal',
      activeNodeId: '',
      locator: {
        item_code: '',
        item_batch: '',
        workingsubclass_code: ''
      }
    }
  },
  computed: {
    graph () {
      return this.traceData.relation_graph || {}
    },
    hasGraph () {
      return Array.isArray(this.graph.nodes) && this.graph.nodes.length > 0
    },
    horizontalOptions () {
      return {
        backgroundImageNoRepeat: true,
        defaultNodeBorderWidth: 0,
        defaultLineShape: 3,
        defaultNodeShape: 0,
        defaultJunctionPoint: 'tb',
        defaultNodeWidth: 330,
        defaultNodeHeight: 430,
        defaultFocusRootNode: false,
        downloadImageFileName: this.downloadName,
        defaultLineColor: 'rgba(0, 186, 189, 1)',
        defaultNodeColor: 'rgba(0, 206, 209, 1)',
        moveToCenterWhenResize: true,
        defaultLineMarker: {
          markerWidth: 12,
          markerHeight: 12,
          refX: '10',
          refY: 6,
          data: 'M2,2 L10,6 L2,10 L6,6 L2,2'
        },
        layouts: [
          {
            label: this.$t(this.key('center')),
            layoutName: 'tree',
            layoutClassName: 'seeks-layout-center',
            centerOffset_x: 0,
            centerOffset_y: 0,
            distance_coefficient: 1,
            layoutDirection: 'v',
            from: 'top',
            min_per_width: 560,
            max_per_width: 1100,
            min_per_height: 560,
            max_per_height: 1100
          }
        ]
      }
    },
    verticalOptions () {
      return {
        defaultNodeShape: 1,
        defaultNodeBorderWidth: 0,
        defaultNodeWidth: 330,
        defaultNodeHeight: 430,
        defaultLineShape: 3,
        defaultJunctionPoint: 'lr',
        defaultFocusRootNode: false,
        downloadImageFileName: this.downloadName,
        defaultLineColor: 'rgba(0, 186, 189, 1)',
        defaultNodeColor: 'rgba(0, 206, 209, 1)',
        moveToCenterWhenResize: true,
        layout: {
          label: this.$t(this.key('center')),
          layoutName: 'tree',
          layoutClassName: 'seeks-layout-center',
          defaultNodeShape: 0,
          defaultLineShape: 1,
          from: 'left',
          min_per_width: 660,
          max_per_width: 1100,
          min_per_height: 560,
          max_per_height: 700
        },
        defaultLineMarker: {
          markerWidth: 12,
          markerHeight: 12,
          refX: 6,
          refY: 6,
          data: 'M2,2 L10,6 L2,10 L6,6 L2,2'
        }
      }
    },
    currentGraphOptions () {
      return this.currentCase === 'horizontal' ? this.horizontalOptions : this.verticalOptions
    },
    downloadName () {
      const firstNode = this.graph.nodes && this.graph.nodes[0]
      return firstNode && firstNode.text ? firstNode.text : this.$t(this.key('reverse'))
    }
  },
  mounted () {
    if (this.form.battery_id) this.fetchData()
  },
  methods: {
    ensureBatteryInput () {
      if (this.form.battery_id) return true
      this.$message.error(this.$t(this.key('enter_battery_id')))
      return false
    },
    async fetchData () {
      if (!this.ensureBatteryInput()) return
      this.loading = true
      try {
        const res = await getBackwardTraceabilityData({ ...this.form })
        const data = res && res.data ? res.data : res
        this.traceData = data || {}
        const firstNode = this.graph.nodes && this.graph.nodes[0]
        this.activeNodeId = firstNode ? String(firstNode.id) : ''
        this.$nextTick(this.renderGraph)
      } finally {
        this.loading = false
      }
    },
    resetForm () {
      this.form.battery_id = ''
      this.traceData = {}
      this.activeNodeId = ''
      this.locator = {
        item_code: '',
        item_batch: '',
        workingsubclass_code: ''
      }
    },
    renderGraph () {
      if (!this.hasGraph || !this.$refs.graphRef) return
      this.$refs.graphRef.setOptions(this.currentGraphOptions)
      this.$refs.graphRef.setJsonData(this.graph)
    },
    onNodeClick (nodeObject) {
      this.activeNodeId = String(nodeObject.id)
    },
    locateNode (field, value, onlyFinalProduct = false) {
      if (!value || !this.hasGraph) return
      const target = this.graph.nodes.find(node => {
        const data = node.data || {}
        if (String(data[field] || '') !== String(value)) return false
        if (!onlyFinalProduct) return true
        return data.type_name === '制成品' && Number(data.status) === -1
      })
      if (!target) {
        this.$message.warning(this.$t(this.key('node_not_found')))
        return
      }
      this.activeNodeId = String(target.id)
      this.$nextTick(() => {
        const graphInstance = this.$refs.graphRef && this.$refs.graphRef.getInstance()
        if (!graphInstance) return
        graphInstance.setZoom(200)
        graphInstance.focusNodeById(target.id)
      })
    },
    async exportTree () {
      if (!this.ensureBatteryInput()) return
      if (!this.hasGraph) {
        this.$message.warning(this.$t(this.key('query_before_export')))
        return
      }
      const res = await exportBackwardTraceabilityTree({
        ...this.form,
        tree_list: JSON.stringify(this.graph.nodes || [])
      })
      const data = res && res.data ? res.data : res
      this.downloadExport(data)
    },
    downloadExport (url) {
      if (!url) return
      const link = document.createElement('a')
      link.href = url
      link.download = `${this.form.battery_id}${this.$t(this.key('reverse'))}`
      link.target = '_blank'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    }
  }
}
</script>

<style lang="scss" scoped>
.search-bar {
  margin-bottom: -18px;
}

.traceability-page {
  height: calc(100vh - 170px);
  min-height: 620px;
}

.trace-graph {
  width: 100%;
  height: 100%;
  min-height: 620px;
  border: 1px solid #ebeef5;
  background: #f7f9fb;
}

.trace-panel {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 20;
  width: 360px;
  padding: 12px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}

.trace-panel__label {
  margin-bottom: 8px;
  color: #606266;
  font-size: 13px;
  font-weight: 600;
}

.trace-panel__label--spaced {
  margin-top: 14px;
}

.trace-panel__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 92px;
  gap: 8px;
  margin-top: 10px;
}

.trace-node {
  position: relative;
  width: 330px;
  height: 410px;
  padding: 28px 12px 12px;
  color: #303133;
  cursor: pointer;
  text-align: left;
}

.trace-node.is-active .trace-node__body {
  border-color: #f56c6c;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.18);
}

.trace-node__tag {
  position: absolute;
  top: 0;
  left: 0;
}

.trace-node__title {
  min-height: 22px;
  margin-bottom: 8px;
  padding-right: 8px;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.4;
  word-break: break-word;
}

.trace-node__body {
  height: 340px;
  overflow: auto;
  padding: 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: #fff;
  color: #555;
}

.trace-node__line {
  min-height: 24px;
  padding: 4px 0;
  border-bottom: 1px solid #efefef;
  line-height: 1.4;
  white-space: normal;
  word-break: break-all;
}
</style>
