<template>
  <div class="cockpit-health-panel">
    <CockpitTechTabs v-model="activeTab" :tabs="healthTabs" variant="panel" />

    <div class="cockpit-health-panel__tab-body">
      <div
        v-show="activeTab === 'healthy'"
        v-hasPermi="['home:health:btn']"
        class="cockpit-health-panel__pane cockpit-health-panel__pane--healthy"
      >
        <div class="cockpit-health-panel__subtitle">综合健康评分</div>
        <div class="cockpit-health-panel__body">
          <ul class="cockpit-health-panel__legend">
            <li
              v-for="item in legendItems"
              :key="item.name"
              class="cockpit-health-panel__legend-item"
            >
              <i :style="{ background: item.color }"></i>
              <span>{{ item.name }}</span>
            </li>
          </ul>
          <div
            ref="chartRef"
            v-loading="loading"
            class="cockpit-health-panel__chart"
            element-loading-background="rgba(5, 14, 35, 0.6)"
          ></div>
        </div>
        <CockpitHealthTable
          class="cockpit-health-panel__table"
          :table-data="tableData"
          :loading="loading"
          :datatime="datatime"
          :sort-config="sortConfig"
          @sort-change="handleSortChange"
        />
      </div>

      <div
        v-show="activeTab === 'abnormal'"
        v-hasPermi="['home:anomalyDetection:btn']"
        class="cockpit-health-panel__pane cockpit-health-panel__pane--abnormal"
      >
        <CockpitAbnormalPanel
          :maplistArr="maplistArr"
          :defaultdata="defaultdata"
          :datatime="datatime"
          :parent-opt="parentOpt"
        />
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import { store } from "@/store";
import { getHealthscoresWindList } from "@/api/healthAnalyse";
import CockpitTechTabs from "./CockpitTechTabs.vue";
import CockpitHealthTable from "./CockpitHealthTable.vue";
import CockpitAbnormalPanel from "./CockpitAbnormalPanel.vue";
import {
  aggregateHealthScoreDistribution,
  buildFieldCodeMap,
  buildFieldNameMap,
  mapHealthscoresWindList,
  filterEvaluatedRows,
  filterRowsByNodeFields,
  sortHealthTableData,
} from "./cockpitHealthMapper";

const HEALTH_TAB_PERMI = ["home:health:btn"];
const ABNORMAL_TAB_PERMI = ["home:anomalyDetection:btn"];

function hasTabPermi(permi) {
  const flags = Array.isArray(permi) ? permi : [];
  if (!flags.length) return true;
  const allPermission = "*:*:*";
  const permissions = store?.getters?.permissions || [];
  return permissions.some(
    (permission) => permission === allPermission || flags.includes(permission),
  );
}

export default {
  name: "CockpitHealthPanel",
  components: { CockpitTechTabs, CockpitHealthTable, CockpitAbnormalPanel },
  props: {
    maplistArr: { type: Object, default: () => ({}) },
    defaultdata: { type: Object, default: () => ({}) },
    parentOpt: { type: Array, default: () => [] },
    datatime: { type: String, default: "" },
  },
  data() {
    return {
      activeTab: "healthy",
      healthTabs: [
        { label: "健康", value: "healthy", permi: HEALTH_TAB_PERMI },
        { label: "异常", value: "abnormal", permi: ABNORMAL_TAB_PERMI },
      ],
      chart: null,
      loading: false,
      tableData: [],
      scoreDistribution: [],
      lastHealthList: [],
      sortConfig: { prop: "", order: "descending" },
      legendItems: [
        { name: "优", color: "#7ECF51" },
        { name: "良", color: "#2979ff" },
        { name: "中", color: "#EECB5F" },
        { name: "差", color: "#E16757" },
      ],
    };
  },
  watch: {
    maplistArr: {
      handler() {
        this.fetchHealthData();
      },
      deep: true,
      immediate: true,
    },
    datatime() {
      this.fetchHealthData();
    },
    parentOpt: {
      handler() {
        if (this.tableData.length) {
          this.applyHealthList(this.lastHealthList);
        }
      },
      deep: true,
    },
    activeTab(val) {
      if (val === "healthy") {
        this.$nextTick(() => {
          if (this.chart) {
            this.chart.resize();
          } else {
            this.initChart();
          }
        });
      }
    },
    healthTabs: {
      deep: true,
      handler() {
        this.syncActiveTabByPermi();
      },
    },
    scoreDistribution: {
      deep: true,
      handler() {
        this.renderChart();
      },
    },
  },
  mounted() {
    this.syncActiveTabByPermi();
    this.$nextTick(() => {
      this.initChart();
    });
    window.addEventListener("resize", this.handleResize);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.handleResize);
    if (this.chart) {
      this.chart.dispose();
      this.chart = null;
    }
  },
  methods: {
    syncActiveTabByPermi() {
      const visibleTabs = this.healthTabs.filter((tab) =>
        hasTabPermi(tab.permi),
      );
      if (!visibleTabs.length) return;
      if (!visibleTabs.some((tab) => tab.value === this.activeTab)) {
        this.activeTab = visibleTabs[0].value;
      }
    },
    getChartTheme() {
      const host =
        this.$refs.chartRef?.closest(".cockpit-dashboard-page") ||
        document.documentElement;
      const read = (name, fallback) =>
        getComputedStyle(host).getPropertyValue(name).trim() || fallback;
      return {
        labelColor: read("--cockpit-chart-label-text", "#ffffff"),
        labelLineColor: read(
          "--cockpit-chart-label-line",
          "rgba(255, 255, 255, 0.55)",
        ),
      };
    },
    initChart() {
      if (!this.$refs.chartRef) return;
      if (this.chart) {
        this.chart.dispose();
      }
      this.chart = echarts.init(this.$refs.chartRef);
      this.renderChart();
    },
    renderChart() {
      if (!this.chart) return;
      const { labelColor, labelLineColor } = this.getChartTheme();
      const chartData = this.scoreDistribution.length
        ? this.scoreDistribution
        : aggregateHealthScoreDistribution([]);
      this.chart.setOption(
        {
          tooltip: {
            trigger: "item",
            formatter: "{b}: {c}台 ({d}%)",
          },
          series: [
            {
              type: "pie",
              radius: ["42%", "72%"],
              center: ["55%", "50%"],
              avoidLabelOverlap: true,
              label: {
                show: true,
                overflow: "none",
                formatter: (params) => {
                  if (!params.value) return "";
                  return `{name|${params.name}}\n{value|${params.value}台}`;
                },
                rich: {
                  name: {
                    fontSize: 11,
                    color: labelColor,
                    lineHeight: 16,
                  },
                  value: {
                    fontSize: 11,
                    color: labelColor,
                    lineHeight: 16,
                    width: 72,
                    overflow: "none",
                  },
                },
              },
              emphasis: {
                label: {
                  color: labelColor,
                  overflow: "none",
                },
              },
              labelLine: {
                show: true,
                length: 6,
                length2: 12,
                smooth: true,
                lineStyle: { color: labelLineColor },
              },
              data: chartData,
            },
          ],
        },
        true,
      );
    },
    handleSortChange(sort) {
      this.sortConfig = sort;
      this.applyHealthList(this.lastHealthList);
    },
    applyHealthList(list) {
      const fieldNameMap = buildFieldNameMap(this.parentOpt);
      const fieldCodeMap = buildFieldCodeMap(this.parentOpt);
      const rows = mapHealthscoresWindList(list, fieldNameMap).map(
        (row, index) => {
          const raw = list[index] || {};
          const fieldCode =
            raw.fieldCode ||
            raw.codeNumber ||
            row.fieldCode ||
            fieldCodeMap[row.fieldName] ||
            "";
          return {
            ...row,
            fieldCode: fieldCode ? String(fieldCode) : "",
          };
        },
      );
      const scoped = filterRowsByNodeFields(rows, this.maplistArr);
      // 只展示已评估（有任意一台风机评分数据）的场站
      const evaluated = filterEvaluatedRows(scoped);
      // 按排序配置排序
      const sorted = sortHealthTableData(evaluated, this.sortConfig);
      this.tableData = sorted;
      this.scoreDistribution = aggregateHealthScoreDistribution(sorted);
    },
    buildHealthRequestParams() {
      const fieldCode =
        this.maplistArr?.codeNumber || this.maplistArr?.fieldCode;
      if (!fieldCode) {
        return null;
      }
      const params = { fieldCode };
      if (this.datatime) {
        params.datatime = this.datatime;
      }
      return params;
    },
    async fetchHealthData() {
      const selectedNode = this.maplistArr;
      if (!selectedNode || !Object.keys(selectedNode).length) return;

      this.loading = true;
      try {
        let list = [];
        // fieldCode 可传公司/区域 codeNumber，接口一次返回下属全部风场
        const params = this.buildHealthRequestParams();
        if (params) {
          const res = await getHealthscoresWindList(params);
          list = Array.isArray(res?.data) ? res.data : [];
        }
        this.lastHealthList = list;
        this.applyHealthList(list);
      } catch (error) {
        console.error("加载健康风场统计失败:", error);
        this.lastHealthList = [];
        this.tableData = [];
        this.scoreDistribution = aggregateHealthScoreDistribution([]);
      } finally {
        this.loading = false;
        this.$nextTick(() => {
          if (!this.chart) {
            this.initChart();
          } else {
            this.renderChart();
            this.chart.resize();
          }
        });
      }
    },
    handleResize() {
      if (this.chart) this.chart.resize();
    },
  },
};
</script>

<style lang="scss" scoped>
.cockpit-health-panel__subtitle {
  margin: 4px 0 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--cockpit-panel-title, #303133);
}

.cockpit-health-panel__tab-body {
  position: relative;
  height: var(--cockpit-health-pane-h);
  min-height: var(--cockpit-health-pane-h);
  overflow: hidden;
}

.cockpit-health-panel__pane {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.cockpit-health-panel__body {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  height: var(--cockpit-health-chart-h, 150px);
  min-height: var(--cockpit-health-chart-h, 150px);
}

.cockpit-health-panel__legend {
  flex: 0 0 52px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.cockpit-health-panel__legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--cockpit-panel-muted, #909399);

  i {
    flex-shrink: 0;
    width: 10px;
    height: 10px;
    border-radius: 1px;
  }
}

.cockpit-health-panel__chart {
  flex: 1;
  min-width: 0;
  height: var(--cockpit-health-chart-h, 150px);
}

.cockpit-health-panel__table {
  flex: 0 0 auto;
  margin-top: 8px;
}
</style>
