import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'

// Mock api/client.js
vi.mock('../../../api/client.js', () => ({
  adminListUsers: vi.fn(),
  adminUpdateAiConfig: vi.fn(),
}))

import AdminAiConfigTab from '../AdminAiConfigTab.vue'
import * as api from '../../../api/client.js'

function makeUser(overrides = {}) {
  return {
    id: overrides.id ?? 'user-1',
    email: overrides.email ?? 'alice@example.com',
    handle: overrides.handle ?? 'alice',
    role: 'user',
    is_active: true,
    ai_provider: overrides.ai_provider ?? null,
    ai_model: overrides.ai_model ?? null,
    ...overrides,
  }
}

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

// ── onMounted: calls adminListUsers() ─────────────────────────────────────────

describe('AdminAiConfigTab — onMounted', () => {
  it('calls adminListUsers() on mount', async () => {
    api.adminListUsers.mockResolvedValue({ items: [] })
    mount(AdminAiConfigTab)
    await flushPromises()
    expect(api.adminListUsers).toHaveBeenCalledTimes(1)
  })

  it('shows "No users yet" empty state when no users', async () => {
    api.adminListUsers.mockResolvedValue({ items: [] })
    const w = mount(AdminAiConfigTab)
    await flushPromises()
    expect(w.text()).toContain('No users yet')
  })

  it('renders a row per user', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [
        makeUser({ id: 'u1', email: 'alice@example.com' }),
        makeUser({ id: 'u2', email: 'bob@example.com' }),
      ],
    })
    const w = mount(AdminAiConfigTab)
    await flushPromises()
    expect(w.text()).toContain('alice@example.com')
    expect(w.text()).toContain('bob@example.com')
  })

  it('pre-populates existing ai_provider and ai_model in inputs', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser({ id: 'u1', ai_provider: 'openai', ai_model: 'gpt-4o' })],
    })
    const w = mount(AdminAiConfigTab)
    await flushPromises()

    // The select should have openai selected
    const select = w.find('select')
    expect(select.element.value).toBe('openai')

    // The model input should have gpt-4o
    const modelInput = w.find('input[type="text"]')
    expect(modelInput.element.value).toBe('gpt-4o')
  })
})

// ── saveConfig: calls adminUpdateAiConfig(id, provider, model) ────────────────

describe('AdminAiConfigTab — saveConfig', () => {
  it('calls adminUpdateAiConfig with user id, provider, and model on Save click', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser({ id: 'u1', email: 'alice@example.com', ai_provider: '', ai_model: '' })],
    })
    api.adminUpdateAiConfig.mockResolvedValue({})

    const w = mount(AdminAiConfigTab)
    await flushPromises()

    // Select a provider
    const select = w.find('select')
    await select.setValue('anthropic')

    // Enter a model
    const modelInput = w.find('input[type="text"]')
    await modelInput.setValue('claude-3-5-sonnet')

    // Click Save
    const saveBtn = w.findAll('button').find(b => b.text().includes('Save'))
    expect(saveBtn).toBeTruthy()
    await saveBtn.trigger('click')
    await flushPromises()

    expect(api.adminUpdateAiConfig).toHaveBeenCalledWith('u1', 'anthropic', 'claude-3-5-sonnet')
  })

  it('shows "Saved" confirmation text after successful save', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser({ id: 'u1', email: 'alice@example.com' })],
    })
    api.adminUpdateAiConfig.mockResolvedValue({})

    const w = mount(AdminAiConfigTab)
    await flushPromises()

    const saveBtn = w.findAll('button').find(b => b.text().includes('Save'))
    await saveBtn.trigger('click')
    await flushPromises()

    expect(w.text()).toContain('Saved')
  })

  it('passes null for empty provider string to API', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser({ id: 'u1', ai_provider: null, ai_model: null })],
    })
    api.adminUpdateAiConfig.mockResolvedValue({})

    const w = mount(AdminAiConfigTab)
    await flushPromises()

    // Select is empty string '' — saveConfig converts '' to null
    const saveBtn = w.findAll('button').find(b => b.text().includes('Save'))
    await saveBtn.trigger('click')
    await flushPromises()

    // Called with null for both empty provider and model
    expect(api.adminUpdateAiConfig).toHaveBeenCalledWith('u1', null, null)
  })
})
