import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { MemoryRouter } from 'react-router-dom'
import { RolesList } from '../../../features/roles/components/RolesList'

const API_URL = 'http://localhost:5000'

const canonical = [
  { id: 1, codigo: 'admin', nombre: 'Administrador', descripcion: 'Todo', activo: true, fechaCreacion: '2026-04-15T00:00:00Z', fechaModificacion: null },
  { id: 2, codigo: 'cajero', nombre: 'Cajero', descripcion: 'Mostrador', activo: true, fechaCreacion: '2026-04-15T00:00:00Z', fechaModificacion: null },
  { id: 3, codigo: 'reportes', nombre: 'Reportes', descripcion: null, activo: false, fechaCreacion: '2026-04-15T00:00:00Z', fechaModificacion: null },
]

const server = setupServer()

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

function renderList() {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } })
  return render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <RolesList />
      </MemoryRouter>
    </QueryClientProvider>,
  )
}

describe('RolesList', () => {
  it('renders all roles including inactive with correct badge', async () => {
    server.use(http.get(`${API_URL}/api/v1/roles`, () => HttpResponse.json(canonical)))

    renderList()

    await waitFor(() => expect(screen.getByText('Administrador')).toBeInTheDocument())
    expect(screen.getByText('Cajero')).toBeInTheDocument()
    expect(screen.getByText('Reportes')).toBeInTheDocument()

    // Active badge for cajero, inactive for reportes
    const activeBadges = screen.getAllByText(/^Activo$/)
    expect(activeBadges.length).toBeGreaterThanOrEqual(2)
    expect(screen.getByText(/^Inactivo$/)).toBeInTheDocument()
  })

  it('hides Deactivate button for already-inactive roles', async () => {
    server.use(http.get(`${API_URL}/api/v1/roles`, () => HttpResponse.json(canonical)))

    renderList()

    await waitFor(() => expect(screen.getByText('Reportes')).toBeInTheDocument())

    // There should be Deactivate buttons only for active roles (2: admin, cajero).
    const deactivateButtons = screen.getAllByRole('button', { name: /desactivar/i })
    expect(deactivateButtons).toHaveLength(2)
  })

  it('shows 409 error alert when deactivate blocked by active usuarios', async () => {
    server.use(
      http.get(`${API_URL}/api/v1/roles`, () => HttpResponse.json(canonical)),
      http.delete(`${API_URL}/api/v1/roles/cajero`, () =>
        HttpResponse.json(
          { error: 'rol_in_use', message: "El rol 'cajero' no puede desactivarse porque existen usuarios activos." },
          { status: 409 },
        ),
      ),
    )

    const u = userEvent.setup()
    renderList()

    await waitFor(() => expect(screen.getByText('Cajero')).toBeInTheDocument())

    // Click Deactivate on cajero row (first active row with deactivate button after admin).
    const buttons = screen.getAllByRole('button', { name: /desactivar/i })
    // Admin is listed first in canonical; cajero deactivate button is index 1.
    await u.click(buttons[1]!)

    await waitFor(() => {
      expect(screen.getByRole('alert')).toHaveTextContent(/no puede desactivarse/i)
    })
  })
})
