import { describe, it, expect, vi, beforeEach } from 'vitest'
import { POST } from './route'
import { NextRequest } from 'next/server'

vi.mock('@/lib/youtube', () => ({
  downloadVideo: vi.fn(),
}))

import { downloadVideo } from '@/lib/youtube'

const mockDownloadVideo = vi.mocked(downloadVideo)

function createRequest(body: object): NextRequest {
  return new NextRequest('http://localhost:3000/api/download', {
    method: 'POST',
    body: JSON.stringify(body),
    headers: { 'Content-Type': 'application/json' },
  })
}

describe('POST /api/download', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('returns 400 when url is missing', async () => {
    const request = createRequest({ format: 'mp4', formatType: 'video' })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(400)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Missing required fields')
  })

  it('returns 400 when format is missing', async () => {
    const request = createRequest({ url: 'https://youtube.com/watch?v=abc', formatType: 'video' })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(400)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Missing required fields')
  })

  it('returns 400 when formatType is missing', async () => {
    const request = createRequest({ url: 'https://youtube.com/watch?v=abc', format: 'mp4' })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(400)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Missing required fields')
  })

  it('returns 400 for invalid YouTube URL', async () => {
    const request = createRequest({
      url: 'https://vimeo.com/123',
      format: 'mp4',
      formatType: 'video',
    })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(400)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Invalid YouTube URL')
  })

  it('returns 500 when download fails', async () => {
    mockDownloadVideo.mockResolvedValue({
      success: false,
      error: 'Download failed',
    })

    const request = createRequest({
      url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
      format: 'mp4',
      formatType: 'video',
    })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(500)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Download failed')
  })

  it('returns download result on success', async () => {
    const mockResult = {
      success: true,
      downloadUrl: '/downloads/123.mp4',
      filename: 'video.mp4',
    }
    mockDownloadVideo.mockResolvedValue(mockResult)

    const request = createRequest({
      url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
      format: 'mp4',
      formatType: 'video',
    })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(200)
    expect(data.success).toBe(true)
    expect(data.downloadUrl).toBe('/downloads/123.mp4')
    expect(data.filename).toBe('video.mp4')
  })

  it('passes correct parameters to downloadVideo', async () => {
    mockDownloadVideo.mockResolvedValue({
      success: true,
      downloadUrl: '/downloads/123.mp3',
      filename: 'audio.mp3',
    })

    const request = createRequest({
      url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
      format: 'mp3',
      formatType: 'audio',
    })
    await POST(request)

    expect(mockDownloadVideo).toHaveBeenCalledWith({
      url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
      format: 'mp3',
      formatType: 'audio',
    })
  })

  it('handles exceptions gracefully', async () => {
    const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
    mockDownloadVideo.mockRejectedValue(new Error('Unexpected error'))

    const request = createRequest({
      url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
      format: 'mp4',
      formatType: 'video',
    })
    const response = await POST(request)
    const data = await response.json()

    expect(response.status).toBe(500)
    expect(data.success).toBe(false)
    expect(data.error).toBe('Unexpected error')
    consoleSpy.mockRestore()
  })
})
