<template>
    <div class="water-page">
        <div class="page-heading">
            <div class="page-title">
                <span class="page-title-icon"><el-icon><component :is="pageIcon"/></el-icon></span>
                <div>
                    <h2>{{ title }}</h2>
                    <span class="muted">按时间与数值范围查询实时点位，并查看趋势明细</span>
                </div>
            </div>
            <el-button class="heading-refresh" :icon="Refresh" :loading="loading" @click="loadData">刷新</el-button>
        </div>

        <el-card shadow="never" class="filter-card">
            <template #header>
                <div class="card-title">
                    <el-icon><Search/></el-icon>
                    <span>监测数据筛选</span>
                </div>
            </template>
            <el-form :inline="true" :model="query" @submit.prevent="loadData">
                <el-form-item label="设备名称">
                    <el-input v-model="query.equipmentName" clearable placeholder="请输入设备名称"/>
                </el-form-item>
                <el-form-item label="设备编码">
                    <el-input v-model="query.equipmentCode" clearable placeholder="请输入设备编码"/>
                </el-form-item>
                <el-form-item label="安装位置">
                    <el-input v-model="query.equipmentLocation" clearable placeholder="请输入位置"/>
                </el-form-item>
                <el-form-item label="采集时间">
                    <el-date-picker
                            v-model="query.timeRange"
                            type="datetimerange"
                            range-separator="至"
                            start-placeholder="开始时间"
                            end-placeholder="结束时间"
                            value-format="YYYY-MM-DD HH:mm:ss"
                            format="YYYY-MM-DD HH:mm:ss"
                            clearable
                    />
                </el-form-item>
                <el-form-item :label="rangeLabel">
                    <el-input-number v-model="query[minKey]" :min="0" controls-position="right"/>
                    <span class="range-sep">至</span>
                    <el-input-number v-model="query[maxKey]" :min="0" controls-position="right"/>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" :icon="Search" :loading="loading" @click="loadData">查询</el-button>
                    <el-button :icon="RefreshLeft" @click="resetQuery">重置</el-button>
                </el-form-item>
            </el-form>
        </el-card>

        <el-alert
                v-if="loadError"
                class="page-error"
                type="error"
                show-icon
                :closable="false"
                title="监测数据加载失败"
                description="请检查后端服务或网络连接后重试。"
        >
            <el-button size="small" type="primary" @click="loadData">重试</el-button>
        </el-alert>

        <div class="metric-grid">
            <div class="metric">
                <div class="metric-icon metric-icon--blue"><el-icon><Monitor/></el-icon></div>
                <div class="metric-body">
                    <span>监测点位</span>
                    <div class="metric-value"><strong>{{ page.total }}</strong><small>个</small></div>
                </div>
            </div>
            <div class="metric">
                <div class="metric-icon metric-icon--cyan"><el-icon><DataAnalysis/></el-icon></div>
                <div class="metric-body">
                    <span>当前均值</span>
                    <div class="metric-value"><strong>{{ averageValue }}</strong><small>{{ unit }}</small></div>
                </div>
            </div>
            <div class="metric">
                <div class="metric-icon metric-icon--orange"><el-icon><Warning/></el-icon></div>
                <div class="metric-body">
                    <span>异常点位</span>
                    <div class="metric-value"><strong class="danger">{{ abnormalCount }}</strong><small>个</small></div>
                </div>
            </div>
            <div class="metric">
                <div class="metric-icon metric-icon--slate"><el-icon><Clock/></el-icon></div>
                <div class="metric-body">
                    <span>数据更新时间</span>
                    <div class="metric-value"><strong class="time">{{ latestTime }}</strong></div>
                </div>
            </div>
        </div>

        <el-card shadow="never" class="table-card">
            <template #header>
                <div class="table-toolbar">
                    <div class="card-title">
                        <el-icon><DataLine/></el-icon>
                        <span>{{ title }}点位清单</span>
                    </div>
                    <el-button
                            v-hasPermi="[exportPermission]"
                            type="success"
                            plain
                            :icon="Download"
                            :loading="exportLoading"
                            @click="exportData"
                    >批量导出</el-button>
                </div>
            </template>
            <el-table :data="page.records" stripe border v-loading="loading" @row-click="showTrend">
                <template #empty>
                    <el-empty :description="loadError ? '暂无法获取监测数据' : '暂无符合条件的监测数据'"/>
                </template>
                <el-table-column type="index" label="#" width="55"/>
                <el-table-column prop="equipmentCode" label="设备编码" min-width="130"/>
                <el-table-column prop="equipmentName" label="设备名称" min-width="150" show-overflow-tooltip/>
                <el-table-column prop="equipmentTypeName" label="设备子类型" min-width="145" show-overflow-tooltip/>
                <el-table-column prop="location" label="安装位置" min-width="180" show-overflow-tooltip/>
                <el-table-column :label="`${metricLabel}(${unit})`" min-width="130">
                    <template #default="{ row }">
            <span :class="{ danger: row.value == null || row.status === 1 || row.status === '1' }">
              {{ row.value ?? '-' }}
            </span>
                    </template>
                </el-table-column>
                <el-table-column label="状态" width="90">
                    <template #default="{ row }">
                        <el-tag :type="statusType(row)">{{ statusText(row) }}</el-tag>
                    </template>
                </el-table-column>
                <el-table-column prop="updateTime" label="采集时间" min-width="165"/>
                <el-table-column label="操作" width="90" fixed="right">
                    <template #default="{ row }">
                        <el-button class="trend-button" link type="primary" @click.stop="showTrend(row)">
                            <el-icon><TrendCharts/></el-icon>
                            <span>趋势</span>
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination
                    v-model:current-page="query.pageNum"
                    v-model:page-size="query.pageSize"
                    :total="page.total"
                    layout="total, sizes, prev, pager, next"
                    :page-sizes="[10, 20, 50]"
                    @change="loadData"
            />
        </el-card>

        <el-drawer
                v-model="trendVisible"
                class="detail-drawer"
                direction="rtl"
                :title="`${current?.equipmentName || ''} - ${title}趋势`"
                size="520px"
        >
            <div v-loading="trendLoading" class="trend-body">
                <div v-show="trendRecords.length" ref="chartRef" class="trend-chart"/>
                <el-empty v-if="!trendLoading && !trendError && !trendRecords.length" description="暂无趋势数据"/>
                <el-alert
                        v-if="trendError"
                        type="error"
                        show-icon
                        :closable="false"
                        title="趋势数据加载失败"
                        description="请检查后端服务或网络连接后重试。"
                >
                    <el-button size="small" type="primary" @click="loadTrend">重试</el-button>
                </el-alert>
                <el-descriptions v-if="current" :column="1" border>
                    <el-descriptions-item label="设备编码">{{ current.equipmentCode }}</el-descriptions-item>
                    <el-descriptions-item label="安装位置">{{ current.location }}</el-descriptions-item>
                    <el-descriptions-item label="当前值">{{ current.value ?? '-' }} {{ current.unit }}
                    </el-descriptions-item>
                    <el-descriptions-item label="采集时间">{{ current.updateTime || '-' }}</el-descriptions-item>
                </el-descriptions>
            </div>
        </el-drawer>
    </div>
</template>
<script setup>
    import {computed, nextTick, onBeforeUnmount, onMounted, ref} from 'vue'
    import {
        Clock,
        DataAnalysis,
        DataLine,
        Download,
        Monitor,
        Refresh,
        RefreshLeft,
        Search,
        TrendCharts,
        Warning
    } from '@element-plus/icons-vue'
    import {ElMessage} from 'element-plus'
    import {saveAs} from 'file-saver'
    import * as echarts from 'echarts'
    import {normalizeMonitoringRecord, normalizePage, readMonitoringExportError, unwrapResponse} from '@/utils/waterSupplyModel'
    import {buildMonitoringQuery, buildTrendQuery} from '@/utils/waterSupplyMonitoringQuery'

    const props = defineProps({
        title: {type: String, required: true},
        metricLabel: {type: String, required: true},
        unit: {type: String, default: 'm³/h'},
        minKey: {type: String, default: 'flowMin'},
        maxKey: {type: String, default: 'flowMax'},
        rangeLabel: {type: String, default: '数值范围'},
        load: {type: Function, required: true},
        trend: {type: Function, required: true},
        exportApi: {type: Function, required: true},
        exportPermission: {type: String, required: true},
        metric: {type: String, default: 'value'},
        monitorType: {type: String, default: ''}
    })

    const pageIcon = computed(() => props.metric === 'pressure' ? Warning : props.metric === 'power' ? DataAnalysis : Monitor)
    const metricColor = computed(() => props.metric === 'pressure' ? '#f97316' : props.metric === 'power' ? '#06b6d4' : '#2563eb')
    const query = ref(createQuery())
    const page = ref({records: [], total: 0})
    const loading = ref(false)
    const loadError = ref(false)
    const exportLoading = ref(false)
    const current = ref(null)
    const trendVisible = ref(false)
    const trendLoading = ref(false)
    const trendError = ref(false)
    const trendRecords = ref([])
    const chartRef = ref(null)
    let chart

    function createQuery() {
        return {
            pageNum: 1,
            pageSize: 10,
            equipmentName: '',
            equipmentCode: '',
            equipmentLocation: '',
            timeRange: [],
            [props.minKey]: undefined,
            [props.maxKey]: undefined
        }
    }

    async function loadData() {
        loading.value = true
        loadError.value = false
        try {
            const response = await props.load(buildMonitoringQuery(query.value, props.minKey, props.maxKey))
            const normalized = normalizePage(response)
            normalized.records = normalized.records.map(row => normalizeMonitoringRecord(row, props.metric, props.monitorType))
            page.value = normalized
        } catch (error) {
            loadError.value = true
            console.warn(`[${props.title}] 数据加载失败`, error)
        } finally {
            loading.value = false
        }
    }

    function resetQuery() {
        query.value = createQuery()
        loadData()
    }

    const averageValue = computed(() => {
        const values = page.value.records.map(item => item.value).filter(value => Number.isFinite(value))
        return values.length ? (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) : '-'
    })
    const abnormalCount = computed(() => page.value.records.filter(item =>
        item.status === 1 || item.status === '1' || item.value == null
    ).length)
    const latestTime = computed(() =>
        page.value.records.map(item => item.updateTime).filter(Boolean).sort().at(-1) || '-'
    )

    function statusText(row) {
        if (row.status === 1 || row.status === '1') return '异常'
        if (row.status === 0 || row.status === '0') return '正常'
        return row.status ? '在线' : '未知'
    }

    function statusType(row) {
        const text = statusText(row)
        return text === '异常' ? 'danger' : text === '正常' || text === '在线' ? 'success' : 'info'
    }

    async function showTrend(row) {
        current.value = row
        trendVisible.value = true
        await loadTrend(true)
    }

    async function loadTrend(resetTrend = false) {
        if (!current.value?.id) return
        trendLoading.value = true
        trendError.value = false
        if (resetTrend) {
            trendRecords.value = []
            chart?.dispose()
            chart = undefined
        }
        try {
            const response = await props.trend(current.value.id, buildTrendQuery(query.value.timeRange))
            const data = unwrapResponse(response)
            const records = Array.isArray(data) ? data : data?.records || []
            trendRecords.value = records.map(item => normalizeMonitoringRecord(item, props.metric, props.monitorType))
            await nextTick()
            renderTrend()
        } catch (error) {
            trendError.value = true
            if (resetTrend) {
                chart?.dispose()
                chart = undefined
            }
            console.warn(`[${props.title}] 趋势数据加载失败`, error)
        } finally {
            trendLoading.value = false
        }
    }

    function renderTrend() {
        chart?.dispose()
        chart = undefined
        if (!trendRecords.value.length) return
        chart = echarts.init(chartRef.value)
        const labels = trendRecords.value.map(item => item.updateTime)
        const values = trendRecords.value.map(item => item.value ?? 0)
        const color = metricColor.value
        chart.setOption({
            tooltip: {
                trigger: 'axis',
                axisPointer: {type: 'line', lineStyle: {color: 'rgba(37, 99, 235, 0.25)'}}
            },
            grid: {left: 48, right: 20, top: 34, bottom: 38},
            xAxis: {
                type: 'category',
                data: labels,
                axisLine: {lineStyle: {color: '#cbd5e1'}},
                axisLabel: {color: '#64748b'},
                axisTick: {show: false}
            },
            yAxis: {
                type: 'value',
                name: props.unit,
                nameTextStyle: {color: '#64748b'},
                axisLine: {show: false},
                axisLabel: {color: '#64748b'},
                splitLine: {lineStyle: {color: '#e2e8f0', type: 'dashed'}}
            },
            series: [{
                type: 'line',
                smooth: true,
                data: values,
                symbol: 'circle',
                symbolSize: 7,
                lineStyle: {width: 3, color},
                itemStyle: {color, borderColor: '#fff', borderWidth: 2},
                areaStyle: {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                        {offset: 0, color: `${color}33`},
                        {offset: 1, color: `${color}05`}
                    ])
                }
            }]
        })
    }

    async function exportData() {
        exportLoading.value = true
        try {
            const response = await props.exportApi(buildMonitoringQuery(query.value, props.minKey, props.maxKey))
            const blob = response instanceof Blob
                ? response
                : new Blob([response], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
            const exportError = await readMonitoringExportError(blob)
            if (exportError) {
                ElMessage.error(exportError)
                return
            }
            if (!blob.size) throw new Error('导出文件为空')
            saveAs(blob, `${props.title}数据_${new Date().toISOString().slice(0, 10)}.xlsx`)
            ElMessage.success('导出完成')
        } catch (error) {
            console.warn(`[${props.title}] 导出失败`, error)
            ElMessage.error('导出失败，请稍后重试')
        } finally {
            exportLoading.value = false
        }
    }

    onMounted(loadData)
    onBeforeUnmount(() => {
        chart?.dispose()
        chart = undefined
    })
</script>

<style lang="scss">
    @use './waterSupplyPageTheme.scss';
</style>

<style scoped>
    .water-page {
        padding: 20px;
        background: linear-gradient(135deg, #eff6ff 0%, #f8fafc 45%, #eef2f7 100%);
        min-height: calc(100vh - 84px)
    }

    .page-heading {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 16px;
        margin-bottom: 16px
    }

    .page-title {
        display: flex;
        align-items: center;
        gap: 12px;
        min-width: 0;
    }

    .page-title-icon {
        display: grid;
        place-items: center;
        width: 42px;
        height: 42px;
        border-radius: 8px;
        color: #fff;
        background: linear-gradient(135deg, #2563eb 0%, #06b6d4 100%);
        box-shadow: 0 8px 16px rgba(37, 99, 235, 0.2);
    }

    .page-heading h2 {
        margin: 0 0 4px;
        font-size: 20px;
        color: #1e293b
    }

    .muted {
        font-size: 13px;
        color: #64748b
    }

    .heading-refresh {
        border-color: #bfdbfe;
        color: #2563eb;
        background: #fff;
    }

    .filter-card {
        margin-bottom: 16px;
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        box-shadow: 0 6px 14px rgba(15, 23, 42, 0.04)
    }

    .filter-card :deep(.el-form-item) {
        margin-top: 8px;
        margin-right: 16px;
        margin-bottom: 8px
    }

    .filter-card :deep(.el-form-item__label) {
        color: #475569
    }

    .range-sep {
        margin: 0 8px;
        color: #94a3b8
    }

    .page-error {
        margin-bottom: 16px
    }

    .metric-grid {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 14px;
        margin-bottom: 16px
    }

    .metric {
        display: flex;
        align-items: center;
        gap: 14px;
        min-width: 0;
        padding: 16px 18px;
        background: #fff;
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        box-shadow: 0 6px 14px rgba(15, 23, 42, 0.04)
    }

    .metric-icon {
        position: static;
        flex: 0 0 42px;
        display: grid;
        place-items: center;
        width: 42px;
        height: 42px;
        border-radius: 8px;
    }

    .metric-icon .el-icon {
        font-size: 22px;
    }

    .metric-icon--blue {
        color: #2563eb;
        background: linear-gradient(135deg, #dbeafe 0%, #eff6ff 100%);
    }

    .metric-icon--cyan {
        color: #0891b2;
        background: linear-gradient(135deg, #cffafe 0%, #ecfeff 100%);
    }

    .metric-icon--orange {
        color: #ea580c;
        background: linear-gradient(135deg, #ffedd5 0%, #fff7ed 100%);
    }

    .metric-icon--slate {
        color: #475569;
        background: linear-gradient(135deg, #e2e8f0 0%, #f8fafc 100%);
    }

    .metric-body {
        min-width: 0;
        text-align: left;
    }

    .metric-body span {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        margin-bottom: 3px;
        color: #64748b;
        font-size: 13px
    }

    .metric-value {
        display: flex;
        align-items: baseline;
        gap: 5px;
        min-width: 0;
    }

    .metric-value strong {
        font-size: 24px;
        line-height: 1.2;
        color: #1e293b;
    }

    .metric-value small {
        color: #94a3b8
    }

    .metric .time {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 16px;
    }

    .danger {
        color: #ef4444 !important
    }

    .table-card {
        min-height: 420px;
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        box-shadow: 0 6px 14px rgba(15, 23, 42, 0.04)
    }

    .card-title {
        display: flex;
        align-items: center;
        gap: 8px;
        color: #1e293b;
        font-weight: 600;
    }

    .card-title .el-icon {
        color: #2563eb;
        font-size: 18px;
    }

    .table-toolbar {
        justify-content: space-between;
        display: flex;
        align-items: center;
    }

    .table-card :deep(.el-table) {
        --el-table-border-color: #e2e8f0;
        --el-table-header-bg-color: #f8fafc;
        --el-table-header-text-color: #475569;
        --el-table-row-hover-bg-color: #eff6ff;
    }

    .table-card :deep(.el-table__row) {
        cursor: pointer;
    }

    .trend-button {
        display: inline-flex;
        align-items: center;
        gap: 4px;
    }

    .table-card :deep(.el-pagination) {
        justify-content: flex-end;
        margin-top: 16px
    }

    .trend-body {
        min-height: 340px;
        padding-right: 4px
    }

    .trend-chart {
        height: 300px;
        margin-bottom: 20px;
        padding: 12px;
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        background: #fff
    }

    .trend-body :deep(.el-empty) {
        margin-bottom: 20px
    }

    @media (max-width: 900px) {
        .metric-grid {
            grid-template-columns:repeat(2, minmax(0, 1fr))
        }

        .filter-card :deep(.el-form-item) {
            margin-bottom: 12px
        }
    }
</style>
