<template>
  <div v-loading="loading" class="credit-archive">
    <div class="toolbar">
      <span class="toolbar-label">年报年度：</span>
      <el-select
        v-model="reportYear"
        size="small"
        clearable
        placeholder="默认最近一年"
        style="width: 160px;"
        @change="loadData"
      >
        <el-option
          v-for="y in yearOptions"
          :key="y"
          :label="`${y} 年`"
          :value="y"
        />
      </el-select>
      <el-button
        type="text"
        icon="el-icon-refresh"
        style="margin-left: 12px;"
        @click="resetGraph"
      >重置图谱</el-button>
      <span class="toolbar-tip">提示：点击一级分支可展开/收起明细，单分支最多展示 {{ maxNodes }} 个节点</span>
    </div>
    <div ref="graph" class="graph-container" />

    <!-- 节点详情弹窗 -->
    <el-dialog
      :visible.sync="detailVisible"
      :title="detailTitle"
      width="560px"
      append-to-body
    >
      <el-descriptions v-if="detailData" :column="1" border size="small">
        <el-descriptions-item
          v-for="(value, key) in detailData"
          :key="key"
          :label="fieldLabel(key)"
        >{{ value || '—' }}</el-descriptions-item>
      </el-descriptions>
    </el-dialog>
  </div>
</template>

<script>
import { getCreditArchive } from '@/api/comprehensive'

const MAX_NODES = 20
const CURRENT_YEAR = new Date().getFullYear()

const FIELD_LABEL_MAP = {
  name: '姓名',
  entName: '企业名称',
  uniscid: '统一社会信用代码',
  certType: '证件类型',
  subConAm: '认缴出资额',
  subConProp: '认缴出资比例（%）',
  respForm: '责任形式',
  position: '职务',
  lerepsign: '法定代表人标志',
  tel: '联系电话',
  email: '电子邮箱',
  invid: '股东ID',
  outinvid: '对外投资ID',
  lmid: '联络员ID'
}

const BRANCH_DEFS = [
  { key: 'shareholders', label: '股东信息', color: '#5470c6' },
  { key: 'legalPersons', label: '法定代表人', color: '#91cc75' },
  { key: 'investments', label: '对外投资', color: '#fac858' },
  { key: 'contacts', label: '联络人', color: '#ee6666' }
]

export default {
  name: 'CreditArchive',
  props: {
    pripid: {
      type: String,
      required: true
    },
    entName: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      loading: false,
      chart: null,
      reportYear: null,
      yearOptions: this.buildYearOptions(),
      maxNodes: MAX_NODES,
      archiveData: {
        shareholders: [],
        legalPersons: [],
        investments: [],
        contacts: []
      },
      truncated: {
        shareholders: false,
        investments: false,
        contacts: false
      },
      branches: BRANCH_DEFS,
      detailVisible: false,
      detailTitle: '',
      detailData: null
    }
  },
  mounted() {
    this.loadData()
    window.addEventListener('resize', this.resize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resize)
    if (this.chart) {
      this.chart.dispose()
      this.chart = null
    }
  },
  methods: {
    buildYearOptions() {
      const list = []
      for (let y = CURRENT_YEAR; y >= CURRENT_YEAR - 9; y--) {
        list.push(y)
      }
      return list
    },
    fieldLabel(key) {
      return FIELD_LABEL_MAP[key] || key
    },
    async loadData() {
      if (!this.pripid) return
      this.loading = true
      try {
        const res = await getCreditArchive({
          pripid: this.pripid,
          reportYear: this.reportYear || undefined
        })
        const data = (res && res.data) || res || {}
        this.archiveData = {
          shareholders: data.shareholders || [],
          legalPersons: data.legalPersons || [],
          investments: data.investments || [],
          contacts: data.contacts || []
        }
        this.truncated = data.truncated || { shareholders: false, investments: false, contacts: false }
        // Q5：首次加载用后端返回的 reportYear 作为默认选中
        if (!this.reportYear && data.reportYear) {
          this.reportYear = data.reportYear
        }
        this.$nextTick(() => this.renderGraph())
      } catch (e) {
        this.$message.error('信用档案数据加载失败')
      } finally {
        this.loading = false
      }
    },
    renderGraph() {
      if (!this.$refs.graph) return
      if (!this.chart) {
        this.chart = this.$echarts.init(this.$refs.graph)
        this.chart.on('click', params => this.handleNodeClick(params))
      }

      const centerName = this.entName || this.archiveData.entName || '主体'
      const centerNode = {
        id: 'center',
        name: centerName,
        symbolSize: 80,
        category: 0,
        fixed: true,
        x: 0,
        y: 0,
        itemStyle: { color: '#409EFF' },
        label: { fontWeight: 'bold' }
      }
      const branchNodes = this.branches.map((b, i) => ({
        id: b.key,
        name: `${b.label} (${(this.archiveData[b.key] || []).length})`,
        symbolSize: 50,
        category: i + 1,
        itemStyle: { color: b.color }
      }))
      const branchLinks = this.branches.map(b => ({
        source: 'center',
        target: b.key,
        lineStyle: { color: '#aaa', width: 2 }
      }))

      this.chart.setOption({
        tooltip: {
          trigger: 'item',
          formatter: params => {
            if (params.dataType === 'edge') return ''
            return params.name
          }
        },
        legend: [{
          data: this.branches.map(b => b.label),
          bottom: 0
        }],
        series: [{
          type: 'graph',
          layout: 'force',
          roam: true,
          draggable: true,
          label: { show: true, position: 'right', formatter: '{b}' },
          force: { repulsion: 400, edgeLength: 120 },
          categories: [
            { name: '主体' },
            ...this.branches.map(b => ({ name: b.label }))
          ],
          data: [centerNode, ...branchNodes],
          links: branchLinks,
          lineStyle: { color: 'source', curveness: 0.1 }
        }]
      }, true)
    },
    handleNodeClick(params) {
      // 点击中心节点 / 边 → 忽略
      if (!params.data || params.dataType === 'edge') return
      const branch = this.branches.find(b => b.key === params.data.id)
      if (branch) {
        this.toggleBranch(branch)
        return
      }
      // 二级节点点击 → 弹出明细
      if (params.data.rawData) {
        const parentKey = String(params.data.id).split('-')[0]
        const parentBranch = this.branches.find(b => b.key === parentKey)
        this.detailTitle = parentBranch ? `${parentBranch.label}详情` : '详情'
        this.detailData = params.data.rawData
        this.detailVisible = true
      }
    },
    toggleBranch(branch) {
      const list = this.archiveData[branch.key] || []
      if (!list.length) {
        this.$message.info(`暂无${branch.label}`)
        return
      }
      const option = this.chart.getOption()
      const series = option.series[0]
      const prefix = branch.key + '-'
      const hasChild = series.data.some(n => String(n.id).startsWith(prefix))

      if (hasChild) {
        // 收起
        series.data = series.data.filter(n => !String(n.id).startsWith(prefix))
        series.links = series.links.filter(l => !String(l.target).startsWith(prefix))
      } else {
        // Q11：单分支最多展开 MAX_NODES 个节点，超出部分显示"更多..."
        const displayList = list.slice(0, MAX_NODES)
        const categoryIndex = this.branches.indexOf(branch) + 1
        displayList.forEach((item, i) => {
          const nodeId = `${branch.key}-${i}`
          series.data.push({
            id: nodeId,
            name: this.getNodeName(branch.key, item),
            symbolSize: 30,
            category: categoryIndex,
            itemStyle: { color: branch.color, opacity: 0.7 },
            rawData: item
          })
          series.links.push({ source: branch.key, target: nodeId })
        })
        // 后端返回的截断标志或前端二次判断
        const isTruncated = this.truncated[branch.key] || list.length > MAX_NODES
        if (isTruncated) {
          const moreId = `${branch.key}-more`
          series.data.push({
            id: moreId,
            name: `更多... (共 ${list.length}${list.length > MAX_NODES ? '+' : ''} 项)`,
            symbolSize: 26,
            category: categoryIndex,
            itemStyle: { color: branch.color, opacity: 0.4 }
          })
          series.links.push({ source: branch.key, target: moreId })
        }
      }
      this.chart.setOption(option, true)
    },
    getNodeName(key, item) {
      if (key === 'investments') return item.entName || '—'
      if (key === 'shareholders') return item.name || '—'
      return item.name || '—'
    },
    resetGraph() {
      this.renderGraph()
    },
    resize() {
      if (this.chart) this.chart.resize()
    }
  }
}
</script>

<style lang="scss" scoped>
.credit-archive {
  .toolbar {
    display: flex;
    align-items: center;
    padding: 10px 12px;
    background: #fafafa;
    border: 1px solid #ebeef5;
    border-bottom: none;

    .toolbar-label {
      font-size: 13px;
      color: #606266;
      margin-right: 6px;
    }
    .toolbar-tip {
      margin-left: auto;
      font-size: 12px;
      color: #909399;
    }
  }
  .graph-container {
    width: 100%;
    height: 600px;
    border: 1px solid #ebeef5;
    background: #fff;
  }
}
</style>
