// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'

vi.mock('@/actions/products', () => ({
  createProductAction: vi.fn(),
  updateProductAction: vi.fn(),
}))
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }))
vi.mock('@/stores/products-store', () => ({
  useProductsStore: vi.fn((selector: (s: { addProduct: () => void; updateProduct: () => void }) => unknown) =>
    selector({ addProduct: vi.fn(), updateProduct: vi.fn() })
  ),
}))

import { ProductDialog } from '@/components/dialogs/product-dialog'
import { createProductAction, updateProductAction } from '@/actions/products'
import { toast } from 'sonner'

const mockCreate = createProductAction as ReturnType<typeof vi.fn>
const mockUpdate = updateProductAction as ReturnType<typeof vi.fn>
const mockToast = toast as unknown as {
  success: ReturnType<typeof vi.fn>
  error: ReturnType<typeof vi.fn>
}

const PRODUCT = {
  id: 'prod-1',
  name: 'Mijn Product',
  code: 'MP',
  description: 'Een product',
  repo_url: 'https://github.com/org/repo',
  definition_of_done: 'Alles groen',
  auto_pr: false,
}

beforeEach(() => {
  vi.clearAllMocks()
})

describe('ProductDialog — create mode', () => {
  it('rendert met lege velden en "Nieuw product" titel', () => {
    render(
      <ProductDialog mode="create" open={true} onOpenChange={vi.fn()} />
    )
    expect(screen.getByText('Nieuw product')).toBeTruthy()
    expect(screen.getByLabelText(/Naam/)).toBeTruthy()
    expect((screen.getByLabelText(/Naam/) as HTMLInputElement).value).toBe('')
  })

  it('toont validatiefout als naam leeg is bij submit', async () => {
    render(
      <ProductDialog mode="create" open={true} onOpenChange={vi.fn()} />
    )
    fireEvent.click(screen.getByRole('button', { name: 'Aanmaken' }))

    await waitFor(() => {
      expect(screen.getByText('Naam is verplicht')).toBeTruthy()
    })
    expect(mockCreate).not.toHaveBeenCalled()
  })

  it('roept createProductAction aan bij geldig formulier', async () => {
    mockCreate.mockResolvedValue({ success: true, productId: 'new-prod' })

    render(
      <ProductDialog mode="create" open={true} onOpenChange={vi.fn()} />
    )

    fireEvent.change(screen.getByLabelText(/Naam/), { target: { value: 'Nieuw Product' } })
    fireEvent.submit(document.getElementById('product-form')!)

    await waitFor(() => {
      expect(mockCreate).toHaveBeenCalledWith(
        expect.objectContaining({ name: 'Nieuw Product' })
      )
    })
    expect(mockToast.success).toHaveBeenCalledWith('Product aangemaakt')
  })

  it('toont error-toast als createProductAction een error retourneert', async () => {
    mockCreate.mockResolvedValue({ error: 'Code is al in gebruik' })

    render(
      <ProductDialog mode="create" open={true} onOpenChange={vi.fn()} />
    )

    fireEvent.change(screen.getByLabelText(/Naam/), { target: { value: 'Test' } })
    fireEvent.submit(document.getElementById('product-form')!)

    await waitFor(() => {
      expect(mockToast.error).toHaveBeenCalledWith('Code is al in gebruik')
    })
  })
})

describe('ProductDialog — edit mode', () => {
  it('rendert met bestaande waarden vooringevuld', () => {
    render(
      <ProductDialog mode="edit" open={true} onOpenChange={vi.fn()} product={PRODUCT} />
    )
    expect(screen.getByText('Product bewerken')).toBeTruthy()
    expect((screen.getByLabelText(/Naam/) as HTMLInputElement).value).toBe('Mijn Product')
  })

  it('roept updateProductAction aan bij opslaan', async () => {
    mockUpdate.mockResolvedValue({ success: true })

    render(
      <ProductDialog mode="edit" open={true} onOpenChange={vi.fn()} product={PRODUCT} />
    )

    fireEvent.change(screen.getByLabelText(/Naam/), { target: { value: 'Gewijzigd Product' } })
    fireEvent.submit(document.getElementById('product-form')!)

    await waitFor(() => {
      expect(mockUpdate).toHaveBeenCalledWith(
        PRODUCT.id,
        expect.objectContaining({ name: 'Gewijzigd Product' })
      )
    })
    expect(mockToast.success).toHaveBeenCalledWith('Product opgeslagen')
  })
})

describe('ProductDialog — demo mode', () => {
  it('submit-knop is disabled in demo-modus', () => {
    render(
      <ProductDialog mode="create" open={true} onOpenChange={vi.fn()} isDemo={true} />
    )
    const submitBtn = screen.getByRole('button', { name: 'Aanmaken' })
    expect(submitBtn).toHaveProperty('disabled', true)
  })
})
