/**
 * points API 契约测试（完整覆盖 pointsApi + pointsAdminApi）
 */
import { describe, it, expect, vi, beforeEach } from 'vitest'

const mockGet = vi.fn()
const mockPost = vi.fn()
const mockPut = vi.fn()
const mockDelete = vi.fn()

vi.mock('../client', () => ({
  default: {
    get: (...args: unknown[]) => mockGet(...args),
    post: (...args: unknown[]) => mockPost(...args),
    put: (...args: unknown[]) => mockPut(...args),
    delete: (...args: unknown[]) => mockDelete(...args),
  },
}))

import { pointsApi, pointsAdminApi } from './points'

beforeEach(() => {
  vi.clearAllMocks()
})

describe('pointsAdminApi', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('getPatientAccount 应调用 GET /health/admin/points/patients/:id/account', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsAdminApi.getPatientAccount('p-001')

    expect(mockGet).toHaveBeenCalledWith('/health/admin/points/patients/p-001/account')
  })

  it('listPatientTransactions 应调用 GET 并传递分页参数', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsAdminApi.listPatientTransactions('p-001', { page: 2, page_size: 15 })

    expect(mockGet).toHaveBeenCalledWith('/health/admin/points/patients/p-001/transactions', {
      params: { page: 2, page_size: 15 },
    })
  })
})

describe('pointsApi - Rules', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listRules 应调用 GET /health/admin/points/rules', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.listRules()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/points/rules')
  })

  it('createRule 应调用 POST /health/admin/points/rules', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { event_type: 'daily_checkin', name: '每日签到', points_value: 10, daily_cap: 1 }
    await pointsApi.createRule(req)

    expect(mockPost).toHaveBeenCalledWith('/health/admin/points/rules', req)
  })

  it('updateRule 应调用 PUT /health/admin/points/rules/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { points_value: 20, version: 1 }
    await pointsApi.updateRule('rule-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/admin/points/rules/rule-001', {
      data: req,
      version: req.version,
    })
  })

  it('deleteRule 应调用 DELETE /health/admin/points/rules/:id', async () => {
    mockDelete.mockResolvedValue(undefined)
    await pointsApi.deleteRule('rule-001', 2)

    expect(mockDelete).toHaveBeenCalledWith('/health/admin/points/rules/rule-001', {
      data: { version: 2 },
    })
  })
})

describe('pointsApi - Products', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listProducts 应调用 GET /health/points/products', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.listProducts()

    expect(mockGet).toHaveBeenCalledWith('/health/points/products', { params: undefined })
  })

  it('createProduct 应调用 POST /health/admin/points/products', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { name: '体检优惠券', product_type: 'service', points_cost: 500, stock: 100 }
    await pointsApi.createProduct(req)

    expect(mockPost).toHaveBeenCalledWith('/health/admin/points/products', req)
  })

  it('updateProduct 应调用 PUT /health/admin/points/products/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { points_cost: 600, version: 1 }
    await pointsApi.updateProduct('prod-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/admin/points/products/prod-001', {
      data: req,
      version: req.version,
    })
  })

  it('deleteProduct 应调用 DELETE /health/admin/points/products/:id', async () => {
    mockDelete.mockResolvedValue(undefined)
    await pointsApi.deleteProduct('prod-001', 1)

    expect(mockDelete).toHaveBeenCalledWith('/health/admin/points/products/prod-001', {
      data: { version: 1 },
    })
  })
})

describe('pointsApi - Orders', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listOrders 应调用 GET /health/admin/points/orders', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.listOrders()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/points/orders', { params: undefined })
  })

  it('verifyOrder 应调用 POST /health/points/verify', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { qr_code: 'QR-123456' }
    await pointsApi.verifyOrder(req)

    expect(mockPost).toHaveBeenCalledWith('/health/points/verify', req)
  })
})

describe('pointsApi - Offline Events', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listOfflineEvents 应调用 GET /health/admin/offline-events', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.listOfflineEvents()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/offline-events', { params: undefined })
  })

  it('createOfflineEvent 应调用 POST /health/admin/offline-events', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { title: '健康讲座', event_date: '2026-05-20', points_reward: 50 }
    await pointsApi.createOfflineEvent(req)

    expect(mockPost).toHaveBeenCalledWith('/health/admin/offline-events', req)
  })

  it('updateOfflineEvent 应调用 PUT /health/admin/offline-events/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { title: '健康讲座(更新)', version: 1 }
    await pointsApi.updateOfflineEvent('evt-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/admin/offline-events/evt-001', req)
  })

  it('deleteOfflineEvent 应调用 DELETE /health/admin/offline-events/:id', async () => {
    mockDelete.mockResolvedValue(undefined)
    await pointsApi.deleteOfflineEvent('evt-001', 1)

    expect(mockDelete).toHaveBeenCalledWith('/health/admin/offline-events/evt-001', {
      data: { version: 1 },
    })
  })
})

describe('pointsApi - Statistics', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('getStatistics 应调用 GET /health/admin/points/statistics', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getStatistics()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/points/statistics')
  })

  it('getPatientStats 应调用 GET /health/admin/statistics/patients', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getPatientStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/patients')
  })

  it('getConsultationStats 应调用 GET /health/admin/statistics/consultations', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getConsultationStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/consultations')
  })

  it('getFollowUpStats 应调用 GET /health/admin/statistics/follow-ups', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getFollowUpStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/follow-ups')
  })

  it('getHealthDataStats 应调用 GET /health/admin/statistics/health-data', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getHealthDataStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/health-data')
  })

  it('getDialysisStats 应调用 GET /health/admin/statistics/dialysis', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getDialysisStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/dialysis')
  })

  it('getPersonalStats 应调用 GET /health/admin/statistics/personal-stats', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await pointsApi.getPersonalStats()

    expect(mockGet).toHaveBeenCalledWith('/health/admin/statistics/personal-stats')
  })
})
