/**
 * config-modules API 契约测试（menus + settings + languages + numberingRules + themes）
 */
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 * as menusApi from './menus'
import * as settingsApi from './settings'
import * as languagesApi from './languages'
import * as numberingApi from './numberingRules'
import * as themesApi from './themes'

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

// ============================================================
// menus
// ============================================================
describe('menus API', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('getMenus 应调用 GET /config/menus', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await menusApi.getMenus()

    expect(mockGet).toHaveBeenCalledWith('/config/menus')
  })

  it('getMenusForUser 应调用 GET /menus/user', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await menusApi.getMenusForUser()

    expect(mockGet).toHaveBeenCalledWith('/menus/user')
  })

  it('batchSaveMenus 应调用 PUT /config/menus 并传递 menus 数组', async () => {
    mockPut.mockResolvedValue(undefined)
    const menus = [{ title: '仪表盘', path: '/dashboard' }]
    await menusApi.batchSaveMenus(menus)

    expect(mockPut).toHaveBeenCalledWith('/config/menus', { menus })
  })

  it('createMenu 应调用 POST /config/menus', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { title: '新菜单', path: '/new', sort_order: 10 }
    await menusApi.createMenu(req)

    expect(mockPost).toHaveBeenCalledWith('/config/menus', req)
  })

  it('deleteMenu 应调用 DELETE /config/menus/:id 并在 body 传递 version', async () => {
    mockDelete.mockResolvedValue(undefined)
    await menusApi.deleteMenu('menu-001', 3)

    expect(mockDelete).toHaveBeenCalledWith('/config/menus/menu-001', { data: { version: 3 } })
  })
})

// ============================================================
// settings
// ============================================================
describe('settings API', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('getSetting 应调用 GET /config/settings/:key 并传递 scope 参数', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await settingsApi.getSetting('site.name', 'global', 'org-001')

    expect(mockGet).toHaveBeenCalledWith('/config/settings/site.name', {
      params: { scope: 'global', scope_id: 'org-001' },
    })
  })

  it('updateSetting 应调用 PUT /config/settings/:key', async () => {
    mockPut.mockResolvedValue(fakeRes)
    await settingsApi.updateSetting('site.name', '新名称', 1)

    expect(mockPut).toHaveBeenCalledWith('/config/settings/site.name', {
      setting_value: '新名称',
      version: 1,
    })
  })

  it('deleteSetting 应调用 DELETE /config/settings/:key', async () => {
    mockDelete.mockResolvedValue(undefined)
    await settingsApi.deleteSetting('site.name', 2)

    expect(mockDelete).toHaveBeenCalledWith('/config/settings/site.name', { data: { version: 2 } })
  })
})

// ============================================================
// languages
// ============================================================
describe('languages API', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listLanguages 应调用 GET /config/languages', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await languagesApi.listLanguages()

    expect(mockGet).toHaveBeenCalledWith('/config/languages')
  })

  it('updateLanguage 应调用 PUT /config/languages/:code', async () => {
    mockPut.mockResolvedValue(fakeRes)
    await languagesApi.updateLanguage('zh-CN', { is_active: true, name: '简体中文' })

    expect(mockPut).toHaveBeenCalledWith('/config/languages/zh-CN', {
      is_active: true,
      name: '简体中文',
    })
  })
})

// ============================================================
// numberingRules
// ============================================================
describe('numberingRules API', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('listNumberingRules 应调用 GET /config/numbering-rules', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await numberingApi.listNumberingRules(1, 10)

    expect(mockGet).toHaveBeenCalledWith('/config/numbering-rules', {
      params: { page: 1, page_size: 10 },
    })
  })

  it('createNumberingRule 应调用 POST /config/numbering-rules', async () => {
    mockPost.mockResolvedValue(fakeRes)
    const req = { name: '患者编号', code: 'patient', prefix: 'P', seq_length: 6 }
    await numberingApi.createNumberingRule(req)

    expect(mockPost).toHaveBeenCalledWith('/config/numbering-rules', req)
  })

  it('updateNumberingRule 应调用 PUT /config/numbering-rules/:id', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const req = { prefix: 'HMS', version: 1 }
    await numberingApi.updateNumberingRule('nr-001', req)

    expect(mockPut).toHaveBeenCalledWith('/config/numbering-rules/nr-001', req)
  })

  it('generateNumber 应调用 POST /config/numbering-rules/:id/generate', async () => {
    mockPost.mockResolvedValue(fakeRes)
    await numberingApi.generateNumber('nr-001')

    expect(mockPost).toHaveBeenCalledWith('/config/numbering-rules/nr-001/generate')
  })

  it('deleteNumberingRule 应调用 DELETE /config/numbering-rules/:id', async () => {
    mockDelete.mockResolvedValue(undefined)
    await numberingApi.deleteNumberingRule('nr-001', 1)

    expect(mockDelete).toHaveBeenCalledWith('/config/numbering-rules/nr-001', { data: { version: 1 } })
  })
})

// ============================================================
// themes
// ============================================================
describe('themes API', () => {
  const fakeRes = { data: { success: true, data: {} } }

  it('getTheme 应调用 GET /config/themes', async () => {
    mockGet.mockResolvedValue(fakeRes)
    await themesApi.getTheme()

    expect(mockGet).toHaveBeenCalledWith('/config/themes')
  })

  it('updateTheme 应调用 PUT /config/themes', async () => {
    mockPut.mockResolvedValue(fakeRes)
    const theme = { primary_color: '#1890ff', brand_name: 'HMS' }
    await themesApi.updateTheme(theme)

    expect(mockPut).toHaveBeenCalledWith('/config/themes', theme)
  })
})
