<template>
  <div class="communityNode-component">
    <div class="graph-container" id="container"></div>
    <div class="statistic-container">
      <div class="statistics-item" v-for="item in statisticsList" :key="item.id">
        <img :src="item.icon" class="icon" />
        <div class="name">{{ item.name }}:&nbsp;</div>
        <div class="count">{{ item.count }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, inject, watch, ref, onUnmounted } from "vue"
import * as echarts from "echarts"
import nodeHoverImg from "@/assets/images/nodeHover.png"
import predictionNodeImg from "@/assets/images/linkPrediction/icon/prediction-node.png"
import charHiddenNodeImg from "@/assets/images/linkPrediction/icon/character-hidden-node.png"
import charInteractionHiddenNodeImg from "@/assets/images/linkPrediction/icon/character-Interaction-hidden-node.png"
import normalGroupNodeImg from "@/assets/images/linkPrediction/icon/normal-group-node.png"
let chart = null
// 记录初始的 links，和当前是否隐藏虚线
let originalLinks = []
let hideDashed = false
const emit = defineEmits(["click:node", "click:edge"])
const statisticsList = inject("statisticsList")
const communityNodeList = ref(inject("communityNodeList"))
const props = defineProps({
  interactionStore: {
    type: Object,
    required: true
  },
  storeId: {
    type: String,
    default: ""
  }
})

// 监听communityNodeList变化 解决第一次进入页面不渲染问题
watch(
  communityNodeList,
  () => {
    initChart()
  },
  { deep: true }
)

const initChart = () => {
  const imageSelect = (node) => {
    if (props.storeId == "characterInteraction") {
      if (node.isIncludePredictNodes) {
        if (node.selfIncludeImplicitRelationship) {
          return `image://${new URL(charInteractionHiddenNodeImg, import.meta.url)}`
        } else {
          return `image://${new URL(predictionNodeImg, import.meta.url)}`
        }
      } else {
        return `image://${new URL(normalGroupNodeImg, import.meta.url)}`
      }
    } else if (props.storeId == "characterHidden") {
      if (node.isIncludePredictNodes) {
        if (node.selfIncludeImplicitRelationship) {
          return `image://${new URL(charHiddenNodeImg, import.meta.url)}`
        } else {
          return `image://${new URL(predictionNodeImg, import.meta.url)}`
        }
      } else {
        return `image://${new URL(normalGroupNodeImg, import.meta.url)}`
      }
    }
  }
  //处理社团节点
  // 确保item是有效的对象
  let nodes = Object.values(communityNodeList.value).map((item) => ({
    id: item.id,
    nodeName: item.id,
    isIncludePredictNodes: item.isIncludePredictNodes,
    nodesNum: item.nodesNum,
    neighbors: item.neighbors,
    category: item.isIncludePredictNodes ? 1 : 0,
    symbolSize: 30,
    selfIncludeImplicitRelationship: item.neighbors
      .map((nei) => ({ id: nei.id, isHidden: nei.isHidden }))
      .find((neiChild) => neiChild.id == item.id && neiChild.isHidden)
  }))
  nodes = nodes.map((item) => ({
    ...item,
    symbol: imageSelect(item)
  }))

  //处理连边
  const links = []
  nodes.forEach((communityNode) => {
    communityNode.neighbors.forEach((communityNei) => {
      links.push({
        source: communityNode.id,
        target: communityNei.id,
        edge: communityNei.isHidden ? 1 : 0, //该边存在互动隐关系则权值为1，否则为0
        lineStyle: {
          width: communityNei.isHidden ? 4 : 1, // 无互动=细线，有互动=加粗
          color: communityNei.isHidden ? props.interactionStore.predictionLineColor : "#37ACD7", // 无互动=灰色，有互动=黄色
          opacity: communityNei.isHidden ? 1 : 0.8, // 可选：调整透明度增强模糊感
          type: communityNei.isHidden ? "dashed" : "solid" // 无互动=实线，有互动=虚线
        }
      })
    })
  })
  // 保存初始 links，用于后续切换
  originalLinks = JSON.parse(JSON.stringify(links))

  const data = { nodes, links }
  const categories = [
    {
      name: "普通社团",
      category: 0,
      icon: `image://${new URL(normalGroupNodeImg, import.meta.url)}`
    },
    {
      name: "含预测节点社团",
      category: 1,
      icon: `image://${new URL(predictionNodeImg, import.meta.url)}`
    },
    {
      name: props.interactionStore.predictionLegendContent,
      category: 2,
      icon: props.interactionStore.predictionLegendIcon
    }
  ]
  const option = {
    //图例配置
    legend: [
      {
        data: categories.map((c) => ({
          name: c.name,
          itemStyle: {
            color:
              c.category === 0
                ? new echarts.graphic.LinearGradient(1, 0, 0, 0, [
                    { offset: 1, color: "#1a3860" }, // 深蓝渐变
                    { offset: 0.5, color: "#38546b" },
                    { offset: 0, color: "#5fb3b3" }
                  ])
                : new echarts.graphic.LinearGradient(1, 0, 0, 0, [
                    { offset: 0, color: "#9eec9c" }, // 绿色渐变
                    { offset: 0.37, color: "#aef295" },
                    { offset: 1, color: "#c2f989" }
                  ])
          },
          icon: c.icon
        })),
        right: 15,
        bottom: 10,
        icon: "circle",
        orient: "vertical",
        itemWidth: 16,
        itemHeight: 16,
        itemGap: 12,
        backgroundColor: "rgba(0,67,125,0.56)", // 半透明深蓝
        borderRadius: 8, // 圆角
        borderColor: "#c2f2ff", // 淡蓝色边框
        borderWidth: 0.3,
        padding: [12, 20, 12, 20], // 上右下左
        textStyle: {
          color: "#fff",
          fontSize: 16,
          fontWeight: "normal"
        }
      }
    ],
    //hover上去的窗口
    tooltip: {
      trigger: "item",
      backgroundColor: "rgba(0,0,0,0)", // 透明背景
      borderColor: "rgba(0,0,0,0)", // 透明边框
      borderWidth: 0,
      extraCssText: "box-shadow:none;padding:0;",
      formatter: function (params) {
        if (params.dataType === "node") {
          return `<div
                    style="
                    width: 107px;
                    height: 68px;
                    border-radius: 4px;
                    background: url('${nodeHoverImg}');
                    background-size: cover;
                    background-position: center;
                    background-repeat: no-repeat;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    flex-direction: column;
                    ">
                <div style="color:#fff;letter-spacing: 0.14px;">
                    <div >节点数：${params.data.nodesNum}</div>
              </div>
            </div>`
        }
        return ""
      }
    },
    series: [
      {
        type: "graph",
        layout: "force",
        animation: false,
        draggable: true,
        roam: true,
        zoom: 0.3,
        categories: categories,
        force: {
          edgeLength: 2500,
          repulsion: 4000,
          gravity: 0.4,
          friction: 0.02,
          coolingFactor: 0.1
        },
        animationDurationUpdate: 3500, // 节点移动更平滑
        data: data.nodes.map((node) => ({
          ...node,
          symbolSize: node.nodesNum / 10 < 30 ? 50 : 70,
          itemStyle: {
            color:
              node.isIncludePredictNodes === false
                ? new echarts.graphic.RadialGradient(0.98, 0.38, 0.9, [
                    { offset: 1, color: "#1a3860" }, // 最左侧
                    { offset: 0.5, color: "#38546b" }, // 中间
                    { offset: 0, color: "#5fb3b3" } // 最右侧
                  ])
                : new echarts.graphic.RadialGradient(0.98, 0.38, 0.9, [
                    // anchorCount为1的节点渐变（原配色）
                    { offset: 0, color: "#9eec9c" },
                    { offset: 0.37, color: "#aef295" },
                    { offset: 1, color: "#c2f989" }
                  ]),

            opacity: 1,
            borderColor: node.selfIncludeImplicitRelationship
              ? props.interactionStore.predictionLineColor
              : "#46C6AD",
            borderWidth: node.selfIncludeImplicitRelationship ? 3 : 1,
            shadowBlur: 4,
            borderType: "dashed",
            shadowColor: "rgba(19, 27, 114, 0.25)"
          },
          emphasis: {
            itemStyle: {
              shadowBlur: 20,
              shadowColor: "#c4a651",
              borderColor: "#fcd267",
              borderWidth: node.isIncludePredictNodes == false ? 1 : 5,
              borderType: "solid"
            }
          }
        })),
        links: data.links,
        lineStyle: {
          color: "#37ACD7",
          width: 1
        },
        emphasis: {
          // 高亮配置
          focus: "adjacency", // 高亮相邻节点
          lineStyle: {
            // 高亮时线条样式
            width: 10 // 线条宽度(10)
          }
        }
      }
    ]
  }
  chart.setOption(option)
  // 先解绑，避免重复注册
  chart.off("legendselectchanged")
  // 监听图例点击：当点击“预测连边”图例（即第 3 个）时，切换虚线可见性
  chart.on("legendselectchanged", (e) => {
    if (e.name === props.interactionStore.predictionLegendContent) {
      hideDashed = !hideDashed
      applyDashedVisibility(hideDashed)
    }
  })
}

// 切换虚线连边可见性
const applyDashedVisibility = (hide) => {
  if (!chart || !originalLinks.length) return
  const updated = originalLinks.map((l) => {
    const isDashed = l?.lineStyle?.type === "dashed"
    if (!isDashed) return l
    return {
      ...l,
      lineStyle: {
        ...l.lineStyle,
        // 完全隐藏：宽度为 0 且透明
        width: hide ? 0 : (l.lineStyle.width ?? 1),
        opacity: hide ? 0 : (l.lineStyle.opacity ?? 1)
      },
      // 避免高亮时又出现
      emphasis: {
        ...(l.emphasis || {}),
        lineStyle: {
          ...((l.emphasis && l.emphasis.lineStyle) || {}),
          width: hide ? 0 : 10
        }
      }
    }
  })

  chart.setOption({
    series: [{ links: updated }]
  })
}

const handleClickNode = () => {
  chart.on("click", function (params) {
    if (params.dataType === "node") {
      emit("click:node", params.data)
    } else if (params.dataType == "edge") {
      const { data } = params
      if (data.edge) {
        emit("click:edge", data)
      }
    }
  })
}
// 监听窗口大小变化，重置图表
const handleResize = () => {
  if (chart) {
    chart.resize()
  }
}
//echarts自适应方法
const resizeChart = () => {
  window.removeEventListener("resize", handleResize) //先移除旧的监听
  window.addEventListener("resize", handleResize)
}

onUnmounted(() => {
  window.removeEventListener("resize", handleResize)
  if (chart) {
    chart.dispose()
  }
})

onMounted(() => {
  // 确保容器存在
  const container = document.getElementById("container")
  if (!container) return
  chart = echarts.init(container)
  if (!chart.getOption()) {
    initChart()
  }
  handleClickNode()
  resizeChart()
})
</script>

<style scoped lang="scss">
.communityNode-component {
  width: 100%;
  height: 100%;
  position: relative;

  .graph-container {
    width: 100%;
    height: 93%;
    backdrop-filter: blur(5px);
  }
  .statistic-container {
    width: vw(378);
    height: vh(42);
    flex-shrink: 0;
    border-radius: vw(4);
    border: 1px solid #3aa1f8;
    background: linear-gradient(270deg, rgba(0, 82, 125, 0.48) 0%, rgba(0, 200, 255, 0.23) 100%);
    backdrop-filter: blur(vw(3));
    position: absolute;
    bottom: vh(48);
    left: vw(15);
    display: flex;
    justify-content: space-between;
    .statistics-item {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;

      .icon {
        width: vw(14);
        height: vh(14);
      }
      .name {
        color: rgba(255, 255, 255, 0.76);
        text-align: center;
        font-family: OPPOSans;
        font-size: vw(14);
        font-style: normal;
        font-weight: 400;
        line-height: normal;
        margin-left: vw(3);
      }
      .count {
        color: #fff;
        font-family: D-DIN;
        font-size: vw(15);
        font-style: normal;
        font-weight: 700;
        line-height: normal;
        margin-bottom: vh(2);
      }
    }
  }
}
</style>
