import { beforeEach, describe, expect, it, vi } from 'vitest'
import { fireEvent, render, screen } from '@testing-library/react'
import type { AudioTrack, VideoQuality } from '../../types'
import { SettingsMenu } from './SettingsMenu'

const { contextState } = vi.hoisted(() => ({
  contextState: {
    value: null as any,
  },
}))

vi.mock('../../contexts/PlayerContext', () => ({
  usePlayerContext: () => contextState.value,
}))

const audioTracks: AudioTrack[] = [
  {
    name: 'English',
    language: 'en',
    url: '',
    groupId: 'audio',
  },
]

const qualities: VideoQuality[] = [
  { label: '1080p', height: 1080, levelIndex: 0 },
  { label: '720p', height: 720, levelIndex: 1 },
]

const subtitles = [{ src: '/sub.vtt', lang: 'en', label: 'English' }]

describe('SettingsMenu', () => {
  beforeEach(() => {
    contextState.value = {
      uiState: {
        controlsVisible: true,
        settingsOpen: true,
        volumeControlOpen: false,
        qualityMenuOpen: false,
        subtitleMenuOpen: false,
      },
      videoState: {
        playing: false,
        currentTime: 0,
        duration: 0,
        buffered: 0,
        volume: 1,
        muted: false,
        playbackRate: 1,
        fullscreen: false,
        pictureInPicture: false,
        loading: false,
        error: null,
        seeking: false,
        isLiveBroadcast: false,
      },
      settings: {
        quality: null,
        subtitle: null,
        subtitleStyle: {},
        audioTrack: null,
        playbackRate: 1,
      },
      setPlaybackRate: vi.fn(),
      setSubtitle: vi.fn(),
      setSubtitleStyle: vi.fn(),
      saveSubtitleStyle: vi.fn(),
      revertSubtitleStyle: vi.fn(),
      setAudioTrack: vi.fn(),
      setQuality: vi.fn(),
      toggleSettings: vi.fn(),
      subtitleStyleEditorEnabled: true,
      translations: {
        noSubtitlesAvailable: 'No subtitles available',
        subtitles: 'Subtitles',
        subtitleStyle: 'Subtitle Style',
        preview: 'Preview',
        save: 'Save',
        cancel: 'Cancel',
        reset: 'Reset',
        off: 'Off',
        auto: 'Auto',
        quality: 'Quality',
        speed: 'Speed',
        fontSize: 'Font Size',
        fontWeight: 'Font Weight',
        textColor: 'Text Color',
        backgroundColor: 'Background Color',
        backgroundOpacity: 'Background Opacity',
        normal: 'Normal',
        default: 'Default',
        audioTrack: 'Audio Track',
        settings: 'Settings',
        level: 'Level',
        play: 'Play',
        pause: 'Pause',
        mute: 'Mute',
        unmute: 'Unmute',
        enterFullscreen: 'Enter fullscreen',
        exitFullscreen: 'Exit fullscreen',
        enterPictureInPicture: 'Enter picture-in-picture',
        exitPictureInPicture: 'Exit picture-in-picture',
        videoProgress: 'Video progress',
        volume: 'Volume',
        live: 'LIVE',
      },
    }
  })

  it('does not render when settings are closed', () => {
    contextState.value.uiState.settingsOpen = false
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)
    expect(screen.queryByText('Settings')).not.toBeInTheDocument()
  })

  it('changes playback speed from speed submenu', () => {
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)

    fireEvent.click(screen.getByText('Speed'))
    fireEvent.click(screen.getByText('1.5x'))

    expect(contextState.value.setPlaybackRate).toHaveBeenCalledWith(1.5)
  })

  it('selects subtitle from submenu', () => {
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)

    fireEvent.click(screen.getByText('Subtitles'))
    fireEvent.click(screen.getByRole('button', { name: 'English' }))
    expect(contextState.value.setSubtitle).toHaveBeenCalledWith(subtitles[0])
  })

  it('selects audio track from submenu', () => {
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)

    fireEvent.click(screen.getByText('Audio Track'))
    fireEvent.click(screen.getByRole('button', { name: 'English' }))
    expect(contextState.value.setAudioTrack).toHaveBeenCalledWith(audioTracks[0])
  })

  it('selects quality from submenu', () => {
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)

    fireEvent.click(screen.getByText('Quality'))
    fireEvent.click(screen.getByText('720p'))
    expect(contextState.value.setQuality).toHaveBeenCalledWith(qualities[1])
  })

  it('saves subtitle style from subtitle style editor', () => {
    render(<SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />)

    fireEvent.click(screen.getByText('Subtitles'))
    fireEvent.click(screen.getByRole('button', { name: /Subtitle Style/i }))
    fireEvent.change(screen.getByLabelText('Font Size'), { target: { value: '30' } })
    fireEvent.click(screen.getByRole('button', { name: 'Save' }))

    expect(contextState.value.saveSubtitleStyle).toHaveBeenCalledWith(
      expect.objectContaining({
        fontSize: 30,
      })
    )
  })
})
