<template>
  <div class="dictionary-metrics-page art-full-height">
    <ElRow :gutter="16">
      <ElCol :span="8">
        <ElCard class="metric-card" shadow="never">
          <div class="metric-title">{{ t('dictionary.metrics.cacheHitRatio') }}</div>
          <ElProgress
            type="circle"
            :percentage="Math.round(cacheStats.hitRatio * 100)"
            :color="hitRatioColor"
          />
        </ElCard>
      </ElCol>
      <ElCol :span="8">
        <ElCard class="metric-card" shadow="never">
          <div class="metric-title">{{ t('dictionary.metrics.totalQueries') }}</div>
          <div class="metric-value">{{ totalQueries }}</div>
          <div class="metric-sub">
            {{ t('dictionary.metrics.hits') }}: {{ cacheStats.totalHits }} |
            {{ t('dictionary.metrics.misses') }}:
            {{ cacheStats.totalMisses }}
          </div>
        </ElCard>
      </ElCol>
      <ElCol :span="8">
        <ElCard class="metric-card" shadow="never">
          <div class="metric-title">{{ t('dictionary.metrics.avgResponse') }}</div>
          <div class="metric-value">{{ averageDurationLabel }}</div>
          <div class="metric-sub">{{ t('dictionary.metrics.last1h') }}</div>
        </ElCard>
      </ElCol>
    </ElRow>

    <ElCard class="chart-card" shadow="never">
      <div class="chart-header">
        <div class="chart-title">{{ t('dictionary.metrics.hitRatioTrend') }}</div>
        <ElSelect v-model="timeRange" size="small" style="width: 120px" @change="refreshStats">
          <ElOption :label="t('dictionary.metrics.timeRange1h')" value="1h" />
          <ElOption :label="t('dictionary.metrics.timeRange24h')" value="24h" />
          <ElOption :label="t('dictionary.metrics.timeRange7d')" value="7d" />
        </ElSelect>
      </div>
      <div ref="chartRef" class="chart-container"></div>
    </ElCard>

    <ElCard class="table-card" shadow="never">
      <div class="table-header">
        <div class="table-title">{{ t('dictionary.metrics.invalidationEvents') }}</div>
        <ElDatePicker
          v-model="dateRange"
          type="daterange"
          :range-separator="t('dictionary.metrics.rangeTo')"
          :start-placeholder="t('dictionary.metrics.start')"
          :end-placeholder="t('dictionary.metrics.end')"
          size="small"
          @change="handleFilterChange"
        />
      </div>
      <ElTable :data="invalidationEvents" v-loading="tableLoading" row-key="id">
        <ElTableColumn
          prop="timestamp"
          :label="t('dictionary.metrics.timestamp')"
          min-width="160"
        />
        <ElTableColumn
          prop="dictionaryCode"
          :label="t('dictionary.metrics.dictionary')"
          min-width="140"
        />
        <ElTableColumn prop="operation" :label="t('dictionary.metrics.operation')" width="120">
          <template #default="{ row }">
            <ElTag :type="resolveOperationTag(row.operation)">
              {{ resolveOperationLabel(row.operation) }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn
          prop="affectedCacheKeyCount"
          :label="t('dictionary.metrics.keys')"
          width="100"
        />
        <ElTableColumn prop="operatorId" :label="t('dictionary.metrics.operator')" width="140" />
      </ElTable>
      <ElPagination
        class="table-pagination"
        :current-page="pagination.page"
        :page-size="pagination.pageSize"
        :total="pagination.total"
        layout="total, sizes, prev, pager, next"
        :page-sizes="[10, 20, 50]"
        @current-change="handlePageChange"
        @size-change="handlePageSizeChange"
      />
    </ElCard>
  </div>
</template>

<script setup lang="ts">
  import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
  import { useI18n } from 'vue-i18n'
  import * as echarts from 'echarts/core'
  import { LineChart } from 'echarts/charts'
  import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
  import { CanvasRenderer } from 'echarts/renderers'
  import { getCacheStats, getInvalidationEvents } from '@/api/dictionary/metrics'
  import { CacheInvalidationOperation } from '@/enums/Dictionary'

  defineOptions({ name: 'DictionaryMetrics' })

  echarts.use([LineChart, GridComponent, TooltipComponent, LegendComponent, CanvasRenderer])

  const chartRef = ref<HTMLElement | null>(null)
  let chartInstance: echarts.ECharts | null = null
  let refreshTimer: number | null = null
  const { t } = useI18n()

  const timeRange = ref<'1h' | '24h' | '7d'>('1h')
  const cacheStats = ref({
    totalHits: 0,
    totalMisses: 0,
    hitRatio: 0,
    hitsByLevel: { l1: 0, l2: 0 },
    missesByLevel: { l1: 0, l2: 0 },
    averageQueryDurationMs: 0,
    topQueriedDictionaries: [] as Array<{ code: string; queryCount: number }>
  })

  const trendPoints = ref<Array<{ time: string; l1: number; l2: number }>>([])

  const tableLoading = ref(false)
  const invalidationEvents = ref<Api.Dictionary.CacheInvalidationLogDto[]>([])
  const pagination = ref({ page: 1, pageSize: 10, total: 0 })
  const dateRange = ref<[Date, Date] | null>(null)

  const totalQueries = computed(() => cacheStats.value.totalHits + cacheStats.value.totalMisses)
  const averageDurationLabel = computed(
    () => `${Math.round(cacheStats.value.averageQueryDurationMs)} ms`
  )

  const hitRatioColor = computed(() => {
    const ratio = cacheStats.value.hitRatio
    if (ratio >= 0.9) return '#67c23a'
    if (ratio >= 0.75) return '#e6a23c'
    return '#f56c6c'
  })

  const resolveOperationLabel = (operation: CacheInvalidationOperation) => {
    if (operation === CacheInvalidationOperation.Create) {
      return t('dictionary.metrics.create')
    }
    if (operation === CacheInvalidationOperation.Delete) {
      return t('dictionary.metrics.delete')
    }
    return t('dictionary.metrics.update')
  }

  const resolveOperationTag = (operation: CacheInvalidationOperation) => {
    if (operation === CacheInvalidationOperation.Create) return 'success'
    if (operation === CacheInvalidationOperation.Delete) return 'danger'
    return 'primary'
  }

  const refreshStats = async () => {
    const stats = await getCacheStats(timeRange.value)
    cacheStats.value = stats
    recordTrend(stats)
    renderChart()
  }

  const recordTrend = (stats: typeof cacheStats.value) => {
    const l1Total = stats.hitsByLevel.l1 + stats.missesByLevel.l1
    const l2Total = stats.hitsByLevel.l2 + stats.missesByLevel.l2
    const l1Ratio = l1Total === 0 ? 0 : (stats.hitsByLevel.l1 / l1Total) * 100
    const l2Ratio = l2Total === 0 ? 0 : (stats.hitsByLevel.l2 / l2Total) * 100
    const now = new Date()
    const label = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(
      2,
      '0'
    )}`

    trendPoints.value.push({ time: label, l1: l1Ratio, l2: l2Ratio })
    if (trendPoints.value.length > 12) {
      trendPoints.value.shift()
    }
  }

  const renderChart = () => {
    if (!chartRef.value) return
    if (!chartInstance) {
      chartInstance = echarts.init(chartRef.value)
    }

    const option: echarts.EChartsCoreOption = {
      tooltip: { trigger: 'axis' },
      legend: { data: [t('dictionary.metrics.l1HitRatio'), t('dictionary.metrics.l2HitRatio')] },
      grid: { left: '3%', right: '4%', bottom: '8%', containLabel: true },
      xAxis: {
        type: 'category',
        data: trendPoints.value.map((point) => point.time)
      },
      yAxis: {
        type: 'value',
        min: 0,
        max: 100,
        axisLabel: { formatter: '{value}%' }
      },
      series: [
        {
          name: t('dictionary.metrics.l1HitRatio'),
          type: 'line',
          data: trendPoints.value.map((point) => point.l1),
          smooth: true
        },
        {
          name: t('dictionary.metrics.l2HitRatio'),
          type: 'line',
          data: trendPoints.value.map((point) => point.l2),
          smooth: true
        },
        {
          name: t('dictionary.metrics.target'),
          type: 'line',
          data: trendPoints.value.map(() => 90),
          lineStyle: { type: 'dashed', color: '#f56c6c' },
          showSymbol: false
        }
      ]
    }

    chartInstance.setOption(option)
  }

  const loadInvalidationEvents = async () => {
    tableLoading.value = true
    try {
      const [start, end] = dateRange.value || []
      const result = await getInvalidationEvents({
        page: pagination.value.page,
        pageSize: pagination.value.pageSize,
        startDate: start ? start.toISOString() : undefined,
        endDate: end ? end.toISOString() : undefined
      })
      invalidationEvents.value = result.items
      pagination.value.total = result.totalCount
    } finally {
      tableLoading.value = false
    }
  }

  const handlePageChange = (page: number) => {
    pagination.value.page = page
    loadInvalidationEvents()
  }

  const handlePageSizeChange = (size: number) => {
    pagination.value.pageSize = size
    pagination.value.page = 1
    loadInvalidationEvents()
  }

  const handleFilterChange = () => {
    pagination.value.page = 1
    loadInvalidationEvents()
  }

  onMounted(async () => {
    await refreshStats()
    await loadInvalidationEvents()

    refreshTimer = window.setInterval(() => {
      refreshStats()
    }, 30000)
  })

  onBeforeUnmount(() => {
    if (refreshTimer) {
      window.clearInterval(refreshTimer)
    }
    chartInstance?.dispose()
  })
</script>

<style scoped>
  .dictionary-metrics-page {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .metric-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: center;
    justify-content: center;
    min-height: 180px;
  }

  .metric-title {
    font-weight: 600;
    color: #606266;
  }

  .metric-value {
    font-size: 28px;
    font-weight: 700;
    color: #303133;
  }

  .metric-sub {
    font-size: 12px;
    color: #909399;
  }

  .chart-card {
    min-height: 320px;
  }

  .chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }

  .chart-title {
    font-weight: 600;
    color: #303133;
  }

  .chart-container {
    width: 100%;
    height: 260px;
  }

  .table-card {
    flex: 1;
  }

  .table-header {
    display: flex;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }

  .table-title {
    font-weight: 600;
    color: #303133;
  }

  .table-pagination {
    display: flex;
    justify-content: flex-end;
    margin-top: 16px;
  }

  @media (width <= 960px) {
    .metric-card {
      min-height: 160px;
    }
  }
</style>
