import { describe, it, expect, vi } from 'vitest'
import { render, screen, userEvent } from '../../../test/utils'
import { VttEditor } from '../VttEditor'

const mockVttContent = `WEBVTT

00:00:01.000 --> 00:00:03.000
First caption

00:00:04.500 --> 00:00:06.000
Second caption`

const invalidVttContent = `WEBVTT

00:00:03.000 --> 00:00:01.000
Invalid timing`

const overlappingVttContent = `WEBVTT

00:00:01.000 --> 00:00:05.000
First caption

00:00:03.000 --> 00:00:06.000
Overlapping caption`

describe('VttEditor', () => {
  it('renders VTT content correctly', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    expect(screen.getByText('Test Editor')).toBeInTheDocument()
    expect(screen.getByText('First caption')).toBeInTheDocument()
    expect(screen.getByText('Second caption')).toBeInTheDocument()
    expect(screen.getByText((content) =>
      content.includes('2 cues') || false
    )).toBeInTheDocument()
  })

  it('displays timing inputs with correct values', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Check for timestamp inputs (they contain the formatted time)
    expect(screen.getByDisplayValue('00:00:01.000')).toBeInTheDocument()
    expect(screen.getByDisplayValue('00:00:03.000')).toBeInTheDocument()
    expect(screen.getByDisplayValue('00:00:04.500')).toBeInTheDocument()
    expect(screen.getByDisplayValue('00:00:06.000')).toBeInTheDocument()
    // Duration display
    expect(screen.getByText('(2000ms)')).toBeInTheDocument()
    expect(screen.getByText('(1500ms)')).toBeInTheDocument()
  })

  it('shows validation errors for invalid VTT', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={invalidVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    expect(screen.getByText('Validation Errors:')).toBeInTheDocument()
    // Both the header error list and inline warning show the error
    expect(screen.getAllByText(/Start time must be before end time/).length).toBeGreaterThanOrEqual(1)
  })

  it('shows per-cue validation warnings for overlapping cues', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={overlappingVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Should show inline warnings for overlapping cues
    expect(screen.getAllByText(/Overlaps with/).length).toBeGreaterThanOrEqual(1)
    // Should show warning count in header
    expect(screen.getByText(/validation warning/)).toBeInTheDocument()
  })

  it('displays empty state when no cues', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent="WEBVTT"
        onChange={onChange}
        title="Empty Editor"
      />
    )

    expect(screen.getByText('No cues found in VTT content')).toBeInTheDocument()
  })

  it('enters edit mode when edit button is clicked', async () => {
    const user = userEvent.setup()
    const onChange = vi.fn()

    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    const cueDiv = screen.getByText('First caption').closest('.group')!
    await user.hover(cueDiv)

    const editButton = screen.getAllByText('Edit text')[0]
    await user.click(editButton)

    expect(screen.getByDisplayValue('First caption')).toBeInTheDocument()
    expect(screen.getByText('Save (Ctrl+Enter)')).toBeInTheDocument()
    expect(screen.getByText('Cancel (Esc)')).toBeInTheDocument()
  })

  it('saves edited text correctly', async () => {
    const user = userEvent.setup()
    const onChange = vi.fn()

    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Enter edit mode
    const cueDiv = screen.getByText('First caption').closest('.group')!
    await user.hover(cueDiv)
    await user.click(screen.getAllByText('Edit text')[0])

    // Edit the text
    const textarea = screen.getByDisplayValue('First caption')
    await user.clear(textarea)
    await user.type(textarea, 'Edited caption')

    // Save changes
    await user.click(screen.getByText('Save (Ctrl+Enter)'))

    expect(onChange).toHaveBeenCalledWith(
      expect.stringContaining('Edited caption')
    )
    expect(screen.getByText('Edited caption')).toBeInTheDocument()
  })

  it('cancels editing without saving', async () => {
    const user = userEvent.setup()
    const onChange = vi.fn()

    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Enter edit mode
    const cueDiv = screen.getByText('First caption').closest('.group')!
    await user.hover(cueDiv)
    await user.click(screen.getAllByText('Edit text')[0])

    // Edit the text
    const textarea = screen.getByDisplayValue('First caption')
    await user.clear(textarea)
    await user.type(textarea, 'Edited caption')

    // Cancel changes
    await user.click(screen.getByText('Cancel (Esc)'))

    expect(onChange).not.toHaveBeenCalled()
    expect(screen.getByText('First caption')).toBeInTheDocument()
    expect(screen.queryByText('Edited caption')).not.toBeInTheDocument()
  })

  it('supports keyboard shortcuts in edit mode', async () => {
    const user = userEvent.setup()
    const onChange = vi.fn()

    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Enter edit mode
    const cueDiv = screen.getByText('First caption').closest('.group')!
    await user.hover(cueDiv)
    await user.click(screen.getAllByText('Edit text')[0])

    const textarea = screen.getByDisplayValue('First caption')
    await user.clear(textarea)
    await user.type(textarea, 'Keyboard edited')

    // Test Ctrl+Enter to save
    await user.keyboard('{Control>}{Enter}{/Control}')

    expect(onChange).toHaveBeenCalledWith(
      expect.stringContaining('Keyboard edited')
    )
  })

  it('cancels editing with Escape key', async () => {
    const user = userEvent.setup()
    const onChange = vi.fn()

    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Enter edit mode
    const cueDiv = screen.getByText('First caption').closest('.group')!
    await user.hover(cueDiv)
    await user.click(screen.getAllByText('Edit text')[0])

    const textarea = screen.getByDisplayValue('First caption')
    await user.type(textarea, ' edited')

    // Cancel with Escape
    await user.keyboard('{Escape}')

    expect(onChange).not.toHaveBeenCalled()
    expect(screen.getByText('First caption')).toBeInTheDocument()
  })

  it('hides edit controls in read-only mode', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Read Only Editor"
        readOnly={true}
      />
    )

    expect(screen.queryByText('Edit text')).not.toBeInTheDocument()
    // Timestamp inputs should be text in read-only mode
    expect(screen.getByText('0:01.000 → 0:03.000')).toBeInTheDocument()
    expect(screen.getByText('First caption')).toBeInTheDocument()
    expect(screen.getByText('Second caption')).toBeInTheDocument()
  })

  it('calculates total duration correctly', () => {
    const onChange = vi.fn()
    render(
      <VttEditor
        vttContent={mockVttContent}
        onChange={onChange}
        title="Test Editor"
      />
    )

    // Should show the end time of the last cue
    expect(screen.getByText(/Total duration: 0:06\.000/)).toBeInTheDocument()
  })

  it('handles malformed VTT gracefully', () => {
    const onChange = vi.fn()
    // This content has no valid cues but is not malformed enough to throw
    const emptyVtt = `WEBVTT

`

    render(
      <VttEditor
        vttContent={emptyVtt}
        onChange={onChange}
        title="Test Editor"
      />
    )

    expect(screen.getByText('No cues found in VTT content')).toBeInTheDocument()
  })

  // New tests for timestamp editing
  describe('Timestamp Editing', () => {
    it('allows editing start time', async () => {
      const user = userEvent.setup()
      const onChange = vi.fn()

      render(
        <VttEditor
          vttContent={mockVttContent}
          onChange={onChange}
          title="Test Editor"
        />
      )

      const startTimeInput = screen.getByDisplayValue('00:00:01.000')
      await user.clear(startTimeInput)
      await user.type(startTimeInput, '00:00:00.500')
      await user.tab() // blur to save

      expect(onChange).toHaveBeenCalledWith(
        expect.stringContaining('00:00:00.500')
      )
    })

    it('allows editing end time', async () => {
      const user = userEvent.setup()
      const onChange = vi.fn()

      render(
        <VttEditor
          vttContent={mockVttContent}
          onChange={onChange}
          title="Test Editor"
        />
      )

      const endTimeInput = screen.getByDisplayValue('00:00:03.000')
      await user.clear(endTimeInput)
      await user.type(endTimeInput, '00:00:02.500')
      await user.tab() // blur to save

      expect(onChange).toHaveBeenCalledWith(
        expect.stringContaining('00:00:02.500')
      )
    })

    it('reverts invalid timestamp on blur', async () => {
      const user = userEvent.setup()
      const onChange = vi.fn()

      render(
        <VttEditor
          vttContent={mockVttContent}
          onChange={onChange}
          title="Test Editor"
        />
      )

      const startTimeInput = screen.getByDisplayValue('00:00:01.000')
      await user.clear(startTimeInput)
      await user.type(startTimeInput, 'invalid')
      await user.tab() // blur

      // Should revert to original value
      expect(screen.getByDisplayValue('00:00:01.000')).toBeInTheDocument()
      expect(onChange).not.toHaveBeenCalled()
    })

    it('saves timestamp on Enter key', async () => {
      const user = userEvent.setup()
      const onChange = vi.fn()

      render(
        <VttEditor
          vttContent={mockVttContent}
          onChange={onChange}
          title="Test Editor"
        />
      )

      const startTimeInput = screen.getByDisplayValue('00:00:01.000')
      await user.clear(startTimeInput)
      await user.type(startTimeInput, '00:00:00.750{Enter}')

      expect(onChange).toHaveBeenCalledWith(
        expect.stringContaining('00:00:00.750')
      )
    })
  })

  // Tests for cue actions (insert/delete)
  // Note: Hover-dependent tests are limited in jsdom environment
  describe('Cue Actions', () => {
    it('action buttons not rendered in read-only mode', () => {
      const onChange = vi.fn()

      render(
        <VttEditor
          vttContent={mockVttContent}
          onChange={onChange}
          title="Test Editor"
          readOnly={true}
        />
      )

      expect(screen.queryByTitle('Insert cue before')).not.toBeInTheDocument()
      expect(screen.queryByTitle('Delete cue')).not.toBeInTheDocument()
    })
  })
})
