import { describe, it, expect, beforeAll, afterAll, afterEach, vi } 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 { CreateMedioPage } from '../../../features/medios/pages/CreateMedioPage'

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

const mockNavigate = vi.fn()
vi.mock('react-router-dom', async (importOriginal) => {
  const actual = await importOriginal<typeof import('react-router-dom')>()
  return { ...actual, useNavigate: () => mockNavigate }
})

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

const server = setupServer()

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

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

describe('CreateMedioPage', () => {
  it('renders the create form with correct title', () => {
    renderPage()
    expect(screen.getByRole('heading', { name: /crear medio/i })).toBeInTheDocument()
  })

  it('successfully creates a medio and navigates away', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/admin/medios`, () =>
        HttpResponse.json(
          { id: 10, codigo: 'RAD01', nombre: 'Radio AM', tipo: 2, plataformaEmpresaId: null, activo: true },
          { status: 201 },
        ),
      ),
    )

    renderPage()

    await userEvent.type(screen.getByLabelText(/código/i), 'RAD01')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Radio AM')

    // Open Radix Select trigger and pick "Radio" (value=2)
    await userEvent.click(screen.getByRole('combobox', { name: /tipo/i }))
    await userEvent.click(screen.getByRole('option', { name: /^radio$/i }))

    await userEvent.click(screen.getByRole('button', { name: /crear medio/i }))

    await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/admin/medios'))
  })

  it('shows backend error when codigo is duplicated', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/admin/medios`, () =>
        HttpResponse.json(
          { error: 'medio_codigo_duplicado', message: 'Ya existe un medio con ese código' },
          { status: 409 },
        ),
      ),
    )

    renderPage()

    await userEvent.type(screen.getByLabelText(/código/i), 'DUP01')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Duplicado')

    // Open Radix Select trigger and pick "Diario" (value=1)
    await userEvent.click(screen.getByRole('combobox', { name: /tipo/i }))
    await userEvent.click(screen.getByRole('option', { name: /^diario$/i }))

    await userEvent.click(screen.getByRole('button', { name: /crear medio/i }))

    await waitFor(() =>
      expect(screen.getByRole('alert')).toHaveTextContent(/ya existe un medio con ese código/i),
    )
  })

  it('submit button is labeled "Crear medio"', () => {
    renderPage()
    expect(screen.getByRole('button', { name: /crear medio/i })).toBeInTheDocument()
  })
})
