import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { allSettled, fork } from 'effector'
import { Provider } from 'effector-react'
import { MemoryRouter } from 'react-router-dom'
import { describe, it, expect, afterEach } from 'vitest'
import { addNotification, dismissAll, $notifications } from '../../model/notification'
import { NotificationStack } from './NotificationStack'

describe('NotificationStack', () => {
  afterEach(() => {
    dismissAll()
  })

  function createTestScope() {
    return fork()
  }

  function renderWithScope(scope: ReturnType<typeof fork>) {
    return render(
      <MemoryRouter>
        <Provider value={scope}>
          <NotificationStack />
        </Provider>
      </MemoryRouter>,
    )
  }

  it('renders nothing when empty', () => {
    const scope = createTestScope()
    const { container } = renderWithScope(scope)
    expect(container.textContent).toBe('')
  })

  it('renders a success notification with check icon', async () => {
    const scope = createTestScope()
    await allSettled(addNotification, { scope, params: { type: 'success', message: 'Success!' } })
    renderWithScope(scope)
    expect(screen.getByText('Success!')).toBeDefined()
  })

  it('renders error alert severity', async () => {
    const scope = createTestScope()
    await allSettled(addNotification, { scope, params: { type: 'error', message: 'Error!' } })
    renderWithScope(scope)
    const alert = screen.getByRole('alert')
    expect(alert).toBeDefined()
  })

  it('dismisses on close button click', async () => {
    const scope = createTestScope()
    await allSettled(addNotification, { scope, params: { type: 'info', message: 'Dismiss me' } })
    renderWithScope(scope)

    const closeBtn = screen.getByRole('button')
    fireEvent.click(closeBtn)

    await waitFor(() => {
      const state = scope.getState($notifications)
      expect(state).toHaveLength(0)
    })
  })

  it('renders multiple notifications up to 3', async () => {
    const scope = createTestScope()
    await allSettled(addNotification, { scope, params: { type: 'info', message: 'A' } })
    await allSettled(addNotification, { scope, params: { type: 'info', message: 'B' } })
    await allSettled(addNotification, { scope, params: { type: 'info', message: 'C' } })
    renderWithScope(scope)

    expect(screen.getByText('A')).toBeDefined()
    expect(screen.getByText('B')).toBeDefined()
    expect(screen.getByText('C')).toBeDefined()
  })
})
