import {describe, expect, it, vi, beforeAll} from 'vitest'

import {render, screen, waitFor} from '../../test-utils'

import {Image} from './image'

// Mock URL.revokeObjectURL for jsdom
beforeAll(() => {
  URL.revokeObjectURL = vi.fn()
})

// Mock the util functions
vi.mock('../../utils', () => ({
  getThumbhashBlobURL: vi.fn((thumbhash?: string) =>
    thumbhash ? `blob:http://localhost/${thumbhash}` : undefined
  ),
  getResizedImageUrl: vi.fn((url?: string) => url),
}))

describe('Image', () => {
  it('renders with src and alt', () => {
    render(<Image src="https://example.com/image.jpg" alt="Test image" />)

    const img = screen.getByRole('img', {name: /test image/i})
    expect(img).toBeInTheDocument()
    expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
  })

  it('renders placeholder when no src provided', () => {
    const {container} = render(<Image alt="No image" />)

    // When no src is provided, Image component still renders an img element but without src
    const img = container.querySelector('img')
    expect(img).toBeInTheDocument()
    expect(img).not.toHaveAttribute('src')
  })

  it('handles onLoad callback', async () => {
    const handleLoad = vi.fn()
    render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        onLoad={handleLoad}
      />
    )

    const img = screen.getByRole('img')

    // Simulate image loading
    img.dispatchEvent(new Event('load'))

    await waitFor(() => {
      expect(handleLoad).toHaveBeenCalled()
    })
  })

  it('applies custom className', () => {
    const {container} = render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        className="custom-class"
      />
    )

    const wrapper = container.firstChild as HTMLElement
    expect(wrapper).toHaveClass('custom-class')
  })

  it('applies aspect ratio style', () => {
    const {container} = render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        aspectRatio="16/9"
      />
    )

    const wrapper = container.firstChild as HTMLElement
    expect(wrapper.style.aspectRatio).toBe('16/9')
  })

  it('uses thumbhash as placeholder when provided with fixed aspect ratio', () => {
    const {container} = render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        thumbhash="testThumbhash"
        aspectRatio="1"
      />
    )

    // Thumbhash is now rendered as a separate img element (placeholder)
    const images = container.querySelectorAll('img')
    expect(images).toHaveLength(2) // placeholder + main image
    const placeholderImg = images[0]
    expect(placeholderImg).toHaveAttribute(
      'src',
      'blob:http://localhost/testThumbhash'
    )
    expect(placeholderImg).toHaveAttribute('aria-hidden', 'true')
  })

  it('renders with natural sizing when aspectRatio is auto', () => {
    const {container} = render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        aspectRatio="auto"
        className="custom-class"
      />
    )

    const wrapper = container.firstChild as HTMLElement
    const img = screen.getByRole('img')

    expect(wrapper.tagName).toBe('DIV')
    expect(wrapper).toHaveClass('custom-class')
    expect(wrapper.style.aspectRatio).toBe('')
    expect(img).toHaveClass('w-full', 'h-auto')
    expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
  })

  it('preserves thumbhash with natural sizing', () => {
    const {container} = render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        aspectRatio="auto"
        thumbhash="testThumbhash"
      />
    )

    // Thumbhash is now rendered as a separate img element (placeholder)
    const images = container.querySelectorAll('img')
    expect(images).toHaveLength(2) // placeholder + main image
    const placeholderImg = images[0]
    expect(placeholderImg).toHaveAttribute(
      'src',
      'blob:http://localhost/testThumbhash'
    )

    const mainImg = images[1]
    expect(mainImg).toHaveClass('w-full', 'h-auto')
  })

  it('passes additional props to img element', () => {
    render(
      <Image
        src="https://example.com/image.jpg"
        alt="Test image"
        loading="lazy"
        data-testid="custom-image"
      />
    )

    const img = screen.getByRole('img')
    expect(img).toHaveAttribute('loading', 'lazy')
    expect(img).toHaveAttribute('data-testid', 'custom-image')
  })
})
