import { describe, expect, it, vi, beforeEach } from 'vitest'
import { flushPromises, mount } from '@vue/test-utils'
import { defineComponent } from 'vue'
import SoraAdminView from '../SoraAdminView.vue'
import type { SoraSystemStats, SoraUserStats, SoraGenerationAdmin } from '@/api/admin/sora'

// 使用 vi.hoisted 确保 mock 函数在 mock 工厂函数执行前定义
const {
  mockGetSystemStats,
  mockListUserStats,
  mockListGenerations,
  mockClearUserStorage
} = vi.hoisted(() => ({
  mockGetSystemStats: vi.fn(),
  mockListUserStats: vi.fn(),
  mockListGenerations: vi.fn(),
  mockClearUserStorage: vi.fn()
}))

vi.mock('@/api/admin/sora', () => ({
  default: {
    getSystemStats: mockGetSystemStats,
    listUserStats: mockListUserStats,
    listGenerations: mockListGenerations,
    clearUserStorage: mockClearUserStorage
  }
}))

vi.mock('vue-i18n', async () => {
  const actual = await vi.importActual<typeof import('vue-i18n')>('vue-i18n')
  return {
    ...actual,
    useI18n: () => ({
      t: (key: string) => key
    })
  }
})

// Stub child components
const AppLayoutStub = defineComponent({
  name: 'AppLayout',
  template: '<div class="app-layout"><slot /></div>'
})

const LoadingSpinnerStub = defineComponent({
  name: 'LoadingSpinner',
  template: '<div class="loading-spinner" />'
})

const IconStub = defineComponent({
  name: 'Icon',
  props: ['name', 'size'],
  template: '<span class="icon" />'
})

const BaseButtonStub = defineComponent({
  name: 'BaseButton',
  props: ['variant', 'size'],
  emits: ['click'],
  template: '<button @click="$emit(\'click\')"><slot /></button>'
})

function createMockSystemStats(overrides: Partial<SoraSystemStats> = {}): SoraSystemStats {
  return {
    total_users: 10,
    total_generations: 100,
    total_storage_bytes: 5 * 1024 * 1024 * 1024,
    active_generations: 3,
    by_status: { completed: 80, failed: 15, pending: 5 },
    by_model: { sora2: 60, sora1: 40 },
    ...overrides
  }
}

function createMockUserStats(): SoraUserStats[] {
  return [
    {
      user_id: 1,
      username: 'user1',
      email: 'user1@example.com',
      quota_bytes: 10 * 1024 * 1024 * 1024,
      used_bytes: 2 * 1024 * 1024 * 1024,
      available_bytes: 8 * 1024 * 1024 * 1024,
      quota_source: 'user',
      generations_count: 20,
      active_count: 1,
      total_file_size_bytes: 1 * 1024 * 1024 * 1024
    }
  ]
}

function createMockGenerations(): SoraGenerationAdmin[] {
  return [
    {
      id: 1,
      user_id: 1,
      username: 'user1',
      email: 'user1@example.com',
      model: 'sora2',
      prompt: 'A beautiful sunset',
      media_type: 'video',
      status: 'completed',
      storage_type: 's3',
      media_url: 'https://example.com/video.mp4',
      file_size_bytes: 10 * 1024 * 1024,
      error_message: '',
      created_at: '2024-01-01T10:00:00Z',
      completed_at: '2024-01-01T10:05:00Z'
    }
  ]
}

describe('SoraAdminView', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockGetSystemStats.mockResolvedValue(createMockSystemStats())
    mockListUserStats.mockResolvedValue({
      items: createMockUserStats(),
      total: 1,
      page: 1,
      page_size: 20,
      pages: 1
    })
    mockListGenerations.mockResolvedValue({
      items: createMockGenerations(),
      total: 1,
      page: 1,
      page_size: 20,
      pages: 1
    })
  })

  function mountComponent() {
    return mount(SoraAdminView, {
      global: {
        stubs: {
          AppLayout: AppLayoutStub,
          LoadingSpinner: LoadingSpinnerStub,
          Icon: IconStub
        }
      }
    })
  }

  describe('初始加载', () => {
    it('加载时显示 loading spinner', () => {
      const wrapper = mountComponent()
      expect(wrapper.find('.loading-spinner').exists()).toBe(true)
    })

    it('加载完成后显示页面内容', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      expect(wrapper.find('.loading-spinner').exists()).toBe(false)
      expect(wrapper.find('.app-layout').exists()).toBe(true)
    })

    it('加载完成后调用所有 API', async () => {
      mountComponent()
      await flushPromises()

      expect(mockGetSystemStats).toHaveBeenCalled()
      expect(mockListUserStats).toHaveBeenCalled()
      expect(mockListGenerations).toHaveBeenCalled()
    })
  })

  describe('概览标签页', () => {
    it('默认显示概览标签页', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      // 概览标签页应显示统计卡片
      const cards = wrapper.findAll('.card')
      expect(cards.length).toBeGreaterThan(0)
    })

    it('显示系统统计数据', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      expect(wrapper.text()).toContain('10')   // total_users
      expect(wrapper.text()).toContain('100')  // total_generations
      expect(wrapper.text()).toContain('3')    // active_generations
    })

    it('显示按状态分布', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      expect(wrapper.text()).toContain('completed')
      expect(wrapper.text()).toContain('80')
    })

    it('显示按模型分布', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      expect(wrapper.text()).toContain('sora2')
      expect(wrapper.text()).toContain('60')
    })
  })

  describe('用户统计标签页', () => {
    it('点击用户统计标签切换到用户列表', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      const tabs = wrapper.findAll('button')
      const userTab = tabs.find(b => b.text().includes('admin.sora.userStats'))
      await userTab?.trigger('click')
      await flushPromises()

      expect(wrapper.find('table').exists()).toBe(true)
      expect(wrapper.text()).toContain('user1')
      expect(wrapper.text()).toContain('user1@example.com')
    })
  })

  describe('生成记录标签页', () => {
    it('点击生成记录标签切换到记录列表', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      const tabs = wrapper.findAll('button')
      const genTab = tabs.find(b => b.text().includes('admin.sora.generations'))
      await genTab?.trigger('click')
      await flushPromises()

      expect(wrapper.find('table').exists()).toBe(true)
      expect(wrapper.text()).toContain('user1')
      expect(wrapper.text()).toContain('sora2')
      expect(wrapper.text()).toContain('completed')
    })
  })

  describe('API 错误处理', () => {
    it('API 错误时不会崩溃', async () => {
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
      mockGetSystemStats.mockRejectedValue(new Error('Network error'))

      const wrapper = mountComponent()
      await flushPromises()

      expect(wrapper.exists()).toBe(true)
      consoleSpy.mockRestore()
    })
  })

  describe('格式化函数', () => {
    it('正确格式化字节数', async () => {
      const wrapper = mountComponent()
      await flushPromises()

      // 5 GB 应该显示为 "5 GB"
      expect(wrapper.text()).toContain('5 GB')
    })
  })
})
