<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import * as echarts from 'echarts'
import api from '@/api/client'
import PageHeader from '@/components/PageHeader.vue'
import StatCard from '@/components/StatCard.vue'
import AppCard from '@/components/AppCard.vue'

const { t } = useI18n()

interface TrafficItem {
  key: string
  label: string
  node?: string
  node_key?: string
  upload: number
  download: number
  total: number
  connections: number
}

const snapshot = ref({
  upload_rate: 0,
  download_rate: 0,
  connections: 0,
  total_nodes: 0,
  alive_nodes: 0,
})
const liveDomains = ref<TrafficItem[]>([])
const liveNodes = ref<TrafficItem[]>([])
const periodDomains = ref<TrafficItem[]>([])
const periodNodes = ref<TrafficItem[]>([])
const periodHours = ref(24)
const domainTab = ref('live')
const nodeTab = ref('live')
const domainPage = ref(1)
const domainPageSize = ref(50)
const domainTotal = ref(0)
const nodePage = ref(1)
const nodePageSize = ref(50)
const nodeTotal = ref(0)
const engineRunning = ref<boolean | null>(null)
const chartRef = ref<HTMLElement>()
let chart: echarts.ECharts | null = null
let timer: number

const domainRows = computed(() => (domainTab.value === 'live' ? liveDomains.value : periodDomains.value))
const nodeRows = computed(() => (nodeTab.value === 'live' ? liveNodes.value : periodNodes.value))

const CHART_AXIS = { color: '#71717a', fontSize: 12 }
const CHART_LINE = { color: '#e4e4e7' }

function formatRate(v: number) {
  if (v < 1024) return `${v} B/s`
  if (v < 1024 * 1024) return `${(v / 1024).toFixed(1)} KB/s`
  return `${(v / 1024 / 1024).toFixed(1)} MB/s`
}

function formatBytes(n: number) {
  if (n < 1024) return `${n} B`
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(2)} MB`
  return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`
}

function dashboardParams() {
  const params: Record<string, number> = {}
  if (domainTab.value === 'live') {
    params.live_domain_limit = domainPageSize.value
    params.live_domain_offset = (domainPage.value - 1) * domainPageSize.value
  } else {
    params.period_domain_limit = domainPageSize.value
    params.period_domain_offset = (domainPage.value - 1) * domainPageSize.value
  }
  if (nodeTab.value === 'live') {
    params.live_node_limit = nodePageSize.value
    params.live_node_offset = (nodePage.value - 1) * nodePageSize.value
  } else {
    params.period_node_limit = nodePageSize.value
    params.period_node_offset = (nodePage.value - 1) * nodePageSize.value
  }
  return params
}

async function load() {
  const { data } = await api.get('/dashboard', { params: dashboardParams() })
  snapshot.value = data.snapshot
  engineRunning.value = data.engine_running
  liveDomains.value = data.live_domains || []
  liveNodes.value = data.live_nodes || []
  periodDomains.value = data.period_domains || []
  periodNodes.value = data.period_nodes || []
  periodHours.value = data.period_hours || 24
  domainTotal.value = domainTab.value === 'live' ? (data.live_domain_total || 0) : (data.period_domain_total || 0)
  nodeTotal.value = nodeTab.value === 'live' ? (data.live_node_total || 0) : (data.period_node_total || 0)
  const history = (data.history || []).reverse()
  if (chart && history.length) {
    chart.setOption({
      grid: { left: 40, right: 16, top: 16, bottom: 24 },
      xAxis: {
        type: 'category',
        data: history.map((h: { created_at?: string }) => h.created_at?.slice(11, 19) || ''),
        axisLabel: CHART_AXIS,
        axisLine: { lineStyle: CHART_LINE },
      },
      yAxis: {
        type: 'value',
        axisLabel: CHART_AXIS,
        splitLine: { lineStyle: CHART_LINE },
      },
      series: [
        {
          name: t('dashboard.seriesDownload'),
          type: 'line',
          smooth: true,
          lineStyle: { width: 2 },
          data: history.map((h: { download_rate: number }) => h.download_rate),
          color: '#0f7a62',
        },
        {
          name: t('dashboard.seriesUpload'),
          type: 'line',
          smooth: true,
          lineStyle: { width: 2 },
          data: history.map((h: { upload_rate: number }) => h.upload_rate),
          color: '#71717a',
        },
      ],
      tooltip: { trigger: 'axis' },
    })
  }
}

function resetDomainPage() {
  domainPage.value = 1
  load()
}

function resetNodePage() {
  nodePage.value = 1
  load()
}

watch(domainTab, resetDomainPage)
watch(nodeTab, resetNodePage)

onMounted(() => {
  if (chartRef.value) {
    chart = echarts.init(chartRef.value)
  }
  load()
  timer = window.setInterval(load, 10000)
})

onUnmounted(() => {
  clearInterval(timer)
  chart?.dispose()
})
</script>

<template>
  <div class="page">
    <PageHeader :title="t('dashboard.title')" :description="t('dashboard.desc')">
      <template #actions>
        <el-tag v-if="engineRunning === null" type="info" size="small">{{ t('dashboard.checking') }}</el-tag>
        <el-tag v-else :type="engineRunning ? 'success' : 'danger'" size="small">
          {{ engineRunning ? t('dashboard.engineRunning') : t('dashboard.engineStopped') }}
        </el-tag>
      </template>
    </PageHeader>

    <div class="stat-grid">
      <StatCard :label="t('dashboard.totalNodes')" :value="snapshot.total_nodes" />
      <StatCard :label="t('dashboard.aliveNodes')" :value="snapshot.alive_nodes" />
      <StatCard :label="t('dashboard.activeConnections')" :value="snapshot.connections" />
      <StatCard :label="t('dashboard.downloadRate')" :value="formatRate(snapshot.download_rate)" />
    </div>

    <div class="content-grid content-grid--2-1">
      <AppCard :title="t('dashboard.domainTraffic')">
        <div class="tabs-bar">
          <el-tabs v-model="domainTab">
            <el-tab-pane :label="t('dashboard.tabLive')" name="live" />
            <el-tab-pane :label="t('common.periodHours', { n: periodHours })" name="period" />
          </el-tabs>
        </div>
        <el-table
          :data="domainRows"
          size="small"
          class="table-scroll--sm"
          :empty-text="t('common.empty')"
        >
          <el-table-column prop="label" :label="t('dashboard.domain')" min-width="160" show-overflow-tooltip />
          <el-table-column prop="node" :label="t('dashboard.outboundNode')" min-width="140" show-overflow-tooltip />
          <el-table-column :label="t('common.upload')" width="100">
            <template #default="{ row }">{{ formatBytes(row.upload) }}</template>
          </el-table-column>
          <el-table-column :label="t('common.download')" width="100">
            <template #default="{ row }">{{ formatBytes(row.download) }}</template>
          </el-table-column>
          <el-table-column :label="t('common.connections')" width="80" align="center">
            <template #default="{ row }">{{ row.connections }}</template>
          </el-table-column>
        </el-table>
        <p class="form-hint form-hint--flush card-footer-hint">
          {{ domainTab === 'live' ? t('dashboard.hintLiveDomain') : t('dashboard.hintPeriodDomain') }}
        </p>
        <div class="card-pager">
          <el-pagination
            v-model:current-page="domainPage"
            v-model:page-size="domainPageSize"
            :page-sizes="[50, 100, 200, 500]"
            :total="domainTotal"
            layout="total, sizes, prev, pager, next"
            @current-change="load"
            @size-change="resetDomainPage"
          />
        </div>
      </AppCard>

      <AppCard :title="t('dashboard.trafficTrend')" padded>
        <div ref="chartRef" class="chart-box" />
      </AppCard>
    </div>

    <AppCard :title="t('dashboard.nodeTraffic')">
      <div class="tabs-bar">
        <el-tabs v-model="nodeTab">
          <el-tab-pane :label="t('dashboard.tabLive')" name="live" />
          <el-tab-pane :label="t('common.periodHours', { n: periodHours })" name="period" />
        </el-tabs>
      </div>
      <el-table
        :data="nodeRows"
        size="small"
        class="table-scroll--md"
        :empty-text="t('common.empty')"
      >
        <el-table-column prop="label" :label="t('dashboard.outboundNode')" min-width="160" show-overflow-tooltip />
        <el-table-column :label="t('common.upload')" width="100">
          <template #default="{ row }">{{ formatBytes(row.upload) }}</template>
        </el-table-column>
        <el-table-column :label="t('common.download')" width="100">
          <template #default="{ row }">{{ formatBytes(row.download) }}</template>
        </el-table-column>
        <el-table-column :label="t('common.connections')" width="80" align="center">
          <template #default="{ row }">{{ row.connections }}</template>
        </el-table-column>
      </el-table>
      <p class="form-hint form-hint--flush card-footer-hint">
        {{ nodeTab === 'live' ? t('dashboard.hintLiveNode') : t('dashboard.hintPeriodNode') }}
      </p>
      <div class="card-pager">
        <el-pagination
          v-model:current-page="nodePage"
          v-model:page-size="nodePageSize"
          :page-sizes="[50, 100, 200, 500]"
          :total="nodeTotal"
          layout="total, sizes, prev, pager, next"
          @current-change="load"
          @size-change="resetNodePage"
        />
      </div>
    </AppCard>
  </div>
</template>
