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(),
  adminDeactivateUser: vi.fn(),
  adminReactivateUser: vi.fn(),
  adminDeleteUser: vi.fn(),
  adminResetUserPassword: vi.fn(),
  adminCreateUser: vi.fn(),
}))

import AdminUsersTab from '../AdminUsersTab.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: overrides.role ?? 'user',
    is_active: overrides.is_active ?? true,
    totp_enabled: false,
    created_at: '2026-01-01T00:00:00Z',
    ...overrides,
  }
}

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

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

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

  it('populates user list from API response', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser({ id: 'u1', email: 'alice@example.com' })],
    })
    const w = mount(AdminUsersTab)
    await flushPromises()
    expect(w.text()).toContain('alice@example.com')
  })

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

  it('does NOT show "No users yet" when users are present', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser()],
    })
    const w = mount(AdminUsersTab)
    await flushPromises()
    expect(w.text()).not.toContain('No users yet')
  })
})

// ── Deactivate flow ───────────────────────────────────────────────────────────

describe('AdminUsersTab — deactivateUser', () => {
  it('calls adminDeactivateUser(id) when user confirms deactivation', async () => {
    const user = makeUser({ id: 'target-id', is_active: true })
    api.adminListUsers.mockResolvedValue({ items: [user] })
    api.adminDeactivateUser.mockResolvedValue({ is_active: false })

    const w = mount(AdminUsersTab)
    await flushPromises()

    // Click "Deactivate" to enter confirmation state
    const deactivateBtn = w.findAll('button').find(b => b.text().trim() === 'Deactivate')
    expect(deactivateBtn).toBeTruthy()
    await deactivateBtn.trigger('click')
    await w.vm.$nextTick()

    // Now click the confirmation "Deactivate" button in the inline panel
    const confirmBtn = w.findAll('button').find(b => b.text().trim() === 'Deactivate')
    expect(confirmBtn).toBeTruthy()
    await confirmBtn.trigger('click')
    await flushPromises()

    expect(api.adminDeactivateUser).toHaveBeenCalledWith('target-id')
  })

  it('marks user as inactive in UI after deactivation', async () => {
    const user = makeUser({ id: 'u1', is_active: true })
    api.adminListUsers.mockResolvedValue({ items: [user] })
    api.adminDeactivateUser.mockResolvedValue({ is_active: false })

    const w = mount(AdminUsersTab)
    await flushPromises()

    // Trigger deactivate flow
    const deactivateBtn = w.findAll('button').find(b => b.text().trim() === 'Deactivate')
    await deactivateBtn.trigger('click')
    await w.vm.$nextTick()

    const confirmBtn = w.findAll('button').find(b => b.text().trim() === 'Deactivate')
    await confirmBtn.trigger('click')
    await flushPromises()

    // The row should now show "Deactivated" status
    expect(w.text()).toContain('Deactivated')
  })
})

// ── Multiple users rendered ───────────────────────────────────────────────────

describe('AdminUsersTab — user list rendering', () => {
  it('renders all users returned by API', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [
        makeUser({ id: 'u1', email: 'alice@example.com' }),
        makeUser({ id: 'u2', email: 'bob@example.com' }),
      ],
    })

    const w = mount(AdminUsersTab)
    await flushPromises()

    expect(w.text()).toContain('alice@example.com')
    expect(w.text()).toContain('bob@example.com')
  })

  it('shows user count', async () => {
    api.adminListUsers.mockResolvedValue({
      items: [makeUser(), makeUser({ id: 'u2', email: 'b@b.com' })],
    })

    const w = mount(AdminUsersTab)
    await flushPromises()

    expect(w.text()).toContain('2 users')
  })
})
