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

describe('UploadDropzone', () => {
  it('renders default state correctly', () => {
    const onFileSelect = vi.fn()
    render(<UploadDropzone onFileSelect={onFileSelect} />)

    expect(screen.getByText('Drag and drop a video file here, or click to select')).toBeInTheDocument()
    expect(screen.getByText('Supports MP4, MOV, AVI, MKV up to 1024MB')).toBeInTheDocument()
  })

  it('shows custom max size in text', () => {
    const onFileSelect = vi.fn()
    const maxSize = 500 * 1024 * 1024 // 500MB
    
    render(
      <UploadDropzone 
        onFileSelect={onFileSelect} 
        maxSize={maxSize}
      />
    )

    expect(screen.getByText('Supports MP4, MOV, AVI, MKV up to 500MB')).toBeInTheDocument()
  })

  it('calls onFileSelect when valid file is uploaded', async () => {
    const user = userEvent.setup()
    const onFileSelect = vi.fn()
    const mockFile = createMockFile('test-video.mp4', 'video/mp4')
    
    render(<UploadDropzone onFileSelect={onFileSelect} />)

    const input = screen.getByRole('presentation').querySelector('input[type="file"]') as HTMLInputElement
    await user.upload(input, mockFile)

    await waitFor(() => {
      expect(onFileSelect).toHaveBeenCalledWith(mockFile)
    })
  })

  it('shows error for file too large', async () => {
    const user = userEvent.setup()
    const onFileSelect = vi.fn()
    const maxSize = 100 * 1024 * 1024 // 100MB
    const largeFile = createMockFile('large-video.mp4', 'video/mp4', 200 * 1024 * 1024) // 200MB
    
    render(
      <UploadDropzone 
        onFileSelect={onFileSelect} 
        maxSize={maxSize}
      />
    )

    const input = screen.getByRole('presentation').querySelector('input[type="file"]') as HTMLInputElement
    await user.upload(input, largeFile)

    await waitFor(() => {
      expect(screen.getByText('File is too large. Maximum size is 100MB')).toBeInTheDocument()
    })
    expect(onFileSelect).not.toHaveBeenCalled()
  })

  it('shows error for invalid file type', async () => {
    const user = userEvent.setup()
    const onFileSelect = vi.fn()
    const invalidFile = createMockFile('document.pdf', 'application/pdf')
    
    render(<UploadDropzone onFileSelect={onFileSelect} />)

    const input = screen.getByRole('presentation').querySelector('input[type="file"]') as HTMLInputElement
    await user.upload(input, invalidFile)

    await waitFor(() => {
      expect(screen.getByText('Invalid file type. Please upload a video file.')).toBeInTheDocument()
    })
    expect(onFileSelect).not.toHaveBeenCalled()
  })

  it('applies disabled styling when disabled', () => {
    const onFileSelect = vi.fn()
    render(
      <UploadDropzone 
        onFileSelect={onFileSelect} 
        disabled={true}
      />
    )

    const dropzone = screen.getByText('Drag and drop a video file here, or click to select').closest('[role="presentation"]')!
    expect(dropzone).toHaveClass('opacity-50', 'cursor-not-allowed')
  })

  it('clears error state when new file is uploaded', async () => {
    const user = userEvent.setup()
    const onFileSelect = vi.fn()
    const invalidFile = createMockFile('document.pdf', 'application/pdf')
    const validFile = createMockFile('video.mp4', 'video/mp4')
    
    render(<UploadDropzone onFileSelect={onFileSelect} />)
    const input = screen.getByRole('presentation').querySelector('input[type="file"]') as HTMLInputElement

    // Upload invalid file first
    await user.upload(input, invalidFile)
    await waitFor(() => {
      expect(screen.getByText('Invalid file type. Please upload a video file.')).toBeInTheDocument()
    })

    // Upload valid file
    await user.upload(input, validFile)
    
    await waitFor(() => {
      expect(screen.queryByText('Invalid file type. Please upload a video file.')).not.toBeInTheDocument()
      expect(onFileSelect).toHaveBeenCalledWith(validFile)
    })
  })

  it('handles custom accept types', () => {
    const onFileSelect = vi.fn()
    const customAccept = { 'video/mp4': ['.mp4'] }
    
    render(
      <UploadDropzone 
        onFileSelect={onFileSelect}
        accept={customAccept}
      />
    )

    // The component should render normally with custom accept types
    expect(screen.getByText('Drag and drop a video file here, or click to select')).toBeInTheDocument()
  })

  it('updates styling during drag events', () => {
    const onFileSelect = vi.fn()
    render(<UploadDropzone onFileSelect={onFileSelect} />)

    // Note: Testing drag events with React Testing Library is limited
    // In a real scenario, you might need to mock the useDropzone hook
    // or test at the integration level with tools like Cypress/Playwright
    const dropzone = screen.getByText('Drag and drop a video file here, or click to select').closest('[role="presentation"]')!
    expect(dropzone.className).toContain('border')
  })
})