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 { SeccionForm } from '../../../features/secciones/components/SeccionForm'
import type { SeccionFormValues } from '../../../features/secciones/components/SeccionForm'
import type { SeccionDetail } from '../../../features/secciones/types'

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

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

const mockMedios = [
  { id: 1, codigo: 'DIA01', nombre: 'Diario El Día', tipo: 1, plataformaEmpresaId: null, activo: true },
  { id: 2, codigo: 'RAD01', nombre: 'Radio AM', tipo: 2, plataformaEmpresaId: null, activo: true },
]

const sampleSeccion: SeccionDetail = {
  id: 1,
  medioId: 1,
  codigo: 'CLAS01',
  nombre: 'Clasificados Autos',
  tipo: 'clasificados',
  activo: true,
  fechaCreacion: '2026-01-01T00:00:00Z',
  fechaModificacion: null,
}

const server = setupServer()

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

function renderForm(opts: { initialData?: SeccionDetail; onSubmit?: (v: SeccionFormValues) => void } = {}) {
  const qc = new QueryClient({
    defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
  })
  const onSubmit = opts.onSubmit ?? vi.fn()
  server.use(
    http.get(`${API_URL}/api/v1/admin/medios`, () =>
      HttpResponse.json({ items: mockMedios, page: 1, pageSize: 200, total: 2 }),
    ),
  )
  render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <SeccionForm
          initialData={opts.initialData}
          isPending={false}
          error={null}
          onSubmit={onSubmit}
        />
      </MemoryRouter>
    </QueryClientProvider>,
  )
  return { onSubmit }
}

describe('SeccionForm — create mode', () => {
  it('shows validation error when código is empty', async () => {
    renderForm()
    await userEvent.click(screen.getByRole('button', { name: /crear sección/i }))
    await waitFor(() =>
      expect(screen.getByText(/código es requerido/i)).toBeInTheDocument(),
    )
  })

  it('shows validation error when tipo is not selected', async () => {
    renderForm()
    await userEvent.type(screen.getByLabelText(/código/i), 'CLAS99')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Mi Sección')
    await userEvent.click(screen.getByRole('button', { name: /crear sección/i }))
    await waitFor(() =>
      expect(screen.getByText(/seleccioná un tipo válido/i)).toBeInTheDocument(),
    )
  })

  it('calls onSubmit with correct values on valid form', async () => {
    const onSubmit = vi.fn()
    renderForm({ onSubmit })

    // Open Medio trigger, wait for medios to load, then pick one
    const medioTrigger = screen.getByRole('combobox', { name: /medio/i })
    await userEvent.click(medioTrigger)
    await waitFor(() =>
      expect(screen.getByRole('option', { name: 'Diario El Día' })).toBeInTheDocument(),
    )
    await userEvent.click(screen.getByRole('option', { name: 'Diario El Día' }))

    await userEvent.type(screen.getByLabelText(/código/i), 'CLAS99')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Mi Sección')

    // Open Tipo trigger and pick Clasificados
    const tipoTrigger = screen.getByRole('combobox', { name: /tipo de sección/i })
    await userEvent.click(tipoTrigger)
    await waitFor(() =>
      expect(screen.getByRole('option', { name: 'Clasificados' })).toBeInTheDocument(),
    )
    await userEvent.click(screen.getByRole('option', { name: 'Clasificados' }))

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

    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalled()
      const firstArg = onSubmit.mock.calls[0][0]
      expect(firstArg).toMatchObject({
        medioId: 1,
        codigo: 'CLAS99',
        nombre: 'Mi Sección',
        tipo: 'clasificados',
      })
    })
  })
})

describe('SeccionForm — edit mode', () => {
  it('código and medioId are disabled in edit mode', async () => {
    renderForm({ initialData: sampleSeccion })
    const codigoInput = screen.getByLabelText(/código/i) as HTMLInputElement
    expect(codigoInput.disabled).toBe(true)
    // Radix Select trigger is a <button> — check it's disabled
    const medioTrigger = screen.getByRole('combobox', { name: /medio/i })
    expect(medioTrigger).toBeDisabled()
  })

  it('pre-fills form with initialData values', async () => {
    renderForm({ initialData: sampleSeccion })
    await waitFor(() =>
      expect((screen.getByLabelText(/nombre/i) as HTMLInputElement).value).toBe('Clasificados Autos'),
    )
    expect((screen.getByLabelText(/código/i) as HTMLInputElement).value).toBe('CLAS01')
  })

  it('shows "Guardar cambios" button in edit mode', () => {
    renderForm({ initialData: sampleSeccion })
    expect(screen.getByRole('button', { name: /guardar cambios/i })).toBeInTheDocument()
  })
})
