import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import React from 'react'
import MoonUIFileUploadPro from './index'

// Mock FileReader
const mockFileReader = {
  readAsDataURL: jest.fn(),
  result: 'data:image/png;base64,mock-base64-data',
  onload: null as any,
  onerror: null as any,
}

global.FileReader = jest.fn(() => mockFileReader) as any

// Mock file objects
const createMockFile = (name: string, size: number, type: string) => {
  const file = new File(['mock content'], name, { type })
  Object.defineProperty(file, 'size', { value: size })
  return file
}

describe('MoonUIFileUploadPro', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  it('renders without crashing', () => {
    render(<MoonUIFileUploadPro />)
    
    expect(screen.getByText('File Upload')).toBeInTheDocument()
    expect(screen.getByText('Drag and drop files here, or click to select')).toBeInTheDocument()
  })

  it('renders with custom title and description', () => {
    render(
      <MoonUIFileUploadPro
        accept="image/*"
        maxSize={5}
        multiple
      />
    )
    
    expect(screen.getByText('Upload up to 5 files (max 5MB each)')).toBeInTheDocument()
    expect(screen.getByText('Accepted types: image/*')).toBeInTheDocument()
  })

  it('handles file selection', async () => {
    const mockOnUpload = jest.fn()
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
    
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    const input = screen.getByRole('button', { hidden: true }) // Hidden file input
    
    fireEvent.change(input, { target: { files: [file] } })
    
    await waitFor(() => {
      expect(mockOnUpload).toHaveBeenCalledWith([file])
    })
  })

  it('validates file size', () => {
    const mockOnUpload = jest.fn()
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} maxSize={1} />)
    
    const file = createMockFile('large-file.jpg', 2 * 1024 * 1024, 'image/jpeg') // 2MB
    const input = screen.getByRole('button', { hidden: true })
    
    // Mock alert
    global.alert = jest.fn()
    
    fireEvent.change(input, { target: { files: [file] } })
    
    expect(global.alert).toHaveBeenCalledWith('large-file.jpg: File size must be less than 1MB')
    expect(mockOnUpload).not.toHaveBeenCalled()
  })

  it('validates file type', () => {
    const mockOnUpload = jest.fn()
    render(
      <MoonUIFileUploadPro
        onUpload={mockOnUpload}
        allowedMimeTypes={['image/jpeg', 'image/png']}
      />
    )
    
    const file = createMockFile('document.pdf', 1024, 'application/pdf')
    const input = screen.getByRole('button', { hidden: true })
    
    global.alert = jest.fn()
    
    fireEvent.change(input, { target: { files: [file] } })
    
    expect(global.alert).toHaveBeenCalledWith('document.pdf: File type application/pdf is not allowed')
    expect(mockOnUpload).not.toHaveBeenCalled()
  })

  it('handles multiple files', async () => {
    const mockOnUpload = jest.fn()
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} multiple />)
    
    const files = [
      createMockFile('file1.jpg', 1024, 'image/jpeg'),
      createMockFile('file2.png', 2048, 'image/png'),
    ]
    const input = screen.getByRole('button', { hidden: true })
    
    fireEvent.change(input, { target: { files } })
    
    await waitFor(() => {
      expect(mockOnUpload).toHaveBeenCalledWith(files)
    })
  })

  it('respects maxFiles limit', () => {
    const mockOnUpload = jest.fn()
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} maxFiles={2} />)
    
    const files = [
      createMockFile('file1.jpg', 1024, 'image/jpeg'),
      createMockFile('file2.png', 1024, 'image/png'),
      createMockFile('file3.gif', 1024, 'image/gif'),
    ]
    const input = screen.getByRole('button', { hidden: true })
    
    global.alert = jest.fn()
    
    fireEvent.change(input, { target: { files } })
    
    expect(global.alert).toHaveBeenCalledWith('Maximum 2 files allowed')
    expect(mockOnUpload).not.toHaveBeenCalled()
  })

  it('handles drag and drop', () => {
    const mockOnUpload = jest.fn()
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
    
    const dropZone = screen.getByText('Drag and drop files here, or click to select').closest('div')
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    
    fireEvent.dragOver(dropZone!, {
      dataTransfer: { files: [file] },
    })
    
    expect(dropZone).toHaveClass('border-primary')
    
    fireEvent.drop(dropZone!, {
      dataTransfer: { files: [file] },
    })
    
    expect(dropZone).not.toHaveClass('border-primary')
  })

  it('handles file removal', async () => {
    const mockOnRemove = jest.fn()
    render(<MoonUIFileUploadPro onRemove={mockOnRemove} />)
    
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    const input = screen.getByRole('button', { hidden: true })
    
    fireEvent.change(input, { target: { files: [file] } })
    
    await waitFor(() => {
      expect(screen.getByText('test.jpg')).toBeInTheDocument()
    })
    
    const removeButton = screen.getByRole('button', { name: /remove/i })
    fireEvent.click(removeButton)
    
    expect(mockOnRemove).toHaveBeenCalledWith(file)
  })

  it('shows progress during upload', async () => {
    const mockOnUpload = jest.fn().mockResolvedValue(undefined)
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
    
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    const input = screen.getByRole('button', { hidden: true })
    
    fireEvent.change(input, { target: { files: [file] } })
    
    await waitFor(() => {
      expect(screen.getByText('Uploading files...')).toBeInTheDocument()
    })
  })

  it('handles upload success', async () => {
    const mockOnUpload = jest.fn().mockResolvedValue(undefined)
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
    
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    const input = screen.getByRole('button', { hidden: true })
    
    fireEvent.change(input, { target: { files: [file] } })
    
    await waitFor(() => {
      expect(screen.getByText('success')).toBeInTheDocument()
    })
  })

  it('handles upload error', async () => {
    const mockOnUpload = jest.fn().mockRejectedValue(new Error('Upload failed'))
    render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
    
    const file = createMockFile('test.jpg', 1024, 'image/jpeg')
    const input = screen.getByRole('button', { hidden: true })
    
    fireEvent.change(input, { target: { files: [file] } })
    
    await waitFor(() => {
      expect(screen.getByText('error')).toBeInTheDocument()
      expect(screen.getByText('Upload failed')).toBeInTheDocument()
    })
  })

  it('is disabled when disabled prop is true', () => {
    render(<MoonUIFileUploadPro disabled />)
    
    const dropZone = screen.getByText('Drag and drop files here, or click to select').closest('div')
    expect(dropZone).toHaveClass('cursor-not-allowed')
  })

  it('applies custom className', () => {
    render(<MoonUIFileUploadPro className="custom-upload" />)
    
    const container = screen.getByText('File Upload').closest('div')
    expect(container).toHaveClass('custom-upload')
  })

  it('formats file sizes correctly', () => {
    render(<MoonUIFileUploadPro />)
    
    // This would be tested through the file display after upload
    // The formatFileSize function should be tested separately
  })

  it('displays correct file icons', () => {
    render(<MoonUIFileUploadPro />)
    
    // This would be tested through the file display after upload
    // The getFileIcon function should be tested separately
  })
})