<template>
  <d2-container class="hawkeye-page">
    <div class="hawkeye-layout">
      <aside class="condition-panel">
        <div class="panel-header">
          <span>{{ $t(key('analysis_condition')) }}</span>
          <el-button type="primary" size="mini" icon="el-icon-data-analysis" :loading="loading" @click="onAnalyze">{{ $t(key('analyze')) }}</el-button>
        </div>
        <el-form ref="searchForm" :model="search" label-position="top" size="mini" class="condition-form">
          <el-form-item :label="$t(key('production_batch'))" prop="table">
            <el-select v-model="search.table" filterable clearable :placeholder="$t(key('select_production_batch'))" @change="onBatchChange">
              <el-option v-for="item in batchOptions" :key="item.id || item.batch" :label="item.batch" :value="item.batch" />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('process'))" prop="ng_colnum">
            <el-select v-model="search.ng_colnum" filterable clearable :placeholder="$t(key('select_ng_column'))" value-key="process_code" @change="onProcessChange">
              <el-option v-for="(item, index) in processOptions" :key="index" :label="formatProcessOption(item)" :value="item" />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('ng_code'))" prop="ng_code">
            <el-select v-model="search.ng_code" filterable clearable :placeholder="$t(key('select_ng_code'))">
              <el-option v-for="(item, index) in ngCodeOptions" :key="index" :label="item.explain || item.name || item.code || item" :value="item.explain || item.code || item" />
            </el-select>
          </el-form-item>
          <el-button icon="el-icon-refresh" size="mini" :disabled="loading" @click="onReset">{{ $t(key('reset')) }}</el-button>
        </el-form>
      </aside>

      <main class="result-panel">
        <div class="panel-header">
          <span>{{ $t(key('analysis_detail')) }}</span>
          <div class="legend">
            <span><i class="legend-dot is-related" />{{ $t(key('correlated')) }}</span>
            <span><i class="legend-dot is-unrelated" />{{ $t(key('not_correlated')) }}</span>
          </div>
        </div>

        <el-collapse v-if="noCorrColumns.length" class="excluded-panel">
          <el-collapse-item :title="$t(key('no_analysis_data_hint'))" name="excluded">
            <el-tag v-for="item in noCorrColumns" :key="item" size="mini" type="warning">{{ getParamName(item) }}</el-tag>
          </el-collapse-item>
        </el-collapse>

        <div v-loading="loading" class="analysis-content">
          <el-empty v-if="!hasAnalysis" :description="$t(key('no_data'))" :image-size="90" />
          <template v-else>
            <section class="chart-row">
              <div ref="pccChart" class="chart-box" />
              <el-table :data="tableData.pcc" size="mini" border height="100%">
                <el-table-column prop="process" :label="$t(key('process_param'))" min-width="160" show-overflow-tooltip />
                <el-table-column prop="sample_size" :label="$t(key('sample_size'))" width="90" />
                <el-table-column prop="corr_data" :label="$t(key('correlation_coeff'))" width="120" />
                <el-table-column prop="pv" :label="$t(key('p_value'))" width="110" />
                <el-table-column :label="$t(key('correlation'))" width="110">
                  <template slot="header">
                    {{ $t(key('correlation')) }}
                    <el-tooltip :content="$t(key('p_value_hint'))" placement="top">
                      <i class="el-icon-question" />
                    </el-tooltip>
                  </template>
                  <template slot-scope="scope">
                    <el-button type="text" :class="relationClass(scope.row.pv)" @click="showDistribution(scope.row)">{{ relationText(scope.row.pv) }}</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </section>

            <section v-if="tableData.chi.length" class="table-section">
              <el-table :data="tableData.chi" size="mini" border height="100%">
                <el-table-column prop="process" :label="$t(key('process_param'))" min-width="220" show-overflow-tooltip />
                <el-table-column prop="sample_size" :label="$t(key('sample_size'))" width="120" />
                <el-table-column prop="corr_data" :label="$t(key('chi_square_value'))" width="150" />
                <el-table-column prop="pv" width="140">
                  <template slot="header">
                    {{ $t(key('p_value')) }}
                    <el-tooltip :content="$t(key('scientific_notation_hint'))" placement="top">
                      <i class="el-icon-question" />
                    </el-tooltip>
                  </template>
                </el-table-column>
                <el-table-column width="120">
                  <template slot="header">
                    {{ $t(key('correlation')) }}
                    <el-tooltip :content="$t(key('p_value_hint2'))" placement="top">
                      <i class="el-icon-question" />
                    </el-tooltip>
                  </template>
                  <template slot-scope="scope">
                    <el-button type="text" :class="relationClass(scope.row.pv)" @click="showDistribution(scope.row)">{{ relationText(scope.row.pv) }}</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </section>
          </template>
        </div>
      </main>
    </div>

    <el-dialog :title="$t(key('analysis_report'))" :visible.sync="distributionDialog.visible" width="80%" @closed="closeDistribution">
      <div ref="distributionChart" class="distribution-chart" />
    </el-dialog>
  </d2-container>
</template>

<script>
import * as echarts from 'echarts'
import { i18nMixin } from '@/composables/useI18n'
import { getBatchAll } from '@/api/planning-production/batch-list'
import { analyzeHawkeyeCorrelation, getBatchResultParam, getDataClassificationByNGCode, getNGWorkstationBatch } from '@/api/data-platform/correlation-analysis/hawkeye'

export default {
  name: 'data-platform-correlation-analysis-hawkeye',
  mixins: [i18nMixin('page.data_platform.correlation_analysis.hawkeye')],
  data () {
    return {
      loading: false,
      search: { table: '', ng_colnum: '', ng_code: undefined },
      batchOptions: [],
      processOptions: [],
      ngCodeOptions: [],
      processParamNames: {},
      noCorrColumns: [],
      tableData: { pcc: [], chi: [] },
      pccChart: null,
      distributionChart: null,
      distributionDialog: { visible: false, data: {} }
    }
  },
  computed: {
    hasAnalysis () {
      return this.tableData.pcc.length > 0 || this.tableData.chi.length > 0
    }
  },
  mounted () {
    this.loadBatchOptions()
    window.addEventListener('resize', this.resizeCharts)
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.resizeCharts)
    if (this.pccChart) this.pccChart.dispose()
    if (this.distributionChart) this.distributionChart.dispose()
  },
  methods: {
    responseData (res) { return res && res.data !== undefined ? res.data : res },
    async loadBatchOptions () {
      const res = await getBatchAll({})
      this.batchOptions = this.responseData(res) || []
    },
    async onBatchChange (batch) {
      this.search.ng_colnum = ''
      this.search.ng_code = undefined
      this.processOptions = []
      this.ngCodeOptions = []
      this.processParamNames = {}
      if (!batch) return
      const [processRes, paramRes] = await Promise.all([
        getNGWorkstationBatch({ batch }),
        getBatchResultParam({ batch })
      ])
      this.processOptions = this.responseData(processRes) || []
      const paramData = this.responseData(paramRes) || {}
      this.processParamNames = paramData.result_param_names || {}
    },
    onProcessChange (value) {
      this.search.ng_code = undefined
      this.ngCodeOptions = Array.isArray(value) ? value : []
    },
    formatProcessOption (item) {
      const first = Array.isArray(item) ? item[0] : item
      return (first && (first.name || first.process_name || first.process_code)) || ''
    },
    buildAnalyzeParams () {
      const ngColumn = Array.isArray(this.search.ng_colnum) ? this.search.ng_colnum[0] : this.search.ng_colnum
      return {
        ...this.search,
        corr_code: [],
        ng_colnum: ngColumn && ngColumn.process_code ? ngColumn.process_code : ngColumn
      }
    },
    async onAnalyze () {
      if (!this.search.table) { this.$message.warning(this.$t(this.key('please_select_batch'))); return }
      if (!this.search.ng_colnum) { this.$message.warning(this.$t(this.key('please_select_process'))); return }
      this.loading = true
      try {
        const res = await analyzeHawkeyeCorrelation(this.buildAnalyzeParams())
        this.applyAnalysisData(this.responseData(res) || {})
      } finally {
        this.loading = false
      }
    },
    applyAnalysisData (data) {
      const x2 = Array.isArray(data.X2) ? data.X2 : []
      const pcc = Array.isArray(data.PCC) ? data.PCC : []
      this.noCorrColumns = Array.isArray(data.no_corr_colnum) ? data.no_corr_colnum : []
      this.tableData.pcc = pcc.map(item => ({
        process: this.getParamName(item.independent_variable_name),
        dependent_variable: item.independent_variable_name,
        sample_size: this.formatNumber(item.value && item.value[3]),
        corr_data: this.formatNumber(item.value && item.value[0]),
        pv: item.value && item.value[2]
      }))
      this.tableData.chi = x2.map(item => ({
        process: this.getParamName(item.independent_variable_name),
        dependent_variable: item.independent_variable_name,
        sample_size: this.formatNumber(item.value && item.value[0]),
        corr_data: this.formatNumber(item.value && item.value[1]),
        pv: item.value && item.value[2]
      }))
      this.$nextTick(() => this.renderPccChart(pcc))
    },
    renderPccChart (pcc) {
      const chartDom = this.$refs.pccChart
      if (!chartDom) return
      if (!this.pccChart) this.pccChart = echarts.init(chartDom)
      const points = pcc.map(item => ({
        name: this.getParamName(item.independent_variable_name),
        value: [Number(item.value && item.value[0]) || 0, Number(item.value && item.value[2]) || 0],
        sampleSize: item.value && item.value[3]
      }))
      this.pccChart.setOption({
        title: { text: this.$t(this.key('tooltip_corr_coeff')), left: 'center', textStyle: { fontSize: 14 } },
        grid: { left: 52, right: 28, top: 58, bottom: 42 },
        tooltip: {
          trigger: 'item',
          formatter: params => {
            const item = params.data
            return `${this.$t(this.key('tooltip_dependent_var'))}: ${item.name}<br>${this.$t(this.key('tooltip_corr_coeff'))}: ${this.formatNumber(item.value[0])}<br>${this.$t(this.key('tooltip_p_value'))}: ${this.formatNumber(item.value[1])}`
          }
        },
        xAxis: { type: 'value', name: this.$t(this.key('tooltip_corr_coeff')) },
        yAxis: { type: 'value', name: this.$t(this.key('tooltip_p_value')) },
        series: [{
          type: 'scatter',
          data: points,
          symbolSize: 9,
          itemStyle: { color: params => (Number(params.data.value[1]) > 0.05 ? '#409EFF' : '#F56C6C') }
        }]
      }, true)
      this.pccChart.resize()
    },
    async showDistribution (row) {
      if (!this.search.ng_code || !row.dependent_variable) return
      const res = await getDataClassificationByNGCode({ ng_code: this.search.ng_code, dependent_variable: row.dependent_variable })
      this.distributionDialog.data = this.responseData(res) || {}
      this.distributionDialog.visible = true
      this.$nextTick(this.renderDistributionChart)
    },
    renderDistributionChart () {
      const chartDom = this.$refs.distributionChart
      if (!chartDom) return
      if (!this.distributionChart) this.distributionChart = echarts.init(chartDom)
      const raw = Array.isArray(this.distributionDialog.data.col3) ? this.distributionDialog.data.col3 : []
      const grouped = this.groupDistribution(raw)
      const xAxis = grouped.values
      this.distributionChart.setOption({
        legend: { data: grouped.classNames, left: 10 },
        tooltip: { trigger: 'axis' },
        grid: { left: 48, right: 28, top: 48, bottom: 42 },
        xAxis: { type: 'category', data: xAxis },
        yAxis: { type: 'value', name: this.$t(this.key('total')) },
        series: grouped.classNames.map(name => ({ name, type: 'line', smooth: true, symbol: 'none', data: xAxis.map(value => grouped.map[name][value] || 0) }))
      }, true)
      this.distributionChart.resize()
    },
    groupDistribution (raw) {
      const classNames = Array.from(new Set(raw.map(item => item.classname))).filter(Boolean)
      const values = Array.from(new Set(raw.map(item => String(item.value)))).sort((a, b) => Number(a) - Number(b))
      const map = {}
      classNames.forEach(name => { map[name] = {}; values.forEach(value => { map[name][value] = 0 }) })
      raw.forEach(item => {
        const className = item.classname
        const value = String(item.value)
        if (map[className] && Object.prototype.hasOwnProperty.call(map[className], value)) map[className][value] += 1
      })
      return { classNames, values, map }
    },
    getParamName (code) {
      return this.processParamNames[code] || code || ''
    },
    relationClass (pv) {
      return Number(pv) > 0.05 ? 'relation-related' : 'relation-unrelated'
    },
    relationText (pv) {
      return Number(pv) > 0.05 ? this.$t(this.key('correlated_short')) : this.$t(this.key('not_correlated_short'))
    },
    formatNumber (value) {
      if (value === undefined || value === null || value === '') return ''
      const number = Number(value)
      if (!Number.isFinite(number)) return value
      return Math.abs(number) < 0.001 && number !== 0 ? number.toExponential(2) : Number(number.toFixed(4))
    },
    resizeCharts () {
      if (this.pccChart) this.pccChart.resize()
      if (this.distributionChart) this.distributionChart.resize()
    },
    closeDistribution () {
      this.distributionDialog.data = {}
    },
    onReset () {
      this.search = { table: '', ng_colnum: '', ng_code: undefined }
      this.processOptions = []
      this.ngCodeOptions = []
      this.noCorrColumns = []
      this.tableData = { pcc: [], chi: [] }
      if (this.pccChart) this.pccChart.clear()
    }
  }
}
</script>

<style lang="scss" scoped>
.hawkeye-page {
  ::v-deep .d2-container-full__body { padding: 0; }
}
.hawkeye-layout {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  height: calc(100vh - 132px);
  min-height: 640px;
  background: #fff;
}
.condition-panel {
  border-right: 1px solid #e5e9f2;
  overflow: auto;
}
.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  padding: 8px 14px;
  background: #f5f7fa;
  color: #303133;
  font-weight: 600;
}
.condition-form {
  padding: 14px;
  ::v-deep .el-select { width: 100%; }
}
.result-panel {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.legend {
  display: flex;
  gap: 14px;
  align-items: center;
  font-size: 12px;
  font-weight: 400;
}
.legend-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 5px;
  border-radius: 50%;
}
.is-related { background: #409eff; }
.is-unrelated { background: #f56c6c; }
.excluded-panel {
  padding: 0 12px;
  ::v-deep .el-tag { margin: 0 6px 6px 0; }
}
.analysis-content {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 14px;
}
.chart-row {
  display: grid;
  grid-template-columns: minmax(360px, 1fr) minmax(420px, 46%);
  gap: 14px;
  height: 360px;
  min-width: 860px;
}
.chart-box {
  height: 100%;
  border: 1px solid #ebeef5;
}
.table-section {
  height: 300px;
  min-width: 860px;
  margin-top: 14px;
}
.relation-related { color: #409eff; }
.relation-unrelated { color: #f56c6c; }
.distribution-chart {
  height: 560px;
  width: 100%;
}
@media (max-width: 1100px) {
  .hawkeye-layout {
    grid-template-columns: 1fr;
    height: auto;
  }
  .condition-panel {
    border-right: 0;
    border-bottom: 1px solid #e5e9f2;
  }
}
</style>
