import { screen, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import MaterialListPage from '@/pages/materials/MaterialListPage'
import { buildMaterial, buildTag } from '@/test/factories'
import { renderWithProviders } from '@/test/render'

const api = vi.hoisted (() => ({
  apiGet: vi.fn (),
}))

vi.mock ('@/lib/api', () => api)

describe ('MaterialListPage', () => {
  it ('shows the empty selection guide without a tag query', () => {
    renderWithProviders (<MaterialListPage/>, { route: '/materials' })

    expect (screen.getByText ('左のリストから照会したいタグを選択してください。')).toBeInTheDocument ()
    expect (screen.getByRole ('link', { name: '素材を新規追加する' })).toHaveAttribute (
        'href',
        '/materials/new',
    )
  })

  it ('loads materials for a tag query', async () => {
    const tag = {
      ...buildTag ({
        id:       4,
        name:     '素材タグ',
        category: 'material',
      }),
      material: buildMaterial ({ id: 8, contentType: 'image/png', file: 'image.png' }),
      children: [],
    }
    api.apiGet.mockResolvedValueOnce (tag)

    renderWithProviders (<MaterialListPage/>, { route: '/materials?tag=%E7%B4%A0%E6%9D%90' })

    await waitFor (() => {
      expect (api.apiGet).toHaveBeenCalledWith (
          '/tags/name/%E7%B4%A0%E6%9D%90/materials',
      )
    })
    expect (await screen.findByRole ('link', { name: '素材タグ' })).toBeInTheDocument ()
    expect (screen.getByRole ('link', { name: '' })).toHaveAttribute ('href', '/materials/8')
  })

  it ('offers adding a missing non-meme material', async () => {
    api.apiGet.mockResolvedValueOnce ({
      ...buildTag ({ name: '未登録', category: 'material' }),
      material: null,
      children: [],
    })

    renderWithProviders (<MaterialListPage/>, { route: '/materials?tag=x' })

    expect (await screen.findByRole ('link', { name: '追加' })).toHaveAttribute (
        'href',
        '/materials/new?tag=%E6%9C%AA%E7%99%BB%E9%8C%B2',
    )
  })
})
