<template>
  <div class="container mx-auto px-4 py-8">
    <!-- 错误提示（带原始响应预览） -->
    <div v-if="error" class="status error mb-4">
      <i class="fa fa-exclamation-circle"></i> {{ error }}
      <div class="raw-response" v-if="rawResponse">
        <button @click="showRaw = !showRaw" class="mt-2">
          {{ showRaw ? '收起原始响应' : '查看原始响应（前1000字符）' }}
        </button>
        <pre v-if="showRaw" class="mt-2 bg-gray-50 p-2 text-sm">{{ truncatedRawResponse }}</pre>
      </div>
    </div>

    <div class="bg-white rounded-xl shadow-lg overflow-hidden">
      <!-- 加载状态 -->
      <div v-if="loading" class="py-20 flex justify-center items-center">
        <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
      </div>
      
      <!-- 数据展示区：表格 + 地图 + 柱状图 -->
      <div v-else-if="filteredData.length > 0" class="flex flex-col md:flex-row">
        <!-- 表格 -->
        <div class="w-full md:w-1/2 overflow-x-auto">
          <table class="min-w-full divide-y divide-gray-200">
            <thead class="bg-gray-50">
              <tr>
                <th 
                  v-for="(col, index) in displayColumns" 
                  :key="index"
                  :style="{ width: col.width }"  
                  class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100 transition-colors"
                  @click="sortData(col.label)"
                >
                  <div class="flex items-center justify-between">
                    {{ col.label }}
                    <span v-if="sortKey === col.label" class="ml-1 text-gray-400">
                      {{ sortOrder === 'asc' ? '↑' : '↓' }}
                    </span>
                  </div>
                </th>
              </tr>
            </thead>
            <tbody class="bg-white divide-y divide-gray-200">
              <tr v-for="(item, rowIndex) in sortedData" :key="rowIndex" 
                  class="hover:bg-gray-50 transition-colors duration-150">
                <td 
                  v-for="(col, colIndex) in displayColumns" 
                  :key="colIndex"
                  :style="{ width: col.width }"  
                  class="px-6 py-4 whitespace-nowrap text-sm"
                >
                  <div class="flex items-center">
                    <div class="text-gray-900 font-medium">
                      {{ formatValue(item, col) }}
                    </div>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <!-- 地图 + 柱状图（右侧区域） -->
        <div class="w-full md:w-1/2 p-4 flex flex-col">
          <!-- 地图（依赖：@vue-leaflet/vue-leaflet） -->
          <div class="h-64 mb-4">
            <LMap 
              :center="mapCenter" 
              :zoom="12" 
              style="width: 100%; height: 100%"
            >
              <LTileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
              <LMarker 
                v-for="(item, idx) in filteredData" 
                :key="idx" 
                :lat-lng="[item.latitude, item.longitude]"
              >
                <LPopup>{{ item.sampling_location }}</LPopup>
              </LMarker>
            </LMap>
          </div>

          <!-- 柱状图（依赖：echarts） -->
          <div class="h-64">
            <div ref="chart" class="w-full h-full"></div>
          </div>
        </div>
      </div>
      
      <!-- 空数据状态 -->
      <div v-else class="p-8 text-center">
        <div class="flex flex-col items-center justify-center">
          <div class="text-gray-400 mb-4">
            <i class="fa fa-database text-5xl"></i>
          </div>
          <h3 class="text-lg font-medium text-gray-900 mb-1">暂无有效数据</h3>
          <p class="text-gray-500">已过滤全空行</p>
        </div>
      </div>
  
      <!-- 数据统计 -->
      <div class="p-4 bg-gray-50 border-t border-gray-200">
        <div class="flex flex-col md:flex-row justify-between items-center">
          <div class="text-sm text-gray-500 mb-2 md:mb-0">
            共 <span class="font-medium text-gray-900">{{ filteredData.length }}</span> 条数据
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
import { LMap, LTileLayer, LMarker, LPopup } from '@vue-leaflet/vue-leaflet'; // 地图组件
import * as echarts from 'echarts'; // 柱状图

// ========== 接口配置 ==========
const apiUrl = 'http://localhost:8000/api/vector/export/all?table_name=Atmo_sample_data'; 

// ========== 响应式数据 ==========
const props = defineProps({
  calculationMethod: {
    type: String,
    required: true,
    default: 'weight'
  }
});

const waterData = ref([]);
const loading = ref(true);
const error = ref('');
const rawResponse = ref('');  
const showRaw = ref(false);   
const sortKey = ref('');      
const sortOrder = ref('asc'); 
const mapCenter = ref([23.5, 116.5]); // 地图初始中心（根据实际数据调整）
const chartInstance = ref(null); // ECharts实例

// 换算函数（重量→体积）
function calculateConcentration(heavyMetalWeight, volume) {
  if (heavyMetalWeight === undefined || volume === undefined || isNaN(heavyMetalWeight) || isNaN(volume) || volume === 0) {
    return '未知';
  }
  const ug = heavyMetalWeight * 1000; 
  const concentration = ug / volume;
  return concentration.toFixed(2); // 保留2位小数
}

function calculateParticleConcentration(particleWeight, volume) {
  if (particleWeight === undefined || volume === undefined || isNaN(particleWeight) || isNaN(volume) || volume === 0) {
    return '未知';
  }
  const ug = particleWeight * 1000; 
  const concentration = ug / volume;
  return concentration.toFixed(2); // 保留2位小数
}

// 列配置（补充 width，根据内容合理分配宽度）
const commonColumns = [
  { key: 'sampling_location', label: '采样位置', type: 'string', width: '180px' },
  { key: 'sample_name', label: '样品名称', type: 'string', width: '70px' },
  { key: 'latitude', label: '纬度', type: 'number', width: '60px' }, // 地图依赖字段
  { key: 'longitude', label: '经度', type: 'number', width: '60px' },// 地图依赖字段
];

const weightColumns = [
  { key: 'Cr_particulate', label: 'Cr mg/kg', type: 'number', width: '80px' },
  { key: 'As_particulate', label: 'As mg/kg', type: 'number', width: '80px' },
  { key: 'Cd_particulate', label: 'Cd mg/kg', type: 'number', width: '80px' },
  { key: 'Hg_particulate', label: 'Hg mg/kg', type: 'number', width: '80px' },
  { key: 'Pb_particulate', label: 'Pb mg/kg', type: 'number', width: '80px' },
  { key: 'particle_weight', label: '颗粒物重量 mg', type: 'number', width: '140px' },
];

const volumeColumns = [
  { key: 'standard_volume', label: '标准体积 m³', type: 'number', width: '120px' },
  { label: 'Cr ug/m³', getValue: (item) => calculateConcentration(item.Cr_particulate, item.standard_volume), type: 'number', width: '80px' },
  { label: 'As ug/m³', getValue: (item) => calculateConcentration(item.As_particulate, item.standard_volume), type: 'number', width: '80px' },
  { label: 'Cd ug/m³', getValue: (item) => calculateConcentration(item.Cd_particulate, item.standard_volume), type: 'number', width: '80px' },
  { label: 'Hg ug/m³', getValue: (item) => calculateConcentration(item.Hg_particulate, item.standard_volume), type: 'number', width: '80px' },
  { label: 'Pb ug/m³', getValue: (item) => calculateConcentration(item.Pb_particulate, item.standard_volume), type: 'number', width: '80px' },
  { label: '颗粒物浓度 ug/m³', getValue: (item) => calculateParticleConcentration(item.particle_weight, item.standard_volume), type: 'number', width: '140px' },
];

// 动态生成显示列
const displayColumns = computed(() => {
  return props.calculationMethod === 'volume' 
    ? [...commonColumns, ...volumeColumns] 
    : [...commonColumns, ...weightColumns];
});

// 数值格式化
const formatValue = (item, col) => {
  if (col.getValue) {
    const val = col.getValue(item);
    return val === '未知' ? '-' : val;
  } else {
    const value = item[col.key];
    if (value === null || value === undefined || value === '') return '-';
    if (col.type === 'number') {
      const num = parseFloat(value);
      return isNaN(num) ? '-' : num.toFixed(2); // 统一保留2位小数
    } else {
      return value;
    }
  }
};

// 过滤全空行（允许0值）
const filteredData = computed(() => {
  return waterData.value.filter(item => {
    return displayColumns.value.some(col => {
      let val = col.getValue ? col.getValue(item) : item[col.key];
      if (col.type === 'string') {
        return val !== null && val !== '' && val !== '-';
      } else {
        const num = parseFloat(val);
        return !isNaN(num); // 允许0值，仅排除非数字
      }
    });
  });
});

// 排序功能
const sortedData = computed(() => {
  if (!sortKey.value) return filteredData.value;
  
  const sortCol = displayColumns.value.find(col => col.label === sortKey.value);
  if (!sortCol) return filteredData.value;
  
  return [...filteredData.value].sort((a, b) => {
    let valA = sortCol.getValue ? sortCol.getValue(a) : a[sortCol.key];
    let valB = sortCol.getValue ? sortCol.getValue(b) : b[sortCol.key];
    
    if (sortCol.type === 'string') {
      const strA = valA.toString().trim();
      const strB = valB.toString().trim();
      return sortOrder.value === 'asc' 
        ? strA.localeCompare(strB) 
        : strB.localeCompare(strA);
    }
    
    const numA = parseFloat(valA) || -Infinity;
    const numB = parseFloat(valB) || -Infinity;
    if (numA < numB) return sortOrder.value === 'asc' ? -1 : 1;
    if (numA > numB) return sortOrder.value === 'asc' ? 1 : -1;
    return 0;
  });
});

// 切换排序
const sortData = (label) => {
  const targetCol = displayColumns.value.find(col => col.label === label);
  if (!targetCol) return;
  
  if (sortKey.value === label) {
    sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
  } else {
    sortKey.value = label;
    sortOrder.value = 'asc';
  }
};

// 截断原始响应（前1000字符）
const truncatedRawResponse = computed(() => {
  return rawResponse.value.length > 1000 
    ? rawResponse.value.slice(0, 1000) + '...' 
    : rawResponse.value;
});

// 柱状图数据（动态生成）
const chartData = computed(() => {
  const xData = filteredData.value.map(item => item.sample_name);
  const yData = filteredData.value.map(item => {
    if (props.calculationMethod === 'volume') {
      const val = item['Cr ug/m³'];
      return val !== '-' ? parseFloat(val) : 0;
    } else {
      const val = item.Cr_particulate;
      return val !== '-' ? parseFloat(val) : 0;
    }
  });

  return {
    xAxis: { type: 'category', data: xData },
    yAxis: { type: 'value' },
    series: [{ name: 'Cr 浓度', type: 'bar', data: yData }],
  };
});

// 初始化柱状图
const initChart = () => {
  nextTick(() => {
    if (chartInstance.value) chartInstance.value.dispose();
    chartInstance.value = echarts.init($refs.chart);
    chartInstance.value.setOption(chartData.value);
  });
};

// 监听数据变化，更新图表
watch(filteredData, () => {
  if (chartInstance.value) {
    chartInstance.value.setOption(chartData.value);
  }
});

// 数据请求 & 修复逻辑（含超时控制）
const fetchData = async () => {
  try {
    loading.value = true;
    error.value = '';
    rawResponse.value = '';

    // 超时控制（5秒）
    const TIMEOUT = 5000;
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), TIMEOUT);

    const response = await fetch(apiUrl, { signal: controller.signal });
    clearTimeout(timeoutId);

    if (!response.ok) throw new Error(`HTTP 错误：${response.status}`);

    let rawText = await response.text();
    rawResponse.value = rawText;

    // 修复 JSON 语法（替换 NaN/Infinity）
    rawText = rawText
      .replace(/:\s*NaN/g, ': null')
      .replace(/:\s*Infinity/g, ': null');

    let data;
    try {
      data = JSON.parse(rawText);
    } catch (parseErr) {
      error.value = `数据解析失败：${parseErr.message}\n原始响应：${rawText.slice(0, 200)}...`;
      console.error(parseErr, rawText);
      loading.value = false;
      return;
    }

    // 兼容接口格式
    let features = [];
    if (data.type === 'FeatureCollection' && Array.isArray(data.features)) {
      features = data.features;
    } else if (Array.isArray(data)) {
      features = data;
    } else {
      throw new Error('接口格式异常，需为 FeatureCollection 或数组');
    }

    // 提取数据（含经纬度）
    waterData.value = features.map(feature => 
      feature.properties ? feature.properties : feature
    );

    // 更新地图中心（取第一个点的经纬度，无数据则保持默认）
    if (waterData.value.length > 0) {
      mapCenter.value = [
        waterData.value[0].latitude, 
        waterData.value[0].longitude
      ];
    }

    console.log('✅ 数据加载完成，记录数：', waterData.value.length);
    initChart(); // 初始化图表

  } catch (err) {
    if (err.name === 'AbortError') {
      error.value = '请求超时！请检查网络或接口响应速度';
    } else {
      error.value = `数据加载失败：${err.message}`;
    }
    console.error(err);
  } finally {
    loading.value = false;
  }
};

// 组件挂载时加载数据
onMounted(() => {
  fetchData();
});

// 卸载时销毁图表
onUnmounted(() => {
  if (chartInstance.value) {
    chartInstance.value.dispose();
  }
});
</script>

<style scoped>
/* 错误提示样式 */
.status.error {
  color: #dc2626;
  background: #fee2e2;
  padding: 12px 16px;
  border-radius: 6px;
}
.status.error button {
  cursor: pointer;
  background: #ff4d4f;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 4px 8px;
}
.raw-response pre {
  white-space: pre-wrap;
  word-break: break-all;
  background: #f9fafb;
  padding: 8px;
  border-radius: 4px;
  font-size: 12px;
}

/* 表格核心样式：固定布局 + 列宽生效 */
table {
  border-collapse: collapse;
  table-layout: fixed; 
  width: 100%;         
}

th, td {
  border: 1px solid #d1d5db;
  text-align: center;
  padding: 10px 6px;   
  min-width: 60px;     
  white-space: normal; 
  overflow: hidden;    
  text-overflow: ellipsis; 
}

/* 地图 & 图表容器 */
.leaflet-container {
  width: 100%;
  height: 100%;
}
.echarts-container {
  width: 100%;
  height: 100%;
}

/* 响应式优化 */
@media (max-width: 768px) {
  th, td {
    padding: 8px 4px;
    font-size: 14px;
  }
  .flex-col md:flex-row {
    flex-direction: column;
  }
}
</style>