import { describe, it, expect, vi, beforeEach } from 'vitest'
import { listMachines, getMachine, addMachine, updateMachine, deleteMachine } from '@/api/machine'
import * as request from '@/utils/request'
import { mockMachines, wrapResponse, wrapPageResponse, wrapErrorResponse } from '../../fixtures'

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

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

  describe('listMachines', () => {
    it('should call POST /admin/machines/list', async () => {
      const mockResponse = wrapPageResponse(mockMachines)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await listMachines()

      expect(request.post).toHaveBeenCalledWith('/admin/machines/list', {})
      expect(result.success).toBe(true)
      expect(result.data.list).toHaveLength(mockMachines.length)
      expect(result.data.list[0].machineId).toBe(mockMachines[0].machineId)
    })
  })

  describe('getMachine', () => {
    it('should call GET /admin/machines/detail with id', async () => {
      const machine = mockMachines[0]
      const mockResponse = wrapResponse(machine)
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getMachine(machine.id)

      expect(request.get).toHaveBeenCalledWith('/admin/machines/detail', { id: machine.id })
      expect(result.success).toBe(true)
      expect(result.data.id).toBe(machine.id)
    })
  })

  describe('addMachine', () => {
    it('should call POST /admin/machines/add with data', async () => {
      const newMachine = {
        ...mockMachines[0],
        id: 4,
        machineId: 'machine-004',
        name: '新机器',
        cameraCount: 0
      }
      const mockResponse = wrapResponse(newMachine)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const addData = {
        machineId: newMachine.machineId,
        name: newMachine.name,
        location: newMachine.location,
        description: newMachine.description
      }
      const result = await addMachine(addData)

      expect(request.post).toHaveBeenCalledWith('/admin/machines/add', addData)
      expect(result.success).toBe(true)
      expect(result.data.machineId).toBe(newMachine.machineId)
    })
  })

  describe('updateMachine', () => {
    it('should call POST /admin/machines/update with data', async () => {
      const machine = mockMachines[0]
      const updatedMachine = { ...machine, name: '更新后名称', location: '三楼' }
      const mockResponse = wrapResponse(updatedMachine)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const updateData = {
        id: machine.id,
        name: '更新后名称',
        location: '三楼',
        description: machine.description,
        enabled: machine.enabled
      }
      const result = await updateMachine(updateData)

      expect(request.post).toHaveBeenCalledWith('/admin/machines/update', updateData)
      expect(result.success).toBe(true)
      expect(result.data.name).toBe('更新后名称')
    })
  })

  describe('deleteMachine', () => {
    it('should call POST /admin/machines/delete with id', async () => {
      const mockResponse = wrapResponse(null)
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await deleteMachine(mockMachines[2].id) // Use machine with 0 cameras

      expect(request.post).toHaveBeenCalledWith('/admin/machines/delete', undefined, {
        params: { id: mockMachines[2].id }
      })
      expect(result.success).toBe(true)
    })

    it('should handle delete failure when machine has cameras', async () => {
      const mockResponse = wrapErrorResponse('该机器下存在摄像头，无法删除')
      vi.mocked(request.post).mockResolvedValue(mockResponse)

      const result = await deleteMachine(mockMachines[0].id) // Machine with cameras

      expect(result.success).toBe(false)
      expect(result.errMessage).toBe('该机器下存在摄像头，无法删除')
    })
  })
})
