<template>
  <div class="container">    
    <div class="chart-container">
      <div v-if="isLoading" class="loading-overlay">
        <div class="spinner"></div>
        <span class="loading-text">数据加载中...</span>
      </div>
      <div v-if="error" class="error-overlay">
        <p>{{ errorMessage }}</p>
        <button class="retry-btn" @click="loadData">重试</button>
      </div>
      <div ref="chartRef" class="chart-wrapper"></div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue' 
import * as echarts from 'echarts' 
import { api5000 } from '@/utils/request'; // 导入 api5000 实例

const indicators = [
  { key: 'Delta_pH', name: 'Delta_pH', color: '#f39c12' }
];

let chart = ref(null) // 存储 ECharts 实例
let chartData = ref([]) // 存储图表数据
const chartRef = ref(null) // 图表容器
const statsByIndex = ref([]); // 存储每个指标的统计量
const isLoading = ref(true);
const error = ref(false);
const errorMessage = ref('');

function initChart() {
  // 确保图表容器已渲染
  if (!chartRef.value) return;
  
  // 初始化 ECharts 实例
  chart.value = echarts.init(chartRef.value);
  
  const option = {
    tooltip: {
      trigger: 'item',
      axisPointer: { type: 'shadow' },
      formatter: function(params) {
        const stat = statsByIndex.value[params.dataIndex];
        if (!stat || stat.min === null) {
          return `<div style="font-weight:bold;margin-bottom:8px;color:#2c3e50;">${params.name}</div>
                  <div>无有效数据</div>`;
        }  
        return `
          <div style="font-weight:bold;margin-bottom:8px;color:#2c3e50;">${stat.name}</div>
          <div style="display:grid;grid-template-columns:1fr 1fr;gap:5px;">
            <span style="color:#7f8c8d;">最小值:</span> <span style="text-align:right;font-weight:bold;">${stat.min}</span>
            <span style="color:#7f8c8d;">下四分位:</span> <span style="text-align:right;font-weight:bold;color:#e74c3c;">${stat.q1}</span>
            <span style="color:#7f8c8d;">中位数:</span> <span style="text-align:right;font-weight:bold;color:#3498db;">${stat.median}</span>
            <span style="color:#7f8c8d;">上四分位:</span> <span style="text-align:right;font-weight:bold;color:#e74c3c;">${stat.q3}</span>
            <span style="color:#7f8c8d;">最大值:</span> <span style="text-align:right;font-weight:bold;">${stat.max}</span>
          </div>
        `;
      }
    },
    title: {
      text: '酸化加剧指标箱线图展示',
      left: 'center',
      textStyle: {
        fontSize: 18,
        fontWeight: 'normal'
      },
      top: 10
    },
    grid: {
      left: '0px',
      right: '0px',
      bottom: '0px',
      top: '70px',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: indicators.map(i => i.name),
      axisLabel: {
        rotate: 30,
        fontSize: 12,
        margin: 15
      },
      axisTick: {
        alignWithLabel: true
      },
    },
    yAxis: {
      type: 'value',
      name: '数值',
      nameTextStyle: {
        fontSize: 14
      },
      nameGap: 25,
      splitLine: {
        lineStyle: {
          type: 'dashed',
          color: '#ddd'
        }
      }
    },
    series: [{
      name: '指标分布',
      type: 'boxplot',
      itemStyle: {
        color: function(params) {
          return indicators[params.dataIndex].color;
        },
        borderWidth: 2
      },
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowColor: 'rgba(0, 0, 0, 0.3)'
        }
      }
    }]
  };
  
  chart.value.setOption(option);
}


function calculatePercentile(sortedArray, percentile) {
  const n = sortedArray.length;
  if (n === 0) return null;
  if (percentile <= 0) return sortedArray[0];
  if (percentile >= 100) return sortedArray[n - 1];
  
  const index = (n - 1) * (percentile / 100);
  const lowerIndex = Math.floor(index);
  const upperIndex = lowerIndex + 1;
  const fraction = index - lowerIndex;
  
  if (upperIndex >= n) return sortedArray[lowerIndex];
  return sortedArray[lowerIndex] + fraction * (sortedArray[upperIndex] - sortedArray[lowerIndex]);
}


function calculateBoxplotStats(data, indicators) {
  const boxplotData = [];
  const statsArray = [];
  
  indicators.forEach(indicator => {
    const values = data
      .map(item => Number(item[indicator.key]))
      .filter(val => !isNaN(val))
      .sort((a, b) => a - b);
    
    if (values.length === 0) {
      boxplotData.push([null, null, null, null, null]);
      statsArray.push({
        min: null, q1: null, median: null, q3: null, max: null,
        name: indicator.name,
        color: indicator.color
      });
    } else {
      const min = Math.min(...values);
      const max = Math.max(...values);
      const q1 = calculatePercentile(values, 25);
      const median = calculatePercentile(values, 50);
      const q3 = calculatePercentile(values, 75);
      boxplotData.push([min, q1, median, q3, max]);
      
      statsArray.push({
        min, q1, median, q3, max,
        name: indicator.name,
        color: indicator.color
      });
    }
  });
  
  return { boxplotData, statsArray };
}


async function loadData() {
  isLoading.value = true;
  error.value = false;
  errorMessage.value = '';
  
  try {
    // 使用 api5000 实例获取数据
    const response = await api5000.get('/api/table-data?table_name=dataset_60');
    const result = response.data;
    
    // 检查响应是否成功
    if (!result || !result.data) {
      throw new Error('接口返回数据格式不正确');
    }
    
    chartData.value = result.data;

    const { boxplotData, statsArray } = calculateBoxplotStats(chartData.value, indicators);
    statsByIndex.value = statsArray;
    
    // 确保图表已初始化
    if (!chart.value) {
      initChart();
    }
    
    chart.value.setOption({
      series: [{
        data: boxplotData
      }]
    });
    
  } catch (err) {
    error.value = true;
    errorMessage.value = `加载失败: ${err.message || '网络错误'}`;
    console.error('数据加载失败:', err);
  } finally {
    isLoading.value = false;
  }
}

const handleResize = () => {
  if (chart.value) {
    chart.value.resize();
  }
};

onMounted(() => {
  nextTick(() => {
    initChart();
    loadData();
  });
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  if (chart.value) {
    chart.value.dispose(); // 销毁 ECharts 实例
    chart.value = null;
  }
  window.removeEventListener('resize', handleResize);
});
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.container {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  background: white;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}
.chart-container {
  width: 100%;
  height: 100%;
  padding: 20px;
  position: relative;
}
.chart-wrapper {
  width: 100%;
  height: 100%; 
  min-height: 200px;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  border-left-color: #3498db;
  animation: spin 1s linear infinite;
}

.loading-text {
  margin-top: 15px;
  font-size: 16px;
  color: #2c3e50;
}

.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 10;
  padding: 20px;
  text-align: center;
}

.error-overlay p {
  color: #e74c3c;
  font-size: 16px;
  margin-bottom: 20px;
}

.retry-btn {
  padding: 8px 16px;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s;
}

.retry-btn:hover {
  background: #2980b9;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
</style>