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

vi.mock('../../../api/client.js', () => ({
  adminListAuditLog: vi.fn().mockResolvedValue({ items: [], total: 0 }),
  adminExportAuditLogCsv: vi.fn().mockResolvedValue({}),
  adminListDailyExports: vi.fn().mockResolvedValue({ items: [] }),
  adminDownloadDailyExport: vi.fn().mockResolvedValue({}),
}))

const stubs = {
  BreadcrumbBar: true,
  EmptyState: true,
  AppIcon: true,
}

async function mountAudit(overrides = {}) {
  const { default: AdminAuditView } = await import('../AdminAuditView.vue')
  return mount(AdminAuditView, {
    global: { stubs, plugins: [createPinia()] },
    ...overrides,
  })
}

describe('UX-04: AdminAuditView shows skeleton table rows during loading', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.resetModules()
  })

  it('renders 8 skeleton <tr> rows when loading=true', async () => {
    const { adminListAuditLog } = await import('../../../api/client.js')
    adminListAuditLog.mockReturnValue(new Promise(() => {})) // never resolves => loading stays true
    const wrapper = await mountAudit()
    const tbody = wrapper.find('tbody')
    expect(tbody.exists()).toBe(true)
    const rows = tbody.findAll('tr')
    expect(rows.length).toBeGreaterThanOrEqual(8)
  })

  it('skeleton rows have exactly 5 <td> cells matching column count', async () => {
    const { adminListAuditLog } = await import('../../../api/client.js')
    adminListAuditLog.mockReturnValue(new Promise(() => {}))
    const wrapper = await mountAudit()
    const rows = wrapper.find('tbody').findAll('tr')
    rows.forEach(row => {
      expect(row.findAll('td').length).toBe(5)
    })
  })

  it('Loading audit log text is absent when loading=true', async () => {
    const { adminListAuditLog } = await import('../../../api/client.js')
    adminListAuditLog.mockReturnValue(new Promise(() => {}))
    const wrapper = await mountAudit()
    expect(wrapper.text()).not.toContain('Loading audit log')
  })
})

describe('UX-01 (audit empty): EmptyState renders when entries is empty after load', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.resetModules()
  })

  it('renders <EmptyState icon="clipboardList" headline="No entries found"> when entries empty and not loading', async () => {
    const { adminListAuditLog } = await import('../../../api/client.js')
    adminListAuditLog.mockResolvedValue({ items: [], total: 0 })
    const wrapper = await mountAudit()
    await new Promise(r => setTimeout(r, 50))
    await wrapper.vm.$nextTick()
    const emptyState = wrapper.findComponent({ name: 'EmptyState' })
    expect(emptyState.exists()).toBe(true)
    expect(emptyState.attributes('icon') ?? emptyState.props('icon')).toBe('clipboardList')
    const headline = emptyState.attributes('headline') ?? emptyState.props('headline')
    expect(headline).toBe('No entries found')
  })

  it('EmptyState includes a Clear filters CTA button', async () => {
    const { adminListAuditLog } = await import('../../../api/client.js')
    adminListAuditLog.mockResolvedValue({ items: [], total: 0 })
    // Mount with EmptyState NOT stubbed so slot content renders
    const { default: AdminAuditView } = await import('../AdminAuditView.vue')
    const wrapper = mount(AdminAuditView, {
      global: { stubs: { BreadcrumbBar: true, AppIcon: true }, plugins: [createPinia()] },
    })
    await new Promise(r => setTimeout(r, 50))
    await wrapper.vm.$nextTick()
    expect(wrapper.text()).toContain('Clear filters')
  })
})
