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 React from 'react'
import { DeactivateProductDialog } from '../../../features/products/components/DeactivateProductDialog'
import type { ProductListItem } from '../../../features/products/types'

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

const sampleProduct: ProductListItem = {
  id: 1,
  nombre: 'Clasificado Estándar',
  medioId: 1,
  productTypeId: 2,
  rubroId: null,
  basePrice: 100.5,
  priceDurationDays: null,
  isActive: true,
}

function wrap(children: React.ReactNode) {
  const qc = new QueryClient({
    defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
  })
  return render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>{children}</MemoryRouter>
    </QueryClientProvider>,
  )
}

describe('DeactivateProductDialog', () => {
  it('renders confirmation message with product name', () => {
    wrap(
      <DeactivateProductDialog
        open={true}
        onOpenChange={vi.fn()}
        product={sampleProduct}
        onConfirm={vi.fn()}
      />,
    )
    expect(screen.getByText(/Clasificado Estándar/i)).toBeInTheDocument()
    expect(screen.getByRole('heading', { name: /desactivar producto/i })).toBeInTheDocument()
  })

  it('calls onConfirm with product id when user confirms', async () => {
    const onConfirm = vi.fn().mockResolvedValue(undefined)
    wrap(
      <DeactivateProductDialog
        open={true}
        onOpenChange={vi.fn()}
        product={sampleProduct}
        onConfirm={onConfirm}
      />,
    )
    const buttons = screen.getAllByRole('button', { name: /desactivar/i })
    const confirmBtn = buttons.find((b) => b.textContent?.trim() === 'Desactivar')!
    await userEvent.click(confirmBtn)
    await waitFor(() => expect(onConfirm).toHaveBeenCalledWith(sampleProduct.id))
  })

  it('shows inline error when backend returns 409', async () => {
    const onConfirm = vi.fn(() =>
      Promise.reject({
        response: { status: 409, data: { message: 'No se puede desactivar: el producto está en uso.' } },
      }),
    )
    wrap(
      <DeactivateProductDialog
        open={true}
        onOpenChange={vi.fn()}
        product={sampleProduct}
        onConfirm={onConfirm}
      />,
    )
    const buttons = screen.getAllByRole('button', { name: /desactivar/i })
    const confirmBtn = buttons.find((b) => b.textContent?.trim() === 'Desactivar')!
    await userEvent.click(confirmBtn)
    await waitFor(() => {
      expect(screen.getByText(/en uso/i)).toBeInTheDocument()
    })
  })

  it('closes dialog when cancel is clicked', async () => {
    const onOpenChange = vi.fn()
    wrap(
      <DeactivateProductDialog
        open={true}
        onOpenChange={onOpenChange}
        product={sampleProduct}
        onConfirm={vi.fn()}
      />,
    )
    await userEvent.click(screen.getByRole('button', { name: /cancelar/i }))
    await waitFor(() => expect(onOpenChange).toHaveBeenCalled())
  })
})
