import { describe, it, expect } from 'vitest'
import { isValidYouTubeUrl, extractYouTubeId, isValidYouTubeId, cn, formatDuration } from './utils'

describe('isValidYouTubeUrl', () => {
  it('accepts standard youtube.com watch URLs', () => {
    expect(isValidYouTubeUrl('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
    expect(isValidYouTubeUrl('http://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
    expect(isValidYouTubeUrl('https://youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
  })

  it('accepts youtu.be short URLs', () => {
    expect(isValidYouTubeUrl('https://youtu.be/dQw4w9WgXcQ')).toBe(true)
    expect(isValidYouTubeUrl('http://youtu.be/dQw4w9WgXcQ')).toBe(true)
  })

  it('accepts URLs without protocol', () => {
    expect(isValidYouTubeUrl('www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
    expect(isValidYouTubeUrl('youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
  })

  it('rejects non-YouTube URLs', () => {
    expect(isValidYouTubeUrl('https://vimeo.com/123456')).toBe(false)
    expect(isValidYouTubeUrl('https://google.com')).toBe(false)
    expect(isValidYouTubeUrl('not a url')).toBe(false)
    expect(isValidYouTubeUrl('')).toBe(false)
  })

  it('rejects YouTube domain without path', () => {
    expect(isValidYouTubeUrl('https://youtube.com')).toBe(false)
    expect(isValidYouTubeUrl('https://youtube.com/')).toBe(false)
  })
})

describe('extractYouTubeId', () => {
  it('extracts ID from standard watch URLs', () => {
    expect(extractYouTubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
    expect(extractYouTubeId('https://youtube.com/watch?v=abc123XYZ_-')).toBe('abc123XYZ_-')
  })

  it('extracts ID from youtu.be short URLs', () => {
    expect(extractYouTubeId('https://youtu.be/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
  })

  it('extracts ID from embed URLs', () => {
    expect(extractYouTubeId('https://www.youtube.com/embed/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
  })

  it('extracts ID from /v/ URLs', () => {
    expect(extractYouTubeId('https://www.youtube.com/v/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
  })

  it('handles URLs with extra parameters', () => {
    expect(extractYouTubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=120')).toBe('dQw4w9WgXcQ')
    expect(extractYouTubeId('https://youtu.be/dQw4w9WgXcQ?t=120')).toBe('dQw4w9WgXcQ')
  })

  it('returns null for invalid URLs', () => {
    expect(extractYouTubeId('https://vimeo.com/123456')).toBe(null)
    expect(extractYouTubeId('not a url')).toBe(null)
    expect(extractYouTubeId('')).toBe(null)
  })
})

describe('isValidYouTubeId', () => {
  it('accepts valid 11-character IDs', () => {
    expect(isValidYouTubeId('dQw4w9WgXcQ')).toBe(true)
    expect(isValidYouTubeId('abc123XYZ_-')).toBe(true)
    expect(isValidYouTubeId('AAAAAAAAAAA')).toBe(true)
    expect(isValidYouTubeId('00000000000')).toBe(true)
  })

  it('rejects IDs with wrong length', () => {
    expect(isValidYouTubeId('dQw4w9WgXc')).toBe(false)
    expect(isValidYouTubeId('dQw4w9WgXcQQ')).toBe(false)
    expect(isValidYouTubeId('')).toBe(false)
  })

  it('rejects IDs with invalid characters', () => {
    expect(isValidYouTubeId('dQw4w9WgXc!')).toBe(false)
    expect(isValidYouTubeId('dQw4w9WgXc@')).toBe(false)
    expect(isValidYouTubeId('dQw4w9 gXcQ')).toBe(false)
  })
})

describe('cn', () => {
  it('merges class names', () => {
    expect(cn('foo', 'bar')).toBe('foo bar')
  })

  it('handles conditional classes', () => {
    expect(cn('foo', false && 'bar', 'baz')).toBe('foo baz')
    expect(cn('foo', true && 'bar', 'baz')).toBe('foo bar baz')
  })

  it('deduplicates tailwind classes', () => {
    expect(cn('p-4', 'p-2')).toBe('p-2')
    expect(cn('text-red-500', 'text-blue-500')).toBe('text-blue-500')
  })
})

describe('formatDuration', () => {
  it('formats seconds into mm:ss', () => {
    expect(formatDuration(0)).toBe('0:00')
    expect(formatDuration(5)).toBe('0:05')
    expect(formatDuration(59)).toBe('0:59')
    expect(formatDuration(60)).toBe('1:00')
    expect(formatDuration(61)).toBe('1:01')
    expect(formatDuration(125)).toBe('2:05')
  })

  it('handles longer durations', () => {
    expect(formatDuration(600)).toBe('10:00')
    expect(formatDuration(3600)).toBe('60:00')
    expect(formatDuration(3661)).toBe('61:01')
  })

  it('handles decimal seconds by flooring', () => {
    expect(formatDuration(5.7)).toBe('0:05')
    expect(formatDuration(59.9)).toBe('0:59')
    expect(formatDuration(60.1)).toBe('1:00')
  })
})
