/**
 * 测试工具函数
 */

import { mount, VueWrapper } from '@vue/test-utils'
import { Component } from 'vue'
import { Router, createRouter, createWebHistory } from 'vue-router'
import { createPinia, Pinia } from 'pinia'
import { expect } from 'vitest'

// 测试路由配置
export const createTestRouter = (routes: any[] = []): Router => {
  return createRouter({
    history: createWebHistory(),
    routes: [
      { path: '/', name: 'Home', component: { template: '<div>Home</div>' } },
      { path: '/login', name: 'Login', component: { template: '<div>Login</div>' } },
      { path: '/404', name: 'NotFound', component: { template: '<div>404</div>' } },
      ...routes
    ]
  })
}

// 创建测试用的 Pinia 实例
export const createTestPinia = (): Pinia => {
  return createPinia()
}

// 挂载组件的增强函数
export interface MountOptions {
  props?: Record<string, any>
  slots?: Record<string, any>
  router?: Router
  pinia?: Pinia
  global?: {
    plugins?: any[]
    mocks?: Record<string, any>
    stubs?: Record<string, any>
    provide?: Record<string, any>
  }
}

export const mountComponent = (
  component: Component,
  options: MountOptions = {}
): VueWrapper => {
  const { props, slots, router, pinia, global } = options

  const plugins = []
  const provide: Record<string, any> = {}
  
  if (router) {
    plugins.push(router)
  }
  
  if (pinia) {
    plugins.push(pinia)
  }

  return mount(component, {
    props,
    slots,
    global: {
      plugins,
      provide: {
        ...provide,
        ...global?.provide
      },
      mocks: {
        ...global?.mocks
      },
      stubs: {
        ...global?.stubs
      }
    }
  })
}

// 等待 DOM 更新
export const waitForUpdate = async (wrapper: VueWrapper): Promise<void> => {
  await wrapper.vm.$nextTick()
}

// 模拟用户交互
export const userInteraction = {
  // 点击元素
  async click(wrapper: VueWrapper, selector: string): Promise<void> {
    const element = wrapper.find(selector)
    await element.trigger('click')
    await waitForUpdate(wrapper)
  },

  // 输入文本
  async type(wrapper: VueWrapper, selector: string, text: string): Promise<void> {
    const input = wrapper.find(selector)
    await input.setValue(text)
    await waitForUpdate(wrapper)
  },

  // 提交表单
  async submit(wrapper: VueWrapper, selector: string = 'form'): Promise<void> {
    const form = wrapper.find(selector)
    await form.trigger('submit')
    await waitForUpdate(wrapper)
  },

  // 鼠标悬停
  async hover(wrapper: VueWrapper, selector: string): Promise<void> {
    const element = wrapper.find(selector)
    await element.trigger('mouseenter')
    await waitForUpdate(wrapper)
  },

  // 键盘事件
  async keydown(wrapper: VueWrapper, selector: string, key: string): Promise<void> {
    const element = wrapper.find(selector)
    await element.trigger('keydown', { key })
    await waitForUpdate(wrapper)
  }
}

// 模拟 API 响应
export const mockApiResponse = {
  success: <T>(data: T) => ({
    code: 200,
    message: 'success',
    data
  }),

  error: (message: string, code: number = 400) => ({
    code,
    message,
    data: null
  }),

  paginated: <T>(items: T[], total?: number, page: number = 1, size: number = 10) => ({
    code: 200,
    message: 'success',
    data: {
      items,
      total: total ?? items.length,
      page,
      size
    }
  })
}

// 创建模拟用户数据
export const createMockUser = (overrides: Partial<any> = {}) => ({
  id: 1,
  username: 'testuser',
  email: 'test@example.com',
  full_name: '测试用户',
  role: 'trainee',
  is_active: true,
  created_at: '2024-01-01T00:00:00.000Z',
  updated_at: '2024-01-01T00:00:00.000Z',
  ...overrides
})

// 创建模拟课程数据
export const createMockCourse = (overrides: Partial<any> = {}) => ({
  id: 1,
  title: '测试课程',
  description: '这是一个测试课程',
  coverImage: '',
  category: '技术',
  difficulty: 'beginner',
  duration: 60,
  materialCount: 5,
  progress: 0,
  rating: 4.5,
  status: 'published',
  tags: ['测试', '课程'],
  createdAt: '2024-01-01T00:00:00.000Z',
  updatedAt: '2024-01-01T00:00:00.000Z',
  ...overrides
})

// 创建模拟考试数据
export const createMockExam = (overrides: Partial<any> = {}) => ({
  id: '1',
  name: '测试考试',
  type: 'practice',
  subject: '测试科目',
  totalScore: 100,
  userScore: 85,
  accuracy: 0.85,
  duration: 3600,
  status: 'completed',
  startTime: '2024-01-01T10:00:00.000Z',
  endTime: '2024-01-01T11:00:00.000Z',
  createdAt: '2024-01-01T10:00:00.000Z',
  ...overrides
})

// 创建模拟陪练记录数据
export const createMockPracticeRecord = (overrides: Partial<any> = {}) => ({
  id: '1',
  sceneId: 1,
  sceneName: '测试陪练场景',
  sceneCategory: '技术面试',
  duration: 1800,
  messageCount: 20,
  overallScore: 85,
  result: 'good',
  startTime: '2024-01-01T14:00:00.000Z',
  endTime: '2024-01-01T14:30:00.000Z',
  createdAt: '2024-01-01T14:30:00.000Z',
  ...overrides
})

// 断言辅助函数
export const assertions = {
  // 检查元素是否存在
  elementExists(wrapper: VueWrapper, selector: string): void {
    expect(wrapper.find(selector).exists()).toBe(true)
  },

  // 检查元素是否不存在
  elementNotExists(wrapper: VueWrapper, selector: string): void {
    expect(wrapper.find(selector).exists()).toBe(false)
  },

  // 检查元素文本
  elementText(wrapper: VueWrapper, selector: string, expectedText: string): void {
    expect(wrapper.find(selector).text()).toBe(expectedText)
  },

  // 检查元素是否包含文本
  elementContainsText(wrapper: VueWrapper, selector: string, expectedText: string): void {
    expect(wrapper.find(selector).text()).toContain(expectedText)
  },

  // 检查元素是否可见
  elementVisible(wrapper: VueWrapper, selector: string): void {
    const element = wrapper.find(selector)
    expect(element.exists()).toBe(true)
    expect(element.isVisible()).toBe(true)
  },

  // 检查元素是否隐藏
  elementHidden(wrapper: VueWrapper, selector: string): void {
    const element = wrapper.find(selector)
    if (element.exists()) {
      expect(element.isVisible()).toBe(false)
    }
  },

  // 检查表单字段值
  inputValue(wrapper: VueWrapper, selector: string, expectedValue: string): void {
    const input = wrapper.find(selector)
    expect((input.element as HTMLInputElement).value).toBe(expectedValue)
  },

  // 检查路由导航
  routePushed(mockRouter: any, expectedRoute: string | object): void {
    expect(mockRouter.push).toHaveBeenCalledWith(expectedRoute)
  }
}

// 时间相关工具
export const timeUtils = {
  // 模拟延时
  delay: (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms)),

  // 获取当前时间戳
  now: (): number => Date.now(),

  // 格式化时间
  format: (date: Date | string | number): string => {
    const d = new Date(date)
    return d.toISOString()
  }
}

// 随机数据生成器
export const faker = {
  // 随机字符串
  string: (length: number = 10): string => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  },

  // 随机数字
  number: (min: number = 0, max: number = 100): number => {
    return Math.floor(Math.random() * (max - min + 1)) + min
  },

  // 随机邮箱
  email: (): string => {
    return `${faker.string(8)}@example.com`
  },

  // 随机中文姓名
  chineseName: (): string => {
    const surnames = ['王', '李', '张', '刘', '陈', '杨', '赵', '黄', '周', '吴']
    const names = ['伟', '芳', '娜', '敏', '静', '丽', '强', '磊', '军', '洋']
    return surnames[Math.floor(Math.random() * surnames.length)] + 
           names[Math.floor(Math.random() * names.length)]
  },

  // 随机布尔值
  boolean: (): boolean => Math.random() < 0.5
}
