import { describe, it, expect, vi, afterEach, beforeAll, afterAll } 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 { DeleteChargeableCharConfigDialog } from '../components/DeleteChargeableCharConfigDialog'

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }))

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

const server = setupServer()
beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }))
afterEach(() => { server.resetHandlers(); vi.clearAllMocks() })
afterAll(() => server.close())

function renderDialog(
  configId = 1,
  symbol = '$',
  onOpenChange = vi.fn(),
) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } })
  return render(
    <QueryClientProvider client={qc}>
      <DeleteChargeableCharConfigDialog
        open={true}
        onOpenChange={onOpenChange}
        configId={configId}
        symbol={symbol}
      />
    </QueryClientProvider>,
  )
}

describe('DeleteChargeableCharConfigDialog', () => {
  it('renders dialog with symbol in warning text', async () => {
    renderDialog(1, '$')

    await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument())
    expect(screen.getByText(/eliminará permanentemente/i)).toBeInTheDocument()
    expect(screen.getByText(/'\$'/)).toBeInTheDocument()
    expect(screen.getByText(/no está en uso/i)).toBeInTheDocument()
  })

  it('confirm button calls delete mutation and shows success toast', async () => {
    const { toast } = await import('sonner')
    server.use(
      http.delete(`${API_URL}/api/v1/admin/chargeable-chars/5`, () =>
        HttpResponse.json({ id: 5 }),
      ),
    )
    const onOpenChange = vi.fn()
    renderDialog(5, '%', onOpenChange)

    await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument())

    const confirmBtn = screen.getByRole('button', { name: /eliminar/i })
    await userEvent.click(confirmBtn)

    await waitFor(() => expect(onOpenChange).toHaveBeenCalledWith(false), { timeout: 5000 })
    expect(toast.success).toHaveBeenCalledWith(expect.stringContaining('%'))
  })

  it('cancel button closes dialog without calling mutation', async () => {
    const deleteCalls: unknown[] = []
    server.use(
      http.delete(`${API_URL}/api/v1/admin/chargeable-chars/1`, async () => {
        deleteCalls.push(true)
        return HttpResponse.json({ id: 1 })
      }),
    )
    const onOpenChange = vi.fn()
    renderDialog(1, '$', onOpenChange)

    await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument())

    const cancelBtn = screen.getByRole('button', { name: /cancelar/i })
    await userEvent.click(cancelBtn)

    await waitFor(() => expect(onOpenChange).toHaveBeenCalledWith(false))
    expect(deleteCalls.length).toBe(0)
  })
})
