<template>
  <div class="page-container">
    <div class="header" style="display: flex; justify-content: space-between; align-items: center;">
      <a-typography-title :heading="4" style="margin: 0">设备管理</a-typography-title>
      <a-button @click="openConfigDialog">
        <template #icon><icon-settings /></template>
        采集频率设置
      </a-button>
    </div>

    <!-- Filter Bar -->
    <div class="filter-bar">
      <a-form :model="searchForm" layout="inline">
        <a-form-item field="name" label="设备名称">
          <a-input v-model="searchForm.name" placeholder="请输入设备名称" allow-clear />
        </a-form-item>
        <a-form-item field="deviceType" label="设备类型">
          <a-select v-model="searchForm.deviceType" placeholder="请选择类型" allow-clear style="width: 150px;">
            <a-option v-for="item in deviceTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
          </a-select>
        </a-form-item>
        <a-form-item field="sourceId" label="接入源">
           <a-select v-model="searchForm.sourceId" placeholder="筛选接入源" allow-clear style="width: 150px;">
              <a-option v-for="s in sources" :key="s.ID" :label="s.Name" :value="s.ID" />
           </a-select>
        </a-form-item>
        <a-form-item field="status" label="状态">
          <a-select v-model="searchForm.status" placeholder="请选择状态" allow-clear style="width: 150px;">
            <a-option label="在线" value="ONLINE" />
            <a-option label="离线" value="OFFLINE" />
          </a-select>
        </a-form-item>
        <a-form-item>
          <a-space>
            <a-button type="primary" @click="handleSearch">
              <template #icon><icon-search /></template> 查询
            </a-button>
            <a-button @click="handleReset">
              <template #icon><icon-refresh /></template> 重置
            </a-button>
            <a-upload action="/" :auto-upload="false" :show-file-list="false" @change="handleImport">
                <template #upload-button>
                    <a-button>
                        <template #icon><icon-upload /></template> 导入
                    </a-button>
                </template>
            </a-upload>
            <a-button @click="handleExport">
                <template #icon><icon-download /></template> 导出
            </a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </div>

    <div class="main-content">
      <!-- Device Table -->
      <a-table
        :data="devices"
        :loading="loading"
        row-key="ID"
        :row-selection="rowSelection"
        v-model:selectedKeys="selectedDeviceKeys"
        :pagination="pagination"
        @page-change="onPageChange"
        @page-size-change="onPageSizeChange"
        :scroll="{ y: 'calc(100vh - 250px)' }"
        :bordered="{ cell: true }"
      >
        <template #columns>
          <a-table-column title="设备名称" data-index="Name" :width="200" />
          <a-table-column title="原始标识" data-index="ExternalID" :width="200" ellipsis tooltip />
          <a-table-column title="状态" :width="100">
             <template #cell="{ record }">
                 <a-badge v-if="record.Status === 'ONLINE'" status="success" text="在线" />
                 <a-badge v-else status="normal" text="离线" />
             </template>
          </a-table-column>
          <a-table-column title="类型" data-index="DeviceType" :width="120">
             <template #cell="{ record }">
                 {{ getDeviceTypeName(record.DeviceType) }}
             </template>
          </a-table-column>
          <a-table-column title="空间位置" data-index="LocationID" :width="150">
             <template #cell="{ record }">
                 {{ getLocationName(record.LocationID) }}
             </template>
          </a-table-column>
          <a-table-column title="操作" :width="200" fixed="right">
            <template #cell="{ record }">
               <a-space>
                 <a-button type="text" size="small" @click="handleMonitor(record)">
                    实时状态
                 </a-button>
                 <a-button type="text" size="small" @click="openDataChart(record)">
                    <template #icon><icon-bar-chart /></template>
                 </a-button>
                 <a-button type="text" size="small" @click="editDevice(record)">编辑</a-button>
                 <a-popconfirm content="确定要删除该设备吗？" @ok="handleDelete(record)">
                    <a-button type="text" status="danger" size="small">删除</a-button>
                 </a-popconfirm>
               </a-space>
            </template>
          </a-table-column>
        </template>
      </a-table>
    </div>

    <!-- Bottom Toolbar -->
    <div class="bottom-toolbar" v-if="selectedDeviceKeys.length > 0">
      <span class="selected-count">已选 {{ selectedDeviceKeys.length }} 个设备</span>
      <a-divider direction="vertical" />
      <a-button type="primary" status="success" @click="openLocationDialog" style="margin-left: 10px;">
         <template #icon><icon-location /></template> 批量关联空间
      </a-button>
      <a-button type="primary" status="warning" @click="openSourceDialog" style="margin-left: 10px;">
         <template #icon><icon-swap /></template> 批量更换数据源
      </a-button>
      <a-popconfirm content="确定要删除选中的设备吗？" @ok="handleBatchDelete">
          <a-button type="primary" status="danger" style="margin-left: 10px;">
             <template #icon><icon-delete /></template> 批量删除
          </a-button>
      </a-popconfirm>
      <div style="flex-grow: 1"></div>
    </div>

    <!-- Virtual Meter Dialog Removed -->

    <!-- Source Dialog -->
    <a-modal v-model:visible="sourceDialogVisible" title="批量更换数据源" @ok="applySource" @cancel="sourceDialogVisible = false">
        <a-select v-model="batchSourceID" placeholder="请选择数据源" allow-clear>
            <a-option v-for="s in sources" :key="s.ID" :label="s.Name" :value="s.ID" />
        </a-select>
    </a-modal>

    <!-- Location Dialog -->
    <a-modal v-model:visible="locationDialogVisible" title="批量关联空间" @ok="applyLocation" @cancel="locationDialogVisible = false">
        <a-tree-select
           v-model="batchLocationID"
           :data="locationTree"
           :field-names="{ key: 'ID', title: 'Name', children: 'children' }"
           style="width: 100%"
           placeholder="请选择空间"
           allow-clear
        />
    </a-modal>

    <!-- Edit Dialog -->
    <a-modal v-model:visible="editVisible" title="设备清洗与配置" @ok="handleEditOk" @cancel="editVisible = false" width="800px">
        <a-form :model="editForm" layout="vertical">
            <a-form-item label="设备名称" field="Name">
                <a-input v-model="editForm.Name" />
            </a-form-item>
            <a-form-item label="原始标识" field="ExternalID">
                <a-input v-model="editForm.ExternalID" disabled />
            </a-form-item>
            
            <a-alert type="info" style="margin-bottom: 10px">配置设备属性映射与清洗规则。</a-alert>
                 
            <div v-for="(row, index) in attributeRows" :key="index" style="display: flex; gap: 10px; margin-bottom: 10px; align-items: center">
               <div style="width: 100px; flex-shrink: 0; text-align: right; padding-right: 10px;">
                   <span style="font-weight: bold; white-space: nowrap;">{{ getAttributeLabel(row.key) }}</span>
                   <div style="font-size: 12px; color: var(--color-text-3)" v-if="getAttributeUnit(row.key)">
                       ({{ getAttributeUnit(row.key) }})
                   </div>
               </div>
               <div style="width: 350px; flex-shrink: 0">
                   <a-select 
                       v-model="row.source" 
                       placeholder="选择数据源 (HA实体)" 
                       allow-search 
                       allow-clear
                       style="width: 100%"
                   >
                       <a-option v-for="ent in candidateEntities" :key="ent.entity_id" :value="ent.entity_id">
                           {{ ent.attributes?.friendly_name || ent.entity_id }} ({{ ent.entity_id }})
                       </a-option>
                   </a-select>
               </div>
               <div style="flex: 1">
                   <a-input v-if="row.key !== 'switch'" v-model="row.formula" placeholder="清洗公式 (如 x/1000)" style="width: 100%">
                        <template #prepend>f(x)=</template>
                   </a-input>
                   <div v-else style="line-height: 32px; color: #86909c; padding-left: 10px;">
                        无需公式 (默认: 1/0)
                   </div>
               </div>
            </div>
            
            <div v-if="attributeRows.length === 0" style="color: var(--color-text-3); text-align: center; padding: 20px; background: var(--color-fill-2)">
               暂无标准属性
            </div>

            <a-form-item label="空间位置" field="LocationID" style="margin-top: 20px">
                 <a-tree-select
                   v-model="editForm.LocationID"
                   :data="locationTree"
                   :field-names="{ key: 'ID', title: 'Name', children: 'children' }"
                   placeholder="请选择空间"
                   allow-clear
                />
            </a-form-item>
        </a-form>
    </a-modal>

    <!-- Data Chart Modal -->
    <a-modal v-model:visible="chartVisible" title="历史数据趋势" width="90%" :footer="false" @open="initChart" unmount-on-close>
        <div style="margin-bottom: 20px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center">
            <a-range-picker 
                v-model="dateRange" 
                show-time 
                format="YYYY-MM-DD HH:mm:ss" 
                :shortcuts="rangeShortcuts"
                style="width: 380px" 
                @change="fetchChartData"
            />
            
            <a-button-group>
                <a-button @click="shiftDateRange(-1)">
                    <template #icon><icon-left /></template>
                </a-button>
                <a-button @click="shiftDateRange(1)">
                    <template #icon><icon-right /></template>
                </a-button>
            </a-button-group>

            <a-select v-model="chartMetric" placeholder="指标" style="width: 150px" @change="fetchChartData">
                 <a-option v-for="attr in standardAttributes" :key="attr.value" :value="attr.value" :label="attr.label" />
            </a-select>

            <div style="flex: 1"></div>

            <a-button type="primary" status="danger" @click="openDeleteDialog">
                 <template #icon><icon-delete /></template> 删除数据
            </a-button>
        </div>
        <div ref="chartRef" style="width: 100%; height: 600px;"></div>
    </a-modal>

    <!-- Delete Data Dialog -->
    <a-modal v-model:visible="deleteDialogVisible" title="删除历史数据" @ok="handleDeleteData" @cancel="deleteDialogVisible = false">
        <a-alert type="warning" style="margin-bottom: 20px">
            警告：删除操作不可恢复，请谨慎操作。
        </a-alert>
        <a-form layout="vertical">
            <a-form-item label="选择时间范围">
                <a-range-picker 
                    v-model="deleteDateRange" 
                    show-time 
                    format="YYYY-MM-DD HH:mm:ss" 
                    style="width: 100%" 
                />
            </a-form-item>
        </a-form>
    </a-modal>

    <!-- Config Dialog -->
    <a-modal v-model:visible="configDialogVisible" title="采集频率设置" @ok="saveConfig" @cancel="configDialogVisible = false">
        <a-form :model="configForm" layout="vertical">
            <a-alert type="info" style="margin-bottom: 20px">
                配置从 HA 查询数据并写入 TDengine 的频率。
            </a-alert>
            
            <a-form-item label="采集间隔 (秒)" field="interval">
                 <a-input-number v-model="configForm.interval" :min="1" :max="3600" placeholder="例如: 5" />
                 <template #extra>
                     设置多少秒执行一次采集任务。当前对应 Cron: {{ cronPreview }}
                 </template>
            </a-form-item>
            
            <a-collapse :default-active-key="[]" :bordered="false">
                 <a-collapse-item header="高级: 自定义 Cron 表达式" key="1">
                     <a-form-item label="Cron 表达式" field="cron">
                         <a-input v-model="configForm.cron" placeholder="*/5 * * * * *" />
                     </a-form-item>
                 </a-collapse-item>
            </a-collapse>
        </a-form>
    </a-modal>

  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue';
import { getDevices, getSources, getLocations, updateDevice, createDevice, getSourceDeviceEntities, getDeviceHistory, deleteDeviceHistory, deleteDevice } from '@/api/resource';
import { getConfig, updateConfig } from '@/api/system';
import type { Device, IntegrationSource, Location as LocType, HAEntity } from '@/api/resource';
import { IconRefresh, IconLocation, IconBarChart, IconLeft, IconRight, IconDelete, IconSearch, IconUpload, IconDownload, IconSwap, IconSettings } from '@arco-design/web-vue/es/icon';
import * as echarts from 'echarts';
import * as XLSX from 'xlsx';

// --- State ---
const router = useRouter();
const loading = ref(false);
const devices = ref<Device[]>([]);
const sources = ref<IntegrationSource[]>([]);
const locations = ref<LocType[]>([]);
const searchForm = reactive({
  name: '',
  deviceType: '',
  sourceId: '',
  status: ''
});
const selectedDeviceKeys = ref<string[]>([]);
const rowSelection = reactive({ type: 'checkbox', showCheckedAll: true, onlyCurrent: false });

const pagination = reactive({
  current: 1,
  pageSize: 20,
  showPageSize: true,
  pageSizeOptions: [10, 20, 50, 100],
  showTotal: true,
  showJumper: true
});

const onPageChange = (current: number) => {
  pagination.current = current;
};

const onPageSizeChange = (pageSize: number) => {
  pagination.current = 1;
  pagination.pageSize = pageSize;
};

// --- Constant: Device Types ---
const deviceTypeOptions = [
    { label: '电力设备', value: 'ELECTRIC' },
    { label: '水务设备', value: 'WATER' },
    { label: '燃气设备', value: 'GAS' },
    { label: '工业电力设备', value: 'INDUSTRIAL_ELECTRIC' },
];

const getDeviceTypeName = (type: string) => {
    const found = deviceTypeOptions.find(opt => opt.value === type);
    return found ? found.label : type;
};

const locationDialogVisible = ref(false);
const batchLocationID = ref('');

const sourceDialogVisible = ref(false);
const batchSourceID = ref('');

const editVisible = ref(false);
const editForm = reactive<Partial<Device>>({
    Name: '',
    AttributeMapping: {},
    LocationID: ''
});
const candidateEntities = ref<HAEntity[]>([]);
const attributeRows = ref<{ key: string; source: string; formula: string }[]>([]);

// Chart State
const chartVisible = ref(false);
const chartRef = ref<HTMLElement | null>(null);
const chartInstance = ref<echarts.ECharts | null>(null);
const chartDevice = ref<Device | null>(null);
const chartMetric = ref('energy');
const chartInterval = ref('1h');
const dateRange = ref<any[]>([]); // Array of Date or strings
const chartLoading = ref(false);
const currentRequestId = ref(0);

// Delete Dialog State
const deleteDialogVisible = ref(false);
const deleteDateRange = ref<any[]>([]);

const shiftDateRange = (direction: number) => {
    if (!dateRange.value || dateRange.value.length !== 2) return;
    
    const start = new Date(dateRange.value[0]);
    const end = new Date(dateRange.value[1]);
    const span = end.getTime() - start.getTime();
    
    const newStart = new Date(start.getTime() + direction * span);
    const newEnd = new Date(end.getTime() + direction * span);
    
    dateRange.value = [newStart, newEnd];
    fetchChartData();
};

const rangeShortcuts = [
    {
        label: '近1小时',
        value: () => [new Date(Date.now() - 3600 * 1000), new Date()],
    },
    {
        label: '近12小时',
        value: () => [new Date(Date.now() - 12 * 3600 * 1000), new Date()],
    },
    {
        label: '近24小时',
        value: () => [new Date(Date.now() - 24 * 3600 * 1000), new Date()],
    },
    {
        label: '近7天',
        value: () => [new Date(Date.now() - 7 * 24 * 3600 * 1000), new Date()],
    },
    {
        label: '近1个月',
        value: () => [new Date(Date.now() - 30 * 24 * 3600 * 1000), new Date()],
    },
    {
        label: '近1年',
        value: () => [new Date(Date.now() - 365 * 24 * 3600 * 1000), new Date()],
    },
];

const standardAttributes = [
    { label: '开关状态', value: 'switch', unit: '' },
    { label: '有功功率', value: 'power', unit: 'W' },
    { label: '电压', value: 'voltage', unit: 'V' },
    { label: '电流', value: 'current', unit: 'A' },
    { label: '累计用电', value: 'energy', unit: 'kWh' },
    { label: '温度', value: 'temperature', unit: '°C' },
];

// --- Config State ---
const configDialogVisible = ref(false);
const configForm = reactive({
    interval: 5,
    cron: '*/5 * * * * *'
});

const cronPreview = computed(() => {
    return `*/${configForm.interval} * * * * *`;
});

const openConfigDialog = async () => {
    try {
        const res = await getConfig('collection_frequency');
        const config = (res as any).data || res;
        if (config && config.ConfigValue) {
            configForm.cron = config.ConfigValue;
            const match = config.ConfigValue.match(/^\*\/(\d+)\s/);
            if (match) {
                configForm.interval = parseInt(match[1]);
            }
        }
        configDialogVisible.value = true;
    } catch (e) {
        // If 404, assume default
        configDialogVisible.value = true;
    }
};

const saveConfig = async () => {
    let finalCron = configForm.cron;
    // If cron looks like default pattern, sync with interval
    if (finalCron.startsWith('*/') && finalCron.endsWith('* * * * *')) {
         finalCron = `*/${configForm.interval} * * * * *`;
    }

    try {
        await updateConfig({
            ConfigKey: 'collection_frequency',
            ConfigValue: finalCron,
            ConfigType: 'Y',
            Remark: `每 ${configForm.interval} 秒采集一次`
        });
        
        Message.success('配置已更新，采集服务将重启生效');
        configDialogVisible.value = false;
    } catch (e: any) {
        if (e.response && e.response.data && e.response.data.warning) {
             Message.warning(e.response.data.warning);
             configDialogVisible.value = false;
        } else {
             Message.error('保存失败');
        }
    }
};

// --- Lifecycle ---
onMounted(async () => {
  await Promise.all([loadSources(), loadLocations()]);
  loadData();
});

// --- Data Loading ---
const loadSources = async () => {
    const res = await getSources();
    sources.value = (res as any).data || res;
};

const loadLocations = async () => {
    const res = await getLocations();
    locations.value = (res as any).data || res;
};

// Simple Tree Builder
const locationTree = computed(() => {
    const list = locations.value;
    const map = new Map<string, any>();
    const roots: any[] = [];
    list.forEach(item => {
        map.set(item.ID, { ...item, children: [] });
    });
    list.forEach(item => {
        const node = map.get(item.ID)!;
        if (item.ParentID && map.has(item.ParentID)) {
            map.get(item.ParentID)!.children!.push(node);
        } else {
            roots.push(node);
        }
    });
    return roots;
});

const loadData = async () => {
  loading.value = true;
  try {
    const params = {
      name: searchForm.name,
      device_type: searchForm.deviceType,
      source_id: searchForm.sourceId,
      status: searchForm.status
    };
    const res = await getDevices(params);
    const allDevices = (res as any).data || res;
    devices.value = allDevices;
  } catch (error) {
    Message.error('加载设备列表失败');
  } finally {
    loading.value = false;
  }
};

const handleSearch = () => {
  pagination.current = 1;
  loadData();
};

const handleReset = () => {
  searchForm.name = '';
  searchForm.deviceType = '';
  searchForm.sourceId = '';
  searchForm.status = '';
  pagination.current = 1;
  loadData();
};

// --- Import / Export ---

const handleExport = () => {
    const data = devices.value.map(d => ({
        Name: d.Name,
        DeviceType: d.DeviceType,
        ExternalID: d.ExternalID,
        LocationID: d.LocationID,
        Status: d.Status,
        SourceID: d.SourceID,
        AttributeMapping: JSON.stringify(d.AttributeMapping || {})
    }));

    const ws = XLSX.utils.json_to_sheet(data);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Devices");
    XLSX.writeFile(wb, `devices_export_${new Date().toISOString().slice(0,10)}.xlsx`);
};

const handleImport = (fileList: any[]) => {
    // arco-design upload returns fileList on change
    const fileItem = fileList[fileList.length - 1];
    if (!fileItem || !fileItem.file) return;

    const reader = new FileReader();
    reader.onload = async (e) => {
        try {
            const data = e.target?.result;
            const workbook = XLSX.read(data, { type: 'array' });
            const firstSheetName = workbook.SheetNames[0];
            const worksheet = workbook.Sheets[firstSheetName];
            const jsonData = XLSX.utils.sheet_to_json(worksheet);
            
            let successCount = 0;
            loading.value = true;

            for (const item of jsonData as any[]) {
                 const deviceData: any = {
                    Name: item.Name,
                    DeviceType: item.DeviceType,
                    ExternalID: item.ExternalID,
                    LocationID: item.LocationID,
                    Status: item.Status,
                    SourceID: item.SourceID,
                    AttributeMapping: item.AttributeMapping ? JSON.parse(item.AttributeMapping) : {}
                 };

                if (deviceData.Name && deviceData.DeviceType) {
                    try {
                        await createDevice(deviceData);
                        successCount++;
                    } catch (err) {
                        console.error('Import row failed', err);
                    }
                }
            }
            
            Message.success(`成功导入 ${successCount} 个设备`);
            loadData();
        } catch (err) {
            console.error(err);
            Message.error('文件解析失败');
        } finally {
            loading.value = false;
        }
    };
    reader.readAsArrayBuffer(fileItem.file);
};

const openSourceDialog = () => {
    sourceDialogVisible.value = true;
};

const applySource = async () => {
    if (!batchSourceID.value) {
        Message.warning('请选择数据源');
        return;
    }
    
    loading.value = true;
    let successCount = 0;
    try {
        for (const id of selectedDeviceKeys.value) {
            try {
                await updateDevice(id, { SourceID: batchSourceID.value });
                successCount++;
            } catch(e) {
                console.error(e);
            }
        }
        Message.success(`成功更新 ${successCount} 个设备的数据源`);
        sourceDialogVisible.value = false;
        loadData();
        selectedDeviceKeys.value = [];
    } catch (err) {
        Message.error('批量操作失败');
    } finally {
        loading.value = false;
    }
};

const getLocationName = (id?: string) => {
    if(!id) return '-';
    const loc = locations.value.find(l => l.ID === id);
    return loc ? loc.Name : id;
};

const getAttributeLabel = (key: string) => {
    const attr = standardAttributes.find(a => a.value === key);
    return attr ? attr.label : key;
};

const getAttributeUnit = (key: string) => {
    const attr = standardAttributes.find(a => a.value === key);
    return attr ? attr.unit : '';
};

// --- Chart Methods ---

const handleMonitor = (record: Device) => {
  router.push({ name: 'DeviceLive', params: { id: record.ID } });
};

const openDataChart = (record: Device) => {
    chartDevice.value = record;
    chartVisible.value = true;
    
    // Default range: last 1h
    const end = new Date();
    const start = new Date();
    start.setTime(start.getTime() - 3600 * 1000);
    dateRange.value = [start, end]; 
};

const initChart = () => {
    // Wait for DOM
    setTimeout(() => {
        if (chartRef.value) {
            if (chartInstance.value) {
                chartInstance.value.dispose();
            }
            chartInstance.value = echarts.init(chartRef.value);
            // Default load
            fetchChartData();
        }
    }, 100);
};

const openDeleteDialog = () => {
    // Default to current chart range
    if (dateRange.value && dateRange.value.length === 2) {
        deleteDateRange.value = [...dateRange.value];
    } else {
        deleteDateRange.value = [];
    }
    deleteDialogVisible.value = true;
};

const handleDeleteData = async () => {
    if (!deleteDateRange.value || deleteDateRange.value.length !== 2) {
        Message.warning('请选择要删除的时间范围');
        return;
    }
    
    if (!chartDevice.value) return;

    try {
        const startStr = new Date(deleteDateRange.value[0]).toISOString();
        const endStr = new Date(deleteDateRange.value[1]).toISOString();

        await deleteDeviceHistory({
            device_id: chartDevice.value.ID,
            metric: chartMetric.value,
            start: startStr,
            end: endStr
        });
        
        Message.success('数据删除成功');
        deleteDialogVisible.value = false;
        fetchChartData(); // Refresh chart
    } catch (err) {
        Message.error('删除失败');
    }
};

const fetchChartData = async () => {
    if (!chartDevice.value) return;

    const requestId = ++currentRequestId.value;
    
    // Validate range
    let startStr = '';
    let endStr = '';
    
    if (dateRange.value && dateRange.value.length === 2) {
        startStr = new Date(dateRange.value[0]).toISOString();
        endStr = new Date(dateRange.value[1]).toISOString();
    } else {
        // Fallback default
        const end = new Date();
        const start = new Date(end.getTime() - 60 * 60 * 1000);
        startStr = start.toISOString();
        endStr = end.toISOString();
        // Update model to reflect default
        dateRange.value = [start, end];
    }
    
    // Auto-calculate interval
    const s = new Date(startStr);
    const e = new Date(endStr);
    const diffMs = e.getTime() - s.getTime();
    const diffHours = diffMs / (1000 * 3600);
    
    if (diffHours <= 1) {
        chartInterval.value = '1m';
    } else if (diffHours <= 12) {
        chartInterval.value = '15m';
    } else if (diffHours <= 24) {
        chartInterval.value = '1h';
    } else if (diffHours <= 24 * 7) {
        chartInterval.value = '6h';
    } else {
        chartInterval.value = '1d';
    }
    
    chartLoading.value = true;
    if (chartInstance.value) {
        chartInstance.value.showLoading();
    }
    try {
        const res = await getDeviceHistory({
            device_ids: chartDevice.value.ID,
            metric: chartMetric.value,
            start: startStr,
            end: endStr,
            interval: chartInterval.value
        });

        if (requestId !== currentRequestId.value) return;

        const data = (res as any).data || res;
        
        renderChart(data);
    } catch (e) {
        if (requestId === currentRequestId.value) {
            Message.error('获取数据失败');
        }
    } finally {
        if (requestId === currentRequestId.value) {
            chartLoading.value = false;
            if (chartInstance.value) {
                chartInstance.value.hideLoading();
            }
        }
    }
};

const renderChart = (data: any[]) => {
    if (!chartInstance.value) return;
    chartInstance.value.clear();
    
    const dates = data.map(item => item.ts);
    const isState = chartMetric.value === 'state' || chartMetric.value === 'switch';
    
    const grid = {
        left: '3%',
        right: '4%',
        bottom: '10%',
        top: '10%',
        containLabel: true,
        show: true,
        borderColor: '#E5E6EB'
    };

    let option: any = {};

    if (isState) {
        option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: { type: 'line' },
                confine: true,
                formatter: (params: any) => {
                    if (!params || params.length === 0) return '';
                    const item = params[0];
                    const val = item.value;
                    const status = val >= 1 ? '开启 (ON)' : '关闭 (OFF)';
                    return `<div style="margin-bottom: 4px; font-weight: bold">${item.name}</div>
                            <div>${item.marker} ${item.seriesName}: <span style="font-weight: bold; color: #165DFF">${status}</span></div>`;
                }
            },
            grid: grid,
            xAxis: {
                type: 'category',
                data: dates,
                boundaryGap: false,
                splitLine: { show: true, lineStyle: { color: '#E5E6EB' } }
            },
            yAxis: {
                type: 'value',
                minInterval: 1,
                max: 1.5,
                min: 0,
                axisLabel: {
                    formatter: (value: number) => {
                        if (value === 0) return 'OFF';
                        if (value === 1) return 'ON';
                        return '';
                    }
                },
                splitLine: { show: true, lineStyle: { type: 'dashed', color: '#E5E6EB' } }
            },
            legend: {
                data: [getAttributeLabel(chartMetric.value)],
                bottom: 0
            },
            series: [
                {
                    name: getAttributeLabel(chartMetric.value),
                    type: 'line',
                    step: 'start',
                    data: data.map(item => item.close),
                    itemStyle: { color: '#165DFF' },
                    areaStyle: {
                        opacity: 0.2,
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                          { offset: 0, color: 'rgba(22, 93, 255, 0.5)' },
                          { offset: 1, color: 'rgba(22, 93, 255, 0.1)' }
                        ])
                    }
                }
            ]
        };
    } else {
        const values = data.map(item => item.close);
        
        option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: { 
                    type: 'line',
                    label: {
                        backgroundColor: '#6a7985'
                    }
                },
                confine: true,
                backgroundColor: 'rgba(255, 255, 255, 0.9)',
                borderColor: '#E5E6EB',
                borderWidth: 1,
                textStyle: {
                    color: '#1D2129'
                },
                formatter: (params: any) => {
                     if (!params || params.length === 0) return '';
                     const item = params[0];
                     return `<div style="margin-bottom: 4px; font-weight: bold">${item.name}</div>
                             <div>${item.marker} ${item.seriesName}: <span style="font-weight: bold; color: #165DFF">${item.value} ${getAttributeUnit(chartMetric.value)}</span></div>`;
                }
            },
            grid: grid,
            legend: {
                data: [getAttributeLabel(chartMetric.value)],
                bottom: 0
            },
            xAxis: {
                type: 'category',
                data: dates,
                boundaryGap: false,
                splitLine: { show: true, lineStyle: { color: '#E5E6EB' } },
                axisLine: { lineStyle: { color: '#86909C' } },
                axisLabel: { color: '#4E5969' }
            },
            yAxis: {
                type: 'value',
                name: getAttributeUnit(chartMetric.value),
                splitLine: { show: true, lineStyle: { type: 'dashed', color: '#E5E6EB' } },
                axisLabel: { color: '#4E5969' }
            },
            series: [
                {
                    name: getAttributeLabel(chartMetric.value),
                    type: 'line',
                    data: values,
                    smooth: true,
                    showSymbol: true,
                    symbol: 'circle',
                    symbolSize: 6,
                    emphasis: {
                        focus: 'series',
                        itemStyle: {
                            shadowBlur: 10,
                            shadowColor: 'rgba(0,0,0,0.3)'
                        }
                    },
                    itemStyle: {
                        color: '#165DFF'
                    },
                    lineStyle: {
                        width: 2
                    }
                }
            ]
        };
    }
    
    chartInstance.value.setOption(option, true);
};

// --- Interactions ---

const openLocationDialog = () => {
    locationDialogVisible.value = true;
};

const applyLocation = async () => {
     for (const id of selectedDeviceKeys.value) {
        await updateDevice(id, { LocationID: batchLocationID.value });
    }
    Message.success('批量关联成功');
    locationDialogVisible.value = false;
    loadData();
    selectedDeviceKeys.value = [];
};

const editDevice = async (row: Device) => {
    Object.assign(editForm, JSON.parse(JSON.stringify(row)));
    // Ensure AttributeMapping exists
    if (!editForm.AttributeMapping) {
        editForm.AttributeMapping = {};
    }
    
    // Parse AttributeMapping into rows
    attributeRows.value = [];
    const map = editForm.AttributeMapping;

    // Load ALL standard attributes
    standardAttributes.forEach(attr => {
        attributeRows.value.push({
            key: attr.value,
            source: map[attr.value] || '',
            formula: map[`${attr.value}_formula`] || ''
        });
    });

    editVisible.value = true;
    
    // Fetch candidates if we have SourceID and ExternalID (Device ID in HA)
    if (row.SourceID && row.ExternalID) {
        try {
            const res = await getSourceDeviceEntities(row.SourceID, row.ExternalID);
            candidateEntities.value = (res as any).data || res;
        } catch (e) {
            candidateEntities.value = [];
            Message.warning('无法加载关联的HA实体列表');
        }
    } else {
        candidateEntities.value = [];
    }
};

const handleEditOk = async () => {
    if (!editForm.ID) return;
    
    // Validation for ELECTRIC type
    if (editForm.DeviceType === 'ELECTRIC') {
        const requiredMetrics = ['voltage', 'current', 'power', 'energy'];
        for (const metric of requiredMetrics) {
            const row = attributeRows.value.find(r => r.key === metric);
            if (row) {
                if (!row.source && !row.formula) {
                    Message.warning(`电力设备属性 [${getAttributeLabel(metric)}] 未绑定实体时，必须填写公式`);
                    return;
                }
            }
        }
    }
    
    // Reconstruct AttributeMapping
    const newMap: Record<string, string> = {};
    
    // If ELECTRIC, ensure structure
    if (editForm.DeviceType === 'ELECTRIC') {
         const keys = ['switch', 'voltage', 'current', 'power', 'energy'];
         keys.forEach(k => {
             newMap[k] = '';
             if (k !== 'switch') newMap[`${k}_formula`] = '';
         });
    }

    attributeRows.value.forEach(row => {
        // Save if source is present OR formula is present OR it's a required electric key
        if (row.key) {
            newMap[row.key] = row.source || ''; 
            if (row.formula) {
                newMap[`${row.key}_formula`] = row.formula;
            }
        }
    });
    editForm.AttributeMapping = newMap;

    try {
        await updateDevice(editForm.ID, editForm);
        Message.success('设备配置已更新');
        editVisible.value = false;
        loadData();
    } catch (err) {
        Message.error('更新失败');
    }
};

const handleDelete = async (record: Device) => {
    try {
        await deleteDevice(record.ID);
        Message.success('删除成功');
        loadData();
    } catch (error) {
        Message.error('删除失败');
    }
};

const handleBatchDelete = async () => {
    if (selectedDeviceKeys.value.length === 0) return;
    
    loading.value = true;
    let successCount = 0;
    try {
        for (const id of selectedDeviceKeys.value) {
            try {
                await deleteDevice(id);
                successCount++;
            } catch (e) {
                console.error(e);
            }
        }
        Message.success(`成功删除 ${successCount} 个设备`);
        selectedDeviceKeys.value = [];
        loadData();
    } catch (err) {
        Message.error('批量删除失败');
    } finally {
        loading.value = false;
    }
};


</script>

<style scoped>
.page-container {
  padding: 20px;
  height: 100vh;
  display: flex;
  flex-direction: column;
}
.header {
  margin-bottom: 20px;
}
.filter-bar {
  margin-bottom: 20px;
  padding: 20px;
  background: var(--color-bg-2);
  border-radius: 4px;
}
.main-content {
    flex: 1;
    overflow: hidden;
}
.bottom-toolbar {
    height: 60px;
    background: var(--color-bg-2);
    border-top: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    padding: 0 20px;
    gap: 10px;
    position: fixed;
    bottom: 0;
    right: 0;
    left: 240px; /* Sidebar width assumption */
    z-index: 100;
    box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}
.selected-count {
    font-weight: bold;
    color: rgb(var(--primary-6));
}
</style>
