import { describe, it, expect, vi } from 'vitest'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { MemoryRouter } from 'react-router-dom'
import { MedioForm } from '../../../features/medios/components/MedioForm'
import type { MedioFormValues } from '../../../features/medios/components/MedioForm'
import type { MedioDetail } from '../../../features/medios/types'

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

const sampleMedio: MedioDetail = {
  id: 1,
  codigo: 'DIA01',
  nombre: 'Diario Principal',
  tipo: 1,
  plataformaEmpresaId: null,
  activo: true,
  fechaCreacion: '2026-01-01T00:00:00Z',
  fechaModificacion: null,
}

function renderForm(opts: { initialData?: MedioDetail; onSubmit?: (v: MedioFormValues) => void } = {}) {
  const qc = new QueryClient({
    defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
  })
  const onSubmit = opts.onSubmit ?? vi.fn()
  render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <MedioForm
          initialData={opts.initialData}
          isPending={false}
          error={null}
          onSubmit={onSubmit}
        />
      </MemoryRouter>
    </QueryClientProvider>,
  )
  return { onSubmit }
}

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

  it('shows validation error when nombre is empty', async () => {
    renderForm()
    await userEvent.type(screen.getByLabelText(/código/i), 'COD1')
    await userEvent.click(screen.getByRole('button', { name: /crear medio/i }))
    await waitFor(() =>
      expect(screen.getByText(/nombre es requerido/i)).toBeInTheDocument(),
    )
  })

  it('shows validation error when tipo is not selected', async () => {
    renderForm()
    await userEvent.type(screen.getByLabelText(/código/i), 'COD1')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Mi Medio')
    await userEvent.click(screen.getByRole('button', { name: /crear medio/i }))
    // The form message for tipo validation appears as a <p> role
    await waitFor(() => {
      const messages = screen.getAllByText(/seleccioná un tipo/i)
      // At least one message should exist (validation error, not just the placeholder option)
      expect(messages.length).toBeGreaterThanOrEqual(1)
    })
  })

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

    await userEvent.type(screen.getByLabelText(/código/i), 'DIA99')
    await userEvent.type(screen.getByLabelText(/nombre/i), 'Mi Diario')

    // Open the Radix Select trigger and pick option
    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(onSubmit).toHaveBeenCalled()
      const firstArg = onSubmit.mock.calls[0][0]
      expect(firstArg).toMatchObject({ codigo: 'DIA99', nombre: 'Mi Diario', tipo: 1 })
    })
  })
})

describe('MedioForm — edit mode', () => {
  it('código field is disabled in edit mode', () => {
    renderForm({ initialData: sampleMedio })
    const codigoInput = screen.getByLabelText(/código/i) as HTMLInputElement
    expect(codigoInput.disabled).toBe(true)
  })

  it('pre-fills form with initialData values', () => {
    renderForm({ initialData: sampleMedio })
    expect((screen.getByLabelText(/código/i) as HTMLInputElement).value).toBe('DIA01')
    expect((screen.getByLabelText(/nombre/i) as HTMLInputElement).value).toBe('Diario Principal')
  })

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