import { describe, it, expect, vi, beforeEach } from 'vitest'
import { login, getInfo, logout, changePassword } from '@/api/login'
import * as request from '@/utils/request'
import { mockLoginResponse, mockAdminInfo, wrapResponse, wrapErrorResponse } from '../../fixtures'

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

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

  describe('login', () => {
    it('should call POST /admin/auth/login with credentials', async () => {
      const mockResponse = wrapResponse(mockLoginResponse)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await login({ username: 'admin', password: 'password123' })

      expect(request.post).toHaveBeenCalledWith('/admin/auth/login', {
        username: 'admin',
        password: 'password123'
      })
      expect(result.success).toBe(true)
      expect(result.data.token).toBe(mockLoginResponse.token)
    })

    it('should handle login failure', async () => {
      const mockResponse = wrapErrorResponse('用户名或密码错误', 401)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await login({ username: 'wrong', password: 'wrong' })

      expect(result.success).toBe(false)
      expect(result.errMessage).toBe('用户名或密码错误')
    })
  })

  describe('getInfo', () => {
    it('should call GET /admin/auth/info', async () => {
      const mockResponse = wrapResponse(mockAdminInfo)
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getInfo()

      expect(request.get).toHaveBeenCalledWith('/admin/auth/info')
      expect(result.success).toBe(true)
      expect(result.data.username).toBe(mockAdminInfo.username)
    })
  })

  describe('logout', () => {
    it('should call POST /admin/auth/logout', async () => {
      const mockResponse = wrapResponse(null)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await logout()

      expect(request.post).toHaveBeenCalledWith('/admin/auth/logout')
      expect(result.success).toBe(true)
    })
  })

  describe('changePassword', () => {
    it('should call POST /admin/auth/password with password data', async () => {
      const mockResponse = wrapResponse(null)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await changePassword({
        oldPassword: 'oldpass',
        newPassword: 'newpass'
      })

      expect(request.post).toHaveBeenCalledWith('/admin/auth/password', {
        oldPassword: 'oldpass',
        newPassword: 'newpass'
      })
      expect(result.success).toBe(true)
    })

    it('should handle wrong old password', async () => {
      const mockResponse = wrapErrorResponse('原密码错误', 400)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await changePassword({
        oldPassword: 'wrongpass',
        newPassword: 'newpass'
      })

      expect(result.success).toBe(false)
      expect(result.errMessage).toBe('原密码错误')
    })
  })
})
