import { describe, it, expect, vi, beforeEach } from 'vitest'
import { getAuditLogs, getAuditLogDetail, getAuditLogStats, getUserAuditLogs, getResourceAuditLogs } from '@/api/audit'
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()
}))

// Mock audit logs data
const mockAuditLogs = [
  {
    id: '1',
    user_id: 'user-1',
    username: 'admin',
    action: 'create',
    resource: 'camera',
    resource_id: 'cam-001',
    ip_address: '192.168.1.1',
    created_at: 1704067200
  },
  {
    id: '2',
    user_id: 'user-1',
    username: 'admin',
    action: 'login',
    resource: 'auth',
    ip_address: '192.168.1.1',
    created_at: 1704063600
  }
]

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

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

      await getAuditLogs()

      expect(request.get).toHaveBeenCalledWith('/audit-logs', undefined)
    })

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

      const params = { action: 'create', resource: 'camera', page: 1, pageSize: 20 }
      await getAuditLogs(params)

      expect(request.get).toHaveBeenCalledWith('/audit-logs', params)
    })

    it('应该返回审计日志列表', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: mockAuditLogs, total: 2 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getAuditLogs()

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

    it('应该支持日期范围过滤', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: [], total: 0 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const params = {
        start_date: '2024-01-01',
        end_date: '2024-01-31'
      }
      await getAuditLogs(params)

      expect(request.get).toHaveBeenCalledWith('/audit-logs', params)
    })
  })

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

      await getAuditLogDetail('1')

      expect(request.get).toHaveBeenCalledWith('/audit-logs/1')
    })

    it('应该返回审计日志详情', async () => {
      const mockResponse = {
        code: 200,
        data: mockAuditLogs[0]
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getAuditLogDetail('1')

      expect(result.data).toEqual(mockAuditLogs[0])
    })
  })

  describe('getAuditLogStats', () => {
    it('应该调用正确的 API 端点', async () => {
      const mockStats = {
        period_days: 7,
        total: 100,
        by_action: [{ action: 'create', count: 50 }],
        by_resource: [{ resource: 'camera', count: 30 }],
        by_user: [{ user_id: 'user-1', username: 'admin', count: 80 }],
        daily: [{ date: '2024-01-01', count: 15 }]
      }
      const mockResponse = {
        code: 200,
        data: mockStats
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      await getAuditLogStats()

      expect(request.get).toHaveBeenCalledWith('/audit-logs/stats/summary', { days: 7 })
    })

    it('应该支持自定义天数', async () => {
      const mockResponse = {
        code: 200,
        data: { period_days: 30 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      await getAuditLogStats(30)

      expect(request.get).toHaveBeenCalledWith('/audit-logs/stats/summary', { days: 30 })
    })

    it('应该返回统计数据', async () => {
      const mockStats = {
        period_days: 7,
        total: 100,
        by_action: [{ action: 'create', count: 50 }],
        by_resource: [{ resource: 'camera', count: 30 }],
        by_user: [{ user_id: 'user-1', username: 'admin', count: 80 }],
        daily: [{ date: '2024-01-01', count: 15 }]
      }
      const mockResponse = {
        code: 200,
        data: mockStats
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getAuditLogStats()

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

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

      await getUserAuditLogs('user-1')

      expect(request.get).toHaveBeenCalledWith('/audit-logs/user/user-1', undefined)
    })

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

      await getUserAuditLogs('user-1', { page: 2, pageSize: 10 })

      expect(request.get).toHaveBeenCalledWith('/audit-logs/user/user-1', { page: 2, pageSize: 10 })
    })

    it('应该返回用户操作历史', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: mockAuditLogs, total: 2 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getUserAuditLogs('user-1')

      expect(result.data.rows).toEqual(mockAuditLogs)
    })
  })

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

      await getResourceAuditLogs('camera', 'cam-001')

      expect(request.get).toHaveBeenCalledWith('/audit-logs/resource/camera/cam-001', undefined)
    })

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

      await getResourceAuditLogs('camera', 'cam-001', { page: 1, pageSize: 20 })

      expect(request.get).toHaveBeenCalledWith('/audit-logs/resource/camera/cam-001', { page: 1, pageSize: 20 })
    })

    it('应该返回资源操作历史', async () => {
      const mockResponse = {
        code: 200,
        data: { rows: [mockAuditLogs[0]], total: 1 }
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getResourceAuditLogs('camera', 'cam-001')

      expect(result.data.rows).toHaveLength(1)
      expect(result.data.rows[0].resource).toBe('camera')
    })
  })

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

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

    it('应该处理 API 返回的错误响应', async () => {
      const mockResponse = {
        code: 403,
        message: '无权限访问',
        data: null
      }
      vi.mocked(request.get).mockResolvedValue(mockResponse)

      const result = await getAuditLogs()

      expect(result.code).toBe(403)
      expect(result.message).toBe('无权限访问')
    })
  })
})
