/// <reference types="@testing-library/jest-dom/vitest" />
import { describe, it, expect, vi } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { MediaLibrary } from './MediaLibrary.js'
import type { MediaClient, MediaItem } from './client.js'

const items: MediaItem[] = [{ key: 'media/a.png', url: 'https://cdn/a.png', size: 1, width: 4, height: 4 }]

function client(): MediaClient {
  return { upload: async () => items[0]!, list: async () => ({ items }), remove: vi.fn(async () => {}) }
}

describe('MediaLibrary', () => {
  it('renders an accessible region with each item as a labelled selectable control', async () => {
    const onSelect = vi.fn()
    render(<MediaLibrary client={client()} onSelect={onSelect} />)
    await waitFor(() => expect(screen.getByRole('region', { name: /media library/i })).toBeInTheDocument())
    const select = await screen.findByRole('button', { name: /select media\/a\.png/i })
    fireEvent.click(select)
    expect(onSelect).toHaveBeenCalledWith(items[0])
  })

  it('uses a container-query grid, never a fixed-width or viewport-breakpoint layout', () => {
    const { container } = render(<MediaLibrary client={client()} onSelect={() => {}} />)
    const html = container.innerHTML
    // CLAUDE.md consequence (4): no fixed px width, no viewport md:/lg: breakpoints in the headless surface.
    expect(html).toMatch(/container-type:\s*inline-size/)
    expect(html).toMatch(/12cqi/)
    expect(html).not.toMatch(/width:\s*\d+px/)
    expect(html).not.toMatch(/\b(sm|md|lg|xl):/)
  })

  it('renders an empty state when there are no items', async () => {
    const empty: MediaClient = { upload: async () => items[0]!, list: async () => ({ items: [] }), remove: async () => {} }
    render(<MediaLibrary client={empty} onSelect={() => {}} />)
    await waitFor(() => expect(screen.getByText(/no media yet/i)).toBeInTheDocument())
  })

  it('on initial-load failure shows the alert and NOT the "no media yet" empty state', async () => {
    const failing: MediaClient = {
      upload: async () => items[0]!,
      list: async () => {
        throw new Error('list failed')
      },
      remove: async () => {},
    }
    render(<MediaLibrary client={failing} onSelect={() => {}} />)
    const alert = await screen.findByRole('alert')
    expect(alert).toHaveTextContent('list failed')
    // The empty-state asserts a fact (nothing uploaded) the failed fetch does not know — must not show.
    expect(screen.queryByText(/no media yet/i)).not.toBeInTheDocument()
  })

  it('surfaces a remove failure in an alert and keeps the item in the list', async () => {
    const failing: MediaClient = {
      upload: async () => items[0]!,
      list: async () => ({ items }),
      remove: async () => {
        throw new Error('delete failed')
      },
    }
    render(<MediaLibrary client={failing} onSelect={() => {}} />)
    const deleteBtn = await screen.findByRole('button', { name: /delete media\/a\.png/i })
    fireEvent.click(deleteBtn)
    const alert = await screen.findByRole('alert')
    expect(alert).toHaveTextContent('delete failed')
    expect(screen.getByRole('button', { name: /select media\/a\.png/i })).toBeInTheDocument()
    expect(screen.getByRole('button', { name: /delete media\/a\.png/i })).toBeInTheDocument()
  })

  it('omits destructive controls and never removes in selection-only mode', async () => {
    const c = client()
    render(<MediaLibrary client={c} onSelect={() => {}} allowDelete={false} />)
    await screen.findByRole('button', { name: /select media\/a\.png/i })
    expect(screen.queryByRole('button', { name: /delete media\/a\.png/i })).not.toBeInTheDocument()
    expect(c.remove).not.toHaveBeenCalled()
  })

  it('restores focus to the upload input after delete (WCAG 2.4.3)', async () => {
    const c = client()
    render(<MediaLibrary client={c} onSelect={() => {}} />)
    const deleteBtn = await screen.findByRole('button', { name: /delete media\/a\.png/i })
    deleteBtn.focus()
    fireEvent.click(deleteBtn)
    await waitFor(() =>
      expect(screen.queryByRole('button', { name: /delete media\/a\.png/i })).not.toBeInTheDocument(),
    )
    expect(document.activeElement).toBe(screen.getByLabelText('Upload image'))
  })
})
