/**
 * articles API 契约测试
 */
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 { articleApi, articleCategoryApi, articleTagApi } from './articles'

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

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

  it('list 应调用 GET /health/articles 并传递查询参数', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await articleApi.list({ page: 1, page_size: 10, status: 'published', category_id: 'cat-001' })

    expect(mockGet).toHaveBeenCalledWith('/health/articles', {
      params: { page: 1, page_size: 10, status: 'published', category_id: 'cat-001' },
    })
  })

  it('get 应调用 GET /health/articles/:id', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await articleApi.get('art-001')

    expect(mockGet).toHaveBeenCalledWith('/health/articles/art-001')
  })

  it('create 应调用 POST /health/articles', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { title: '健康饮食指南', content: '正文内容', content_type: 'markdown' as const }
    await articleApi.create(req)

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

  it('update 应调用 PUT /health/articles/:id 并传递请求体', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { title: '健康饮食指南(修订)', version: 1 }
    await articleApi.update('art-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/articles/art-001', req)
  })

  it('delete 应调用 DELETE /health/articles/:id', async () => {
    mockDelete.mockResolvedValue({ data: { success: true, data: null } })
    await articleApi.delete('art-001', 1)

    expect(mockDelete).toHaveBeenCalledWith('/health/articles/art-001')
  })

  it('submit 应调用 POST /health/articles/:id/submit 并传递 version', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await articleApi.submit('art-001', 2)

    expect(mockPost).toHaveBeenCalledWith('/health/articles/art-001/submit', { version: 2 })
  })

  it('approve 应调用 POST /health/articles/:id/approve', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await articleApi.approve('art-001', 2)

    expect(mockPost).toHaveBeenCalledWith('/health/articles/art-001/approve', { version: 2 })
  })

  it('reject 应调用 POST /health/articles/:id/reject 并传递 review_note', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await articleApi.reject('art-001', 2, '内容需要修改')

    expect(mockPost).toHaveBeenCalledWith('/health/articles/art-001/reject', {
      version: 2,
      review_note: '内容需要修改',
    })
  })

  it('unpublish 应调用 POST /health/articles/:id/unpublish', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await articleApi.unpublish('art-001', 3)

    expect(mockPost).toHaveBeenCalledWith('/health/articles/art-001/unpublish', { version: 3 })
  })

  it('view 应调用 POST /health/articles/:id/view', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await articleApi.view('art-001')

    expect(mockPost).toHaveBeenCalledWith('/health/articles/art-001/view')
  })
})

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

  it('list 应调用 GET /health/article-categories', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await articleCategoryApi.list()

    expect(mockGet).toHaveBeenCalledWith('/health/article-categories')
  })

  it('create 应调用 POST /health/article-categories', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { name: '营养健康', sort_order: 1 }
    await articleCategoryApi.create(req)

    expect(mockPost).toHaveBeenCalledWith('/health/article-categories', req)
  })

  it('update 应调用 PUT /health/article-categories/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { name: '营养健康(更新)' }
    await articleCategoryApi.update('cat-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/article-categories/cat-001', req)
  })

  it('delete 应调用 DELETE /health/article-categories/:id', async () => {
    mockDelete.mockResolvedValue({ data: { success: true, data: null } })
    await articleCategoryApi.delete('cat-001')

    expect(mockDelete).toHaveBeenCalledWith('/health/article-categories/cat-001')
  })
})

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

  it('list 应调用 GET /health/article-tags', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await articleTagApi.list()

    expect(mockGet).toHaveBeenCalledWith('/health/article-tags')
  })

  it('create 应调用 POST /health/article-tags', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { name: '高血压', color: '#ff0000' }
    await articleTagApi.create(req)

    expect(mockPost).toHaveBeenCalledWith('/health/article-tags', req)
  })

  it('update 应调用 PUT /health/article-tags/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { name: '高血压管理', version: 1 }
    await articleTagApi.update('tag-001', req)

    expect(mockPut).toHaveBeenCalledWith('/health/article-tags/tag-001', req)
  })

  it('delete 应调用 DELETE /health/article-tags/:id 并在 body 传递 version', async () => {
    mockDelete.mockResolvedValue({ data: { success: true, data: null } })
    await articleTagApi.delete('tag-001', 2)

    expect(mockDelete).toHaveBeenCalledWith('/health/article-tags/tag-001', { data: { version: 2 } })
  })
})
