import { act, fireEvent, render } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { createRef } from 'react'

import NicoViewer from '@/components/NicoViewer'

import type { NiconicoViewerHandle } from '@/types'


describe ('NicoViewer', () => {
  afterEach (() => {
    vi.useRealTimers ()
  })

  it ('does not time out after metadata reports a playable duration', () => {
    vi.useFakeTimers ()

    const onError = vi.fn ()
    const onMetadataChange = vi.fn ()
    const { container } = render (
        <NicoViewer
            id="sm12345"
            width={640}
            height={360}
            onMetadataChange={onMetadataChange}
            onError={onError}/>,
    )
    const iframe = container.querySelector ('iframe')
    expect (iframe).not.toBeNull ()

    fireEvent.load (iframe!)
    act (() => {
      window.dispatchEvent (new MessageEvent ('message', {
        origin: 'https://embed.nicovideo.jp',
        source: iframe!.contentWindow,
        data:   {
          eventName: 'playerMetadataChange',
          data:      {
            currentTime:           7,
            duration:              120,
            isVideoMetaDataLoaded: true,
            maximumBuffered:       30,
            muted:                 false,
            showComment:           true,
            volume:                1,
          },
        },
      }))
    })

    act (() => {
      vi.advanceTimersByTime (8_000)
    })

    expect (onMetadataChange).toHaveBeenCalled ()
    expect (onError).not.toHaveBeenCalled ()
  })

  it ('seeks with milliseconds', () => {
    const ref = createRef<NiconicoViewerHandle> ()
    const { container } = render (
        <NicoViewer
            ref={ref}
            id="sm12345"
            width={640}
            height={360}/>,
    )
    const iframe = container.querySelector ('iframe')!
    const postMessage = vi.spyOn (iframe.contentWindow!, 'postMessage')

    act (() => {
      ref.current!.seek (7_000)
    })

    expect (postMessage).toHaveBeenCalledWith (
        expect.objectContaining ({
          eventName: 'seek',
          data:      { time: 7_000 },
        }),
        'https://embed.nicovideo.jp',
    )
  })
})
