import { describe, expect, it, vi } from 'vitest'

import {
  act,
  fireEvent,
  renderWithProviders,
  screen,
} from '../../../test/utils'

import VideoViewer from './VideoViewer'

describe('VideoViewer', () => {
  const items = [
    {
      src: 'https://cdn.example.com/one.mp4',
      poster: '/one.jpg',
      mimeType: 'video/mp4',
      filename: 'one.mp4',
      preload: 'auto' as const,
    },
    { src: 'https://cdn.example.com/two.webm', mimeType: 'video/webm' },
  ]

  it('renders nothing with no active video', () => {
    const { container } = renderWithProviders(
      <VideoViewer open onClose={vi.fn()} items={[]} />
    )
    expect(container.firstChild).toBeNull()
  })

  it('renders media attributes and an optional source type', () => {
    renderWithProviders(
      <VideoViewer open onClose={vi.fn()} items={[items[0]]} />
    )
    const video = screen.getByTestId('video-viewer').querySelector('video')
    expect(video).not.toBeNull()
    if (!video) throw new Error('Expected video element')
    expect(video).toHaveAttribute('src', items[0].src)
    expect(video).toHaveAttribute('poster', items[0].poster)
    expect(video).toHaveAttribute('preload', 'auto')
    expect(video).toHaveAttribute('autoplay')
    expect(video?.muted).toBe(true)
    expect(video.querySelector('source')).toHaveAttribute('type', 'video/mp4')
  })

  it('defaults preload and navigates stacked items', () => {
    renderWithProviders(<VideoViewer open onClose={vi.fn()} items={items} />)
    expect(screen.getByText('1 / 2')).toBeInTheDocument()
    expect(
      screen.getByTestId('video-viewer').querySelector('video')
    ).toHaveAttribute('preload', 'auto')
    fireEvent.click(screen.getByRole('button', { name: 'Next video' }))
    expect(
      screen.getByTestId('video-viewer').querySelector('video')
    ).toHaveAttribute('src', items[1].src)
    expect(
      screen.getByTestId('video-viewer').querySelector('video')
    ).toHaveAttribute('preload', 'metadata')
  })

  it('pauses the toolkit\u2019s own native audio when it opens', () => {
    // `useActiveAudioPlayer` only covers the players stream-chat-react
    // mounts. `MessageAttachment.Audio` and the playable `LinkAttachment`
    // card render plain `<audio>` elements that never reach that pool, so
    // without the marker sweep thread audio kept sounding under the video.
    const audio = document.createElement('audio')
    audio.setAttribute('data-mes-native-player', '')
    document.body.appendChild(audio)
    const pause = vi.spyOn(audio, 'pause').mockImplementation(() => {})

    try {
      renderWithProviders(
        <VideoViewer open onClose={vi.fn()} items={[items[0]]} />
      )
      expect(pause).toHaveBeenCalledTimes(1)
    } finally {
      audio.remove()
    }
  })

  it('keeps the frame mounted, paused, until the dialog finishes closing', () => {
    vi.useFakeTimers()
    try {
      const { rerender } = renderWithProviders(
        <VideoViewer open onClose={vi.fn()} items={[items[0]]} />
      )
      const video = screen.getByTestId('video-viewer').querySelector('video')
      if (!video) throw new Error('Expected video element')
      const pause = vi.spyOn(video, 'pause').mockImplementation(() => {})

      rerender(
        <VideoViewer open={false} onClose={vi.fn()} items={[items[0]]} />
      )

      // Still there, so the last frame doesn't blink out from under the
      // 150ms backdrop fade — but paused, so nothing plays under it.
      expect(
        screen.getByTestId('video-viewer').querySelector('video')
      ).not.toBeNull()
      expect(pause).toHaveBeenCalled()

      act(() => {
        vi.advanceTimersByTime(150)
      })

      // Gone once the dialog is: a `<video preload="metadata">` left in a
      // closed viewer fetches a header per bubble in the thread.
      expect(
        screen.getByTestId('video-viewer').querySelector('video')
      ).toBeNull()
    } finally {
      vi.useRealTimers()
    }
  })

  it('mounts no video before the viewer has ever opened', () => {
    renderWithProviders(
      <VideoViewer open={false} onClose={vi.fn()} items={[items[0]]} />
    )
    expect(screen.getByTestId('video-viewer').querySelector('video')).toBeNull()
  })
})
