<script setup lang="ts">
import { ArrowRight, DollarSign, Key, LayoutGrid, Loader2, Ticket, Users } from 'lucide-vue-next'
import * as echarts from 'echarts'
import { useColorMode } from '@vueuse/core'
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'

import { BasicPage } from '@/components/global-layout'
import { BASE_URL } from '@/services/api'

const { t } = useI18n()
const router = useRouter()
const colorMode = useColorMode()
const isDark = computed(() => colorMode.value === 'dark')

interface DashboardStats {
  totalApplications: number
  totalCards: number
  totalUsers: number
  monthlyRevenue: number
}

interface Ticket {
  id: number
  title: string
  status: string
  priority: string
  createdAt: Date
}

interface Province {
  name: string
  count: number
  online?: number
  offline?: number
}

const loading = ref(true)
const currentUser = ref<any>(null)
const stats = ref<DashboardStats>({
  totalApplications: 0,
  totalCards: 0,
  totalUsers: 0,
  monthlyRevenue: 0,
})

const provinces = ref<Province[]>([])
const onlineTrendData = ref<number[]>([])
const recentTickets = ref<Ticket[]>([])

const mapChart = ref<HTMLElement | null>(null)
const activityChart = ref<HTMLCanvasElement | null>(null)
let chartInstance: any = null
let activityChartInstance: any = null

const overseasUsers = computed(() => {
  if (!provinces.value || provinces.value.length === 0)
    return 0
  return provinces.value.reduce((sum, country) => sum + (country.count || 0), 0)
})

const onlineUsers = computed(() => {
  if (!provinces.value || provinces.value.length === 0)
    return 0
  return provinces.value.reduce((sum, country) => sum + (country.online || 0), 0)
})

const offlineUsers = computed(() => {
  if (!provinces.value || provinces.value.length === 0)
    return 0
  return provinces.value.reduce((sum, country) => sum + (country.offline || 0), 0)
})

const totalUsers = computed(() => {
  if (stats.value?.totalUsers && stats.value.totalUsers > 0) {
    return stats.value.totalUsers
  }
  return overseasUsers.value || 0
})

function formatDate(date: Date) {
  return new Intl.DateTimeFormat('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  }).format(date)
}

function formatNumber(num: number) {
  return (num || 0).toLocaleString()
}

function getTicketStatusColor(status: string) {
  const colors: Record<string, string> = {
    open: 'bg-yellow-500/10 text-yellow-500',
    processing: 'bg-blue-500/10 text-blue-500',
    resolved: 'bg-green-500/10 text-green-500',
    closed: 'bg-gray-500/10 text-gray-500',
  }
  return colors[status] || 'bg-gray-500/10 text-gray-500'
}

function getTicketStatusText(status: string) {
  const texts: Record<string, string> = {
    open: t('admin.ticketStatusOpen'),
    processing: t('admin.ticketStatusProcessing'),
    resolved: t('admin.ticketStatusResolved'),
    closed: t('admin.ticketStatusClosed'),
  }
  return texts[status] || status
}

function getTicketPriorityColor(priority: string) {
  const colors: Record<string, string> = {
    low: 'text-gray-500',
    normal: 'text-blue-500',
    high: 'text-orange-500',
    urgent: 'text-red-500',
  }
  return colors[priority] || 'text-gray-500'
}

function getTicketPriorityText(priority: string) {
  const texts: Record<string, string> = {
    low: t('admin.priorityLow'),
    normal: t('admin.priorityNormal'),
    high: t('admin.priorityHigh'),
    urgent: t('admin.priorityUrgent'),
  }
  return texts[priority] || priority
}

function goToTicket(ticketId: number) {
  router.push(`/admin/tickets/${ticketId}`)
}

function goToTickets() {
  router.push('/admin/tickets')
}

async function fetchDashboard() {
  loading.value = true
  try {
    const token = localStorage.getItem('token')
    if (!token) {
      console.error('No token found')
      return
    }

    const response = await fetch(`${BASE_URL}/dev/dashboard`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const data = await response.json()

    if (data.code === 200 && data.data) {
      if (data.data.stats) {
        stats.value = {
          totalApplications: data.data.stats.totalApplications || 0,
          totalCards: data.data.stats.totalCards || 0,
          totalUsers: data.data.stats.totalUsers || 0,
          monthlyRevenue: data.data.stats.monthlyRevenue || 0,
        }
      }

      if (data.data.userDistribution) {
        const allProvinces: Province[] = []
        if (data.data.userDistribution.provinces && Array.isArray(data.data.userDistribution.provinces)) {
          allProvinces.push(...data.data.userDistribution.provinces.map((p: any) => ({
            name: p.name,
            count: p.count || 0,
            online: p.online || 0,
            offline: p.offline || 0,
          })))
        }
        if (data.data.userDistribution.overseas && Array.isArray(data.data.userDistribution.overseas)) {
          allProvinces.push(...data.data.userDistribution.overseas.map((p: any) => ({
            name: p.name,
            count: p.count || 0,
            online: p.online || 0,
            offline: p.offline || 0,
          })))
        }
        provinces.value = allProvinces
      }

      if (data.data.onlineTrend && Array.isArray(data.data.onlineTrend)) {
        onlineTrendData.value = data.data.onlineTrend.map((t: any) => t.value || t.count || 0)
      }

      if (data.data.recentTickets && Array.isArray(data.data.recentTickets)) {
        recentTickets.value = data.data.recentTickets.map((t: any) => ({
          id: t.id,
          title: t.title,
          status: t.status,
          priority: t.priority,
          createdAt: new Date(t.created_at),
        }))
      }
    }
    else {
      console.error('API returned error:', data)
    }
  }
  catch (error) {
    console.error(t('admin.fetchDashboardError'), error)
  }
  finally {
    loading.value = false
  }
}

function fetchCurrentUser() {
  const userStr = localStorage.getItem('user')
  if (userStr) {
    currentUser.value = JSON.parse(userStr)
  }
}

async function initMapChart() {
  if (!mapChart.value)
    return

  try {
    const worldResponse = await fetch('/world.json')

    if (!worldResponse.ok) {
      throw new Error('Failed to load world map data')
    }

    const worldData = await worldResponse.json()

    echarts.registerMap('world', worldData)

    chartInstance = echarts.init(mapChart.value)

    updateMapOption()

    window.addEventListener('resize', () => {
      chartInstance?.resize()
    })
  }
  catch (error) {
    console.error(t('admin.initMapError'), error)
  }
}

const worldNameMap: Record<string, string> = {
  'Afghanistan': '阿富汗',
  'Albania': '阿尔巴尼亚',
  'Algeria': '阿尔及利亚',
  'American Samoa': '美属萨摩亚',
  'Andorra': '安道尔',
  'Angola': '安哥拉',
  'Anguilla': '安圭拉',
  'Antarctica': '南极洲',
  'Antigua and Barbuda': '安提瓜和巴布达',
  'Argentina': '阿根廷',
  'Armenia': '亚美尼亚',
  'Aruba': '阿鲁巴',
  'Australia': '澳大利亚',
  'Austria': '奥地利',
  'Azerbaijan': '阿塞拜疆',
  'Bahamas': '巴哈马',
  'Bahrain': '巴林',
  'Bangladesh': '孟加拉国',
  'Barbados': '巴巴多斯',
  'Belarus': '白俄罗斯',
  'Belgium': '比利时',
  'Belize': '伯利兹',
  'Benin': '贝宁',
  'Bermuda': '百慕大',
  'Bhutan': '不丹',
  'Bolivia': '玻利维亚',
  'Bosnia and Herzegovina': '波黑',
  'Botswana': '博茨瓦纳',
  'Brazil': '巴西',
  'British Indian Ocean Ter.': '英属印度洋领地',
  'Brunei': '文莱',
  'Bulgaria': '保加利亚',
  'Burkina Faso': '布基纳法索',
  'Burundi': '布隆迪',
  'Cambodia': '柬埔寨',
  'Cameroon': '喀麦隆',
  'Canada': '加拿大',
  'Cape Verde': '佛得角',
  'Cayman Is.': '开曼群岛',
  'Central African Rep.': '中非',
  'Chad': '乍得',
  'Chile': '智利',
  'China': '中国',
  'Colombia': '哥伦比亚',
  'Comoros': '科摩罗',
  'Congo': '刚果',
  'Dem. Rep. Congo': '刚果民主共和国',
  'Cook Is.': '库克群岛',
  'Costa Rica': '哥斯达黎加',
  'Croatia': '克罗地亚',
  'Cuba': '古巴',
  'Cyprus': '塞浦路斯',
  'Czech Rep.': '捷克',
  'Côte d\'Ivoire': '科特迪瓦',
  'Denmark': '丹麦',
  'Djibouti': '吉布提',
  'Dominica': '多米尼克',
  'Dominican Rep.': '多米尼加',
  'Ecuador': '厄瓜多尔',
  'Egypt': '埃及',
  'El Salvador': '萨尔瓦多',
  'Equatorial Guinea': '赤道几内亚',
  'Eritrea': '厄立特里亚',
  'Estonia': '爱沙尼亚',
  'Ethiopia': '埃塞俄比亚',
  'Falkland Is.': '福克兰群岛',
  'Faeroe Is.': '法罗群岛',
  'Fiji': '斐济',
  'Finland': '芬兰',
  'France': '法国',
  'French Guiana': '法属圭亚那',
  'French Polynesia': '法属波利尼西亚',
  'French Southern Ter.': '法属南方领地',
  'Gabon': '加蓬',
  'Gambia': '冈比亚',
  'Gaza': '加沙',
  'Georgia': '格鲁吉亚',
  'Germany': '德国',
  'Ghana': '加纳',
  'Gibraltar': '直布罗陀',
  'Greece': '希腊',
  'Greenland': '格陵兰',
  'Grenada': '格林纳达',
  'Guadeloupe': '瓜德罗普',
  'Guam': '关岛',
  'Guatemala': '危地马拉',
  'Guinea': '几内亚',
  'Guinea-Bissau': '几内亚比绍',
  'Guyana': '圭亚那',
  'Haiti': '海地',
  'Heard I. and McDonald Is.': '赫德岛和麦克唐纳群岛',
  'Honduras': '洪都拉斯',
  'Hong Kong': '香港',
  'Hungary': '匈牙利',
  'Iceland': '冰岛',
  'India': '印度',
  'Indonesia': '印度尼西亚',
  'Iran': '伊朗',
  'Iraq': '伊拉克',
  'Ireland': '爱尔兰',
  'Isle of Man': '马恩岛',
  'Israel': '以色列',
  'Italy': '意大利',
  'Jamaica': '牙买加',
  'Japan': '日本',
  'Jordan': '约旦',
  'Kazakhstan': '哈萨克斯坦',
  'Kenya': '肯尼亚',
  'Kiribati': '基里巴斯',
  'Korea': '韩国',
  'Dem. Rep. Korea': '朝鲜',
  'Kuwait': '科威特',
  'Kyrgyzstan': '吉尔吉斯斯坦',
  'Lao PDR': '老挝',
  'Latvia': '拉脱维亚',
  'Lebanon': '黎巴嫩',
  'Lesotho': '莱索托',
  'Liberia': '利比里亚',
  'Libya': '利比亚',
  'Liechtenstein': '列支敦士登',
  'Lithuania': '立陶宛',
  'Luxembourg': '卢森堡',
  'Macao': '澳门',
  'Macedonia': '马其顿',
  'Madagascar': '马达加斯加',
  'Malawi': '马拉维',
  'Malaysia': '马来西亚',
  'Maldives': '马尔代夫',
  'Mali': '马里',
  'Malta': '马耳他',
  'Marshall Is.': '马绍尔群岛',
  'Martinique': '马提尼克',
  'Mauritania': '毛里塔尼亚',
  'Mauritius': '毛里求斯',
  'Mexico': '墨西哥',
  'Micronesia': '密克罗尼西亚',
  'Moldova': '摩尔多瓦',
  'Monaco': '摩纳哥',
  'Mongolia': '蒙古',
  'Montenegro': '黑山',
  'Montserrat': '蒙特塞拉特',
  'Morocco': '摩洛哥',
  'Mozambique': '莫桑比克',
  'Myanmar': '缅甸',
  'Namibia': '纳米比亚',
  'Nauru': '瑙鲁',
  'Nepal': '尼泊尔',
  'Netherlands': '荷兰',
  'New Caledonia': '新喀里多尼亚',
  'New Zealand': '新西兰',
  'Nicaragua': '尼加拉瓜',
  'Niger': '尼日尔',
  'Nigeria': '尼日利亚',
  'Niue': '纽埃',
  'Norfolk Island': '诺福克岛',
  'Northern Mariana Is.': '北马里亚纳群岛',
  'Norway': '挪威',
  'Oman': '阿曼',
  'Pakistan': '巴基斯坦',
  'Palau': '帕劳',
  'Palestine': '巴勒斯坦',
  'Panama': '巴拿马',
  'Papua New Guinea': '巴布亚新几内亚',
  'Paraguay': '巴拉圭',
  'Peru': '秘鲁',
  'Philippines': '菲律宾',
  'Pitcairn Is.': '皮特凯恩群岛',
  'Poland': '波兰',
  'Portugal': '葡萄牙',
  'Puerto Rico': '波多黎各',
  'Qatar': '卡塔尔',
  'Réunion': '留尼汪',
  'Romania': '罗马尼亚',
  'Russia': '俄罗斯',
  'Rwanda': '卢旺达',
  'Saint Helena': '圣赫勒拿',
  'Saint Kitts and Nevis': '圣基茨和尼维斯',
  'Saint Lucia': '圣卢西亚',
  'Saint Pierre and Miquelon': '圣皮埃尔和密克隆',
  'Saint Vincent and the Grenadines': '圣文森特和格林纳丁斯',
  'Samoa': '萨摩亚',
  'San Marino': '圣马力诺',
  'Sao Tome and Principe': '圣多美和普林西比',
  'Saudi Arabia': '沙特阿拉伯',
  'Senegal': '塞内加尔',
  'Serbia': '塞尔维亚',
  'Seychelles': '塞舌尔',
  'Sierra Leone': '塞拉利昂',
  'Singapore': '新加坡',
  'Slovakia': '斯洛伐克',
  'Slovenia': '斯洛文尼亚',
  'Solomon Is.': '所罗门群岛',
  'Somalia': '索马里',
  'South Africa': '南非',
  'South Georgia and the South Sandwich Is.': '南乔治亚和南桑威奇群岛',
  'S. Sudan': '南苏丹',
  'Spain': '西班牙',
  'Sri Lanka': '斯里兰卡',
  'Sudan': '苏丹',
  'Suriname': '苏里南',
  'Swaziland': '斯威士兰',
  'Sweden': '瑞典',
  'Switzerland': '瑞士',
  'Syria': '叙利亚',
  'Taiwan': '台湾',
  'Tajikistan': '塔吉克斯坦',
  'Tanzania': '坦桑尼亚',
  'Thailand': '泰国',
  'Timor-Leste': '东帝汶',
  'Togo': '多哥',
  'Tokelau': '托克劳',
  'Tonga': '汤加',
  'Trinidad and Tobago': '特立尼达和多巴哥',
  'Tunisia': '突尼斯',
  'Turkey': '土耳其',
  'Turkmenistan': '土库曼斯坦',
  'Turks and Caicos Is.': '特克斯和凯科斯群岛',
  'Tuvalu': '图瓦卢',
  'Uganda': '乌干达',
  'Ukraine': '乌克兰',
  'United Arab Emirates': '阿联酋',
  'United Kingdom': '英国',
  'United States': '美国',
  'United States Minor Outlying Is.': '美属小离岛',
  'Uruguay': '乌拉圭',
  'Uzbekistan': '乌兹别克斯坦',
  'Vanuatu': '瓦努阿图',
  'Vatican City': '梵蒂冈',
  'Venezuela': '委内瑞拉',
  'Vietnam': '越南',
  'Virgin Is.': '维尔京群岛',
  'W. Sahara': '西撒哈拉',
  'Yemen': '也门',
  'Zambia': '赞比亚',
  'Zimbabwe': '津巴布韦',
}

function updateMapOption() {
  if (!chartInstance)
    return

  const data = provinces.value.filter((d: any) => d.count > 0)
  const maxCount = Math.max(...data.map((d: any) => d.count || 0), 1)

  const dark = isDark.value

  const seriesData = data.map((d: any) => {
    const ratio = d.count / maxCount
    let r: number, g: number, b: number
    if (dark) {
      r = Math.round(30 + (59 - 30) * ratio)
      g = Math.round(58 + (130 - 58) * ratio)
      b = Math.round(138 + (246 - 138) * ratio)
    }
    else {
      r = Math.round(147 + (37 - 147) * ratio)
      g = Math.round(197 + (99 - 197) * ratio)
      b = Math.round(253 + (235 - 253) * ratio)
    }
    return {
      name: d.name,
      value: d.count,
      count: d.count,
      online: d.online || 0,
      offline: d.offline || 0,
      itemStyle: {
        areaColor: `rgb(${r}, ${g}, ${b})`,
      },
    }
  })

  const option = {
    tooltip: {
      trigger: 'item',
      backgroundColor: dark ? 'rgba(15, 23, 42, 0.95)' : 'rgba(255, 255, 255, 0.95)',
      borderColor: dark ? '#334155' : '#e2e8f0',
      borderWidth: 1,
      padding: 12,
      textStyle: {
        color: dark ? '#f8fafc' : '#0f172a',
      },
      formatter: (params: any) => {
        if (params.data && params.data.count > 0) {
          return `<div style="padding: 4px;">
            <div style="font-weight: 600; margin-bottom: 6px; font-size: 13px;">${params.name}</div>
            <div style="display: flex; align-items: center; gap: 6px; margin-bottom: 3px;">
              <span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#22c55e;"></span>
              <span>${t('admin.online')}: ${params.data.online}</span>
            </div>
            <div style="display: flex; align-items: center; gap: 6px; margin-bottom: 3px;">
              <span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#ef4444;"></span>
              <span>${t('admin.offline')}: ${params.data.offline}</span>
            </div>
            <div style="display: flex; align-items: center; gap: 6px;">
              <span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#3b82f6;"></span>
              <span>${t('admin.total')}: ${params.data.count}</span>
            </div>
          </div>`
        }
        return `<div style="padding: 4px;">
          <div style="font-weight: 600; margin-bottom: 4px; font-size: 13px;">${params.name}</div>
          <div style="color: ${dark ? '#94a3b8' : '#64748b'};">${t('admin.noUserData')}</div>
        </div>`
      },
    },
    geo: {
      map: 'world',
      roam: true,
      zoom: 1.2,
      nameMap: worldNameMap,
      label: {
        show: false,
      },
      emphasis: {
        label: {
          show: true,
          color: dark ? '#f8fafc' : '#0f172a',
          fontSize: 11,
          fontWeight: 600,
        },
        itemStyle: {
          areaColor: dark ? '#334155' : '#f1f5f9',
          borderColor: dark ? '#475569' : '#94a3b8',
          borderWidth: 1,
        },
      },
      itemStyle: {
        areaColor: dark ? '#1e293b' : '#e2e8f0',
        borderColor: dark ? '#334155' : '#cbd5e1',
        borderWidth: 0.5,
      },
    },
    series: [
      {
        name: t('admin.userDistribution'),
        type: 'map',
        geoIndex: 0,
        data: seriesData,
      },
    ],
  }

  chartInstance.setOption(option)
}

function initActivityChart() {
  if (!activityChart.value)
    return

  try {
    import('chart.js/auto').then(({ default: Chart }) => {
      const ctx = activityChart.value?.getContext('2d')
      if (!ctx)
        return

      const labels = Array.from({ length: 30 }, (_, i) => {
        const date = new Date()
        date.setDate(date.getDate() - (29 - i))
        return date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' })
      })

      const data = onlineTrendData.value.length > 0
        ? onlineTrendData.value
        : Array.from({ length: 30 }).fill(0)

      if (activityChartInstance) {
        activityChartInstance.destroy()
      }

      activityChartInstance = new Chart(ctx, {
        type: 'line',
        data: {
          labels,
          datasets: [
            {
              label: t('admin.verificationCount'),
              data,
              borderColor: '#3b82f6',
              backgroundColor: 'rgba(59, 130, 246, 0.1)',
              fill: true,
              tension: 0.4,
              pointRadius: 0,
              pointHoverRadius: 6,
              pointHoverBackgroundColor: '#3b82f6',
              pointHoverBorderColor: '#fff',
              pointHoverBorderWidth: 2,
            },
          ],
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              display: false,
            },
            tooltip: {
              backgroundColor: 'rgba(15, 23, 42, 0.95)',
              titleColor: '#f8fafc',
              bodyColor: '#cbd5e1',
              borderColor: '#334155',
              borderWidth: 1,
              padding: 12,
              displayColors: false,
              callbacks: {
                label: (context: any) => `${context.parsed.y} ${t('admin.online')}`,
              },
            },
          },
          scales: {
            x: {
              grid: {
                display: false,
              },
              ticks: {
                color: '#94a3b8',
                font: {
                  size: 11,
                },
              },
            },
            y: {
              grid: {
                color: '#334155',
              },
              ticks: {
                color: '#94a3b8',
                font: {
                  size: 11,
                },
              },
              beginAtZero: true,
            },
          },
          interaction: {
            intersect: false,
            mode: 'index',
          },
        },
      })
    })
  }
  catch (error) {
    console.error(t('admin.initActivityChartError'), error)
  }
}

onMounted(async () => {
  fetchCurrentUser()
  await fetchDashboard()
  await nextTick()

  initMapChart()
  initActivityChart()
})

watch(isDark, () => {
  updateMapOption()
})

onUnmounted(() => {
  if (chartInstance) {
    chartInstance.dispose()
    chartInstance = null
  }
  if (activityChartInstance) {
    activityChartInstance.destroy()
    activityChartInstance = null
  }
})
</script>

<template>
  <BasicPage
    :title="t('admin.dashboard.title')"
    :description="`${t('admin.welcomeBack')}, ${currentUser?.username || t('admin.adminRole')}`"
  >
    <div v-if="loading" class="flex items-center justify-center py-12">
      <div class="text-center">
        <Loader2 class="size-8 animate-spin mx-auto text-muted-foreground" />
        <p class="mt-4 text-muted-foreground">
          {{ t('admin.loading') }}...
        </p>
      </div>
    </div>

    <div v-else class="space-y-4">
      <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.totalApplications') }}
            </UiCardTitle>
            <LayoutGrid class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              {{ formatNumber(stats.totalApplications) }}
            </div>
            <p class="text-xs text-muted-foreground">
              +12.5% {{ t('admin.lastMonth') }}
            </p>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.totalCards') }}
            </UiCardTitle>
            <Key class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              {{ formatNumber(stats.totalCards) }}
            </div>
            <p class="text-xs text-muted-foreground">
              +8.2% {{ t('admin.lastMonth') }}
            </p>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.totalUsers') }}
            </UiCardTitle>
            <Users class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              {{ formatNumber(totalUsers) }}
            </div>
            <p class="text-xs text-muted-foreground">
              +15.3% {{ t('admin.lastMonth') }}
            </p>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.monthlyRevenue') }}
            </UiCardTitle>
            <DollarSign class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              ¥{{ formatNumber(stats.monthlyRevenue) }}
            </div>
            <p class="text-xs text-muted-foreground">
              +23.1% {{ t('admin.lastMonth') }}
            </p>
          </UiCardContent>
        </UiCard>
      </div>

      <div class="grid gap-4 lg:grid-cols-2">
        <UiCard>
          <UiCardHeader>
            <div class="flex items-center justify-between">
              <div>
                <UiCardTitle>{{ t('admin.userDistribution') }}</UiCardTitle>
                <UiCardDescription>{{ t('admin.userDistributionDesc') }}</UiCardDescription>
              </div>
              <div class="flex items-center gap-4 text-sm">
                <div class="flex items-center gap-2">
                  <div class="size-3 rounded-full bg-green-500" />
                  <span class="text-muted-foreground">{{ t('admin.online') }}: {{ formatNumber(onlineUsers) }}</span>
                </div>
                <div class="flex items-center gap-2">
                  <div class="size-3 rounded-full bg-red-500" />
                  <span class="text-muted-foreground">{{ t('admin.offline') }}: {{ formatNumber(offlineUsers) }}</span>
                </div>
                <div class="flex items-center gap-2">
                  <div class="size-3 rounded-full bg-blue-500" />
                  <span class="text-muted-foreground">{{ t('admin.total') }}: {{ formatNumber(totalUsers) }}</span>
                </div>
              </div>
            </div>
          </UiCardHeader>
          <UiCardContent>
            <div class="relative h-[350px] rounded-lg overflow-hidden bg-card">
              <div ref="mapChart" class="w-full h-full" />
            </div>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader>
            <UiCardTitle>{{ t('admin.onlineTrend') }}</UiCardTitle>
            <UiCardDescription>{{ t('admin.onlineTrendDesc') }}</UiCardDescription>
          </UiCardHeader>
          <UiCardContent class="pl-2">
            <div class="relative h-[350px]">
              <canvas ref="activityChart" />
            </div>
          </UiCardContent>
        </UiCard>
      </div>

      <UiCard>
        <UiCardHeader>
          <div class="flex items-center justify-between">
            <div>
              <UiCardTitle>{{ t('admin.recentTickets') }}</UiCardTitle>
              <UiCardDescription>{{ t('admin.recentTicketsDesc') }}</UiCardDescription>
            </div>
            <UiButton variant="ghost" size="sm" @click="goToTickets">
              {{ t('admin.viewAll') }}
              <ArrowRight class="ml-1 size-4" />
            </UiButton>
          </div>
        </UiCardHeader>
        <UiCardContent>
          <div v-if="recentTickets.length > 0" class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
            <div
              v-for="ticket in recentTickets.slice(0, 5)"
              :key="ticket.id"
              class="flex items-start gap-3 p-3 rounded-lg border hover:bg-muted/50 cursor-pointer transition-colors"
              @click="goToTicket(ticket.id)"
            >
              <div class="flex-shrink-0">
                <div class="size-8 rounded-full bg-primary/10 flex items-center justify-center">
                  <Ticket class="size-4 text-primary" />
                </div>
              </div>
              <div class="flex-1 min-w-0">
                <p class="text-sm font-medium truncate">
                  {{ ticket.title }}
                </p>
                <div class="flex items-center gap-2 mt-1">
                  <UiBadge :class="getTicketStatusColor(ticket.status)" class="text-[10px] flex-shrink-0">
                    {{ getTicketStatusText(ticket.status) }}
                  </UiBadge>
                  <span :class="`text-xs ${getTicketPriorityColor(ticket.priority)}`">
                    {{ getTicketPriorityText(ticket.priority) }}
                  </span>
                </div>
                <span class="text-xs text-muted-foreground">{{ formatDate(ticket.createdAt) }}</span>
              </div>
            </div>
          </div>
          <div v-else class="text-center py-8 text-muted-foreground">
            <Ticket class="mx-auto size-10 text-muted-foreground mb-2" />
            <p class="text-sm">
              {{ t('admin.noTickets') }}
            </p>
          </div>
        </UiCardContent>
      </UiCard>
    </div>
  </BasicPage>
</template>
