import { renderHook, act } from '@testing-library/react'
import { useToast, clearAllToasts, reducer } from '../toast/use-toast'
import type { ToasterToast } from '../toast/use-toast'

beforeEach(() => {
  clearAllToasts()
})

describe('useToast', () => {
  it('adds a toast', () => {
    const { result } = renderHook(() => useToast())

    act(() => {
      result.current.toast({ title: 'Hello', description: 'World' })
    })

    expect(result.current.toasts).toHaveLength(1)
    expect(result.current.toasts[0].title).toBe('Hello')
    expect(result.current.toasts[0].description).toBe('World')
  })

  it('adds toast with variant', () => {
    const { result } = renderHook(() => useToast())

    act(() => {
      result.current.toast({ title: 'Error', variant: 'destructive' })
    })

    expect(result.current.toasts[0].variant).toBe('destructive')
  })

  it('dismisses a specific toast', () => {
    jest.useFakeTimers()
    const { result } = renderHook(() => useToast())

    let toastId: string
    act(() => {
      // Use duration: 0 to prevent auto-dismiss interference
      const t = result.current.toast({ title: 'Dismiss me', duration: 0 })
      toastId = t.id
    })

    expect(result.current.toasts).toHaveLength(1)

    act(() => {
      result.current.dismiss(toastId)
    })

    // Advance past the dismiss animation delay
    act(() => {
      jest.advanceTimersByTime(500)
    })

    expect(result.current.toasts).toHaveLength(0)
    jest.useRealTimers()
  })

  it('clears all toasts', () => {
    const { result } = renderHook(() => useToast())

    act(() => {
      result.current.toast({ title: 'One', duration: 0 })
      result.current.toast({ title: 'Two', duration: 0 })
      result.current.toast({ title: 'Three', duration: 0 })
    })

    expect(result.current.toasts.length).toBeGreaterThanOrEqual(1)

    act(() => {
      result.current.clear()
    })

    expect(result.current.toasts).toHaveLength(0)
  })
})

describe('reducer', () => {
  const makeToast = (id: string, title: string): ToasterToast => ({
    id,
    title,
  })

  it('ADD_TOAST adds to front of list', () => {
    const state = { toasts: [makeToast('1', 'First')] }
    const result = reducer(state, {
      type: 'ADD_TOAST',
      toast: makeToast('2', 'Second'),
    })
    expect(result.toasts[0].title).toBe('Second')
    expect(result.toasts).toHaveLength(2)
  })

  it('UPDATE_TOAST updates matching toast', () => {
    const state = { toasts: [makeToast('1', 'Original')] }
    const result = reducer(state, {
      type: 'UPDATE_TOAST',
      toast: { id: '1', title: 'Updated' },
    })
    expect(result.toasts[0].title).toBe('Updated')
  })

  it('REMOVE_TOAST with undefined removes all', () => {
    const state = {
      toasts: [makeToast('1', 'A'), makeToast('2', 'B')],
    }
    const result = reducer(state, {
      type: 'REMOVE_TOAST',
      toastId: undefined,
    })
    expect(result.toasts).toHaveLength(0)
  })

  it('REMOVE_TOAST with id removes specific toast', () => {
    const state = {
      toasts: [makeToast('1', 'A'), makeToast('2', 'B')],
    }
    const result = reducer(state, {
      type: 'REMOVE_TOAST',
      toastId: '1',
    })
    expect(result.toasts).toHaveLength(1)
    expect(result.toasts[0].id).toBe('2')
  })
})
