import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import DashboardView from '@/views/dashboard/index.vue'
import { wrapResponse, mockDashboardStats } from '../../../fixtures'

// Mock vue-router
const mockPush = vi.fn()
vi.mock('vue-router', () => ({
  useRouter: () => ({ push: mockPush }),
  useRoute: () => ({ query: {} })
}))

// Mock element-plus
vi.mock('element-plus', () => ({
  ElMessage: {
    success: vi.fn(),
    error: vi.fn(),
    info: vi.fn()
  }
}))

// Mock __APP_VERSION__
vi.stubGlobal('__APP_VERSION__', '1.0.0')

// Mock stats API
const mockGetDashboardStats = vi.fn()
vi.mock('@/api/stats', () => ({
  getDashboardStats: () => mockGetDashboardStats()
}))

// Create i18n instance
const i18n = createI18n({
  legacy: false,
  locale: 'zh-CN',
  messages: {
    'zh-CN': {
      仪表盘: '仪表盘',
      '欢迎回来，这是您的数据概览': '欢迎回来，这是您的数据概览',
      机器总数: '机器总数',
      已启用: '已启用',
      已禁用: '已禁用',
      摄像头总数: '摄像头总数',
      在线: '在线',
      离线: '离线',
      通道总数: '通道总数',
      可用通道数量: '可用通道数量',
      摄像头在线率: '摄像头在线率',
      系统运行正常: '系统运行正常',
      快捷操作: '快捷操作',
      刷新数据: '刷新数据',
      摄像头管理: '摄像头管理',
      机器管理: '机器管理',
      'Stream 测试': 'Stream 测试',
      观看统计: '观看统计',
      系统信息: '系统信息',
      系统状态: '系统状态',
      正常: '正常',
      数据更新时间: '数据更新时间',
      版本: '版本',
      获取统计数据失败: '获取统计数据失败'
    }
  }
})

describe('Dashboard View', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.clearAllMocks()
    mockGetDashboardStats.mockResolvedValue(wrapResponse(mockDashboardStats))
    mockPush.mockClear()
  })

  const mountDashboard = () => {
    return mount(DashboardView, {
      global: {
        plugins: [createPinia(), i18n]
      }
    })
  }

  describe('页面渲染', () => {
    it('应该正确渲染仪表盘页面', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.page-container').exists()).toBe(true)
      expect(wrapper.find('.dashboard__header').exists()).toBe(true)
      expect(wrapper.find('.dashboard__title').exists()).toBe(true)
    })

    it('应该显示页面标题', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.dashboard__title').text()).toBe('仪表盘')
    })

    it('应该显示统计卡片', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.dashboard__stats').exists()).toBe(true)
      expect(wrapper.findAll('.dashboard__card').length).toBe(4)
    })

    it('应该显示快捷操作按钮', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.dashboard__actions').exists()).toBe(true)
      expect(wrapper.findAll('.dashboard__action').length).toBeGreaterThan(0)
    })

    it('应该显示系统信息', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.dashboard__info').exists()).toBe(true)
    })
  })

  describe('数据加载', () => {
    it('页面加载时应该调用获取统计数据 API', async () => {
      mountDashboard()
      await flushPromises()

      expect(mockGetDashboardStats).toHaveBeenCalled()
    })

    it('应该正确显示机器总数', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const cards = wrapper.findAll('.dashboard__card')
      const machineCard = cards[0]
      expect(machineCard.find('.dashboard__card-value').text()).toBe(String(mockDashboardStats.machineTotal))
    })

    it('应该正确显示摄像头总数', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const cards = wrapper.findAll('.dashboard__card')
      const cameraCard = cards[1]
      expect(cameraCard.find('.dashboard__card-value').text()).toBe(String(mockDashboardStats.cameraTotal))
    })

    it('应该正确显示通道总数', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const cards = wrapper.findAll('.dashboard__card')
      const channelCard = cards[2]
      expect(channelCard.find('.dashboard__card-value').text()).toBe(String(mockDashboardStats.channelTotal))
    })

    it('应该正确计算并显示在线率', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const expectedRate = Math.round((mockDashboardStats.cameraOnline / mockDashboardStats.cameraTotal) * 100)
      const cards = wrapper.findAll('.dashboard__card')
      const rateCard = cards[3]
      expect(rateCard.find('.dashboard__card-value').text()).toContain(String(expectedRate))
    })
  })

  describe('快捷操作导航', () => {
    it('点击摄像头管理应该跳转', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const actions = wrapper.findAll('.dashboard__action')
      const cameraAction = actions.find((a) => a.text().includes('摄像头管理'))

      if (cameraAction) {
        await cameraAction.trigger('click')
        expect(mockPush).toHaveBeenCalledWith('/camera')
      }
    })

    it('点击机器管理应该跳转', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const actions = wrapper.findAll('.dashboard__action')
      const machineAction = actions.find((a) => a.text().includes('机器管理'))

      if (machineAction) {
        await machineAction.trigger('click')
        expect(mockPush).toHaveBeenCalledWith('/machine')
      }
    })

    it('点击 Stream 测试应该跳转', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const actions = wrapper.findAll('.dashboard__action')
      const streamAction = actions.find((a) => a.text().includes('Stream 测试'))

      if (streamAction) {
        await streamAction.trigger('click')
        expect(mockPush).toHaveBeenCalledWith('/stream-test')
      }
    })

    it('点击观看统计应该跳转', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const actions = wrapper.findAll('.dashboard__action')
      const statsAction = actions.find((a) => a.text().includes('观看统计'))

      if (statsAction) {
        await statsAction.trigger('click')
        expect(mockPush).toHaveBeenCalledWith('/stats')
      }
    })
  })

  describe('刷新数据', () => {
    it('点击刷新按钮应该重新加载数据', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      mockGetDashboardStats.mockClear()

      const refreshBtn = wrapper.find('.dashboard__refresh')
      await refreshBtn.trigger('click')
      await flushPromises()

      expect(mockGetDashboardStats).toHaveBeenCalled()
    })

    it('刷新时应该显示加载状态', async () => {
      let resolvePromise: Function
      mockGetDashboardStats.mockImplementation(
        () =>
          new Promise((resolve) => {
            resolvePromise = resolve
          })
      )

      const wrapper = mountDashboard()
      await flushPromises()

      mockGetDashboardStats.mockClear()
      mockGetDashboardStats.mockImplementation(
        () =>
          new Promise((resolve) => {
            resolvePromise = () => resolve(wrapResponse(mockDashboardStats))
          })
      )

      const refreshBtn = wrapper.find('.dashboard__refresh')
      await refreshBtn.trigger('click')

      // 检查加载状态图标
      expect(wrapper.find('.dashboard__refresh-icon').exists()).toBe(true)

      resolvePromise!()
      await flushPromises()
    })
  })

  describe('错误处理', () => {
    it('获取数据失败应该显示错误消息', async () => {
      const { ElMessage } = await import('element-plus')
      mockGetDashboardStats.mockResolvedValue(wrapResponse(null, false, '服务器错误'))

      mountDashboard()
      await flushPromises()

      // 错误处理逻辑测试
      expect(mockGetDashboardStats).toHaveBeenCalled()
    })

    it('网络错误应该显示错误消息', async () => {
      mockGetDashboardStats.mockResolvedValue(wrapResponse(null, false, '网络错误'))

      mountDashboard()
      await flushPromises()

      expect(mockGetDashboardStats).toHaveBeenCalled()
    })
  })

  describe('系统信息', () => {
    it('应该显示系统状态为正常', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.find('.dashboard__badge--success').text()).toBe('正常')
    })

    it('应该显示版本号', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      expect(wrapper.text()).toContain('v1.0.0')
    })

    it('数据更新后应该显示更新时间', async () => {
      const wrapper = mountDashboard()
      await flushPromises()

      const infoItems = wrapper.findAll('.dashboard__info-item')
      const updateTimeItem = infoItems.find((item) => item.text().includes('数据更新时间'))
      expect(updateTimeItem).toBeDefined()
    })
  })

  describe('空数据处理', () => {
    it('无数据时应该显示默认值', async () => {
      mockGetDashboardStats.mockResolvedValue(wrapResponse(null))

      const wrapper = mountDashboard()
      await flushPromises()

      const cards = wrapper.findAll('.dashboard__card')
      // 默认值为 0
      expect(cards[0].find('.dashboard__card-value').text()).toBe('0')
    })

    it('在线率为零时应该显示 0%', async () => {
      mockGetDashboardStats.mockResolvedValue(
        wrapResponse({
          ...mockDashboardStats,
          cameraTotal: 0,
          cameraOnline: 0
        })
      )

      const wrapper = mountDashboard()
      await flushPromises()

      const cards = wrapper.findAll('.dashboard__card')
      const rateCard = cards[3]
      expect(rateCard.find('.dashboard__card-value').text()).toContain('0')
    })
  })
})
