import { describe, it, expect, vi, beforeEach } from 'vitest'
import { listUsers, getUser, createUser, updateUser, deleteUser, resetPassword } from '@/api/user'
import * as request from '@/utils/request'

// Mock request module
vi.mock('@/utils/request', () => ({
  get: vi.fn(),
  post: vi.fn(),
  put: vi.fn(),
  del: vi.fn()
}))

describe('User API', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  describe('listUsers', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: [], total: 0 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      await listUsers()

      expect(request.get).toHaveBeenCalledWith('/users', undefined)
    })

    it('应该传递查询参数', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: [], total: 0 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const params = { page: 1, pageSize: 10, search: 'admin', role: 'admin' as const }
      await listUsers(params)

      expect(request.get).toHaveBeenCalledWith('/users', params)
    })

    it('应该返回用户列表数据', async () => {
      const mockUsers = [
        { id: '1', username: 'admin', role: 'admin' },
        { id: '2', username: 'user1', role: 'viewer' }
      ]
      const mockResponse = {
        code: 200,
        data: { rows: mockUsers, total: 2 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await listUsers()

      expect(result.data.rows).toEqual(mockUsers)
      expect(result.data.total).toBe(2)
    })
  })

  describe('getUser', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: { id: '1', username: 'admin', role: 'admin' }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      await getUser('1')

      expect(request.get).toHaveBeenCalledWith('/users/1')
    })

    it('应该返回用户详情', async () => {
      const mockUser = { id: '1', username: 'admin', role: 'admin' }
      const mockResponse = {
        code: 200,
        data: mockUser
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getUser('1')

      expect(result.data).toEqual(mockUser)
    })
  })

  describe('createUser', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: { id: '1', username: 'newuser', role: 'viewer' }
      }
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const userData = { username: 'newuser', password: '123456', role: 'viewer' as const }
      await createUser(userData)

      expect(request.post).toHaveBeenCalledWith('/users', userData)
    })

    it('应该返回创建的用户', async () => {
      const mockUser = { id: '1', username: 'newuser', role: 'viewer' }
      const mockResponse = {
        code: 200,
        data: mockUser
      }
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const userData = { username: 'newuser', password: '123456', role: 'viewer' as const }
      const result = await createUser(userData)

      expect(result.data).toEqual(mockUser)
    })
  })

  describe('updateUser', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: { id: '1', username: 'admin', role: 'admin' }
      }
      vi.mocked(request.put).mockResolvedValue(mockResponse)

      const updateData = { role: 'operator' as const }
      await updateUser('1', updateData)

      expect(request.put).toHaveBeenCalledWith('/users/1', updateData)
    })

    it('应该返回更新后的用户', async () => {
      const mockUser = { id: '1', username: 'admin', role: 'operator' }
      const mockResponse = {
        code: 200,
        data: mockUser
      }
      vi.mocked(request.put).mockResolvedValue(mockResponse)

      const updateData = { role: 'operator' as const }
      const result = await updateUser('1', updateData)

      expect(result.data).toEqual(mockUser)
    })
  })

  describe('deleteUser', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: null
      }
      vi.mocked(request.del).mockResolvedValue(mockResponse)

      await deleteUser('1')

      expect(request.del).toHaveBeenCalledWith('/users/1')
    })

    it('应该返回成功响应', async () => {
      const mockResponse = {
        code: 200,
        data: null,
        message: 'success'
      }
      vi.mocked(request.del).mockResolvedValue(mockResponse)

      const result = await deleteUser('1')

      expect(result.code).toBe(200)
    })
  })

  describe('resetPassword', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockResponse = {
        code: 200,
        data: null
      }
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      await resetPassword('1', 'newpassword')

      expect(request.post).toHaveBeenCalledWith('/users/1/reset-password', { password: 'newpassword' })
    })

    it('应该返回成功响应', async () => {
      const mockResponse = {
        code: 200,
        data: null,
        message: 'success'
      }
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await resetPassword('1', 'newpassword')

      expect(result.code).toBe(200)
    })
  })

  describe('错误处理', () => {
    it('API 错误应该被正确传递', async () => {
      const error = new Error('Network Error')
      vi.mocked(request.get).mockRejectedValue(error)

      await expect(listUsers()).rejects.toThrow('Network Error')
    })

    it('应该处理 API 返回的错误响应', async () => {
      const mockResponse = {
        code: 400,
        message: '用户名已存在',
        data: null
      }
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const userData = { username: 'existinguser', password: '123456', role: 'viewer' as const }
      const result = await createUser(userData)

      expect(result.code).toBe(400)
      expect(result.message).toBe('用户名已存在')
    })
  })
})
