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

import TagInput from '@/components/common/TagInput'
import { buildTag } from '@/test/factories'

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

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

describe ('TagInput', () => {
  beforeEach (() => {
    vi.clearAllMocks ()
  })

  it ('updates value and fetches autocomplete for the last token', async () => {
    const setValue = vi.fn ()
    api.apiGet.mockResolvedValueOnce ([buildTag ({ name: '虹夏', postCount: 2 })])

    render (<TagInput value="ぼっち 虹" setValue={setValue}/>)

    fireEvent.change (screen.getByRole ('textbox'), { target: { value: 'ぼっち 虹夏' } })

    await waitFor (() => {
      expect (api.apiGet).toHaveBeenCalledWith (
          '/tags/autocomplete',
          { params: { q: '虹夏', nico: '0' } },
      )
    })
    expect (setValue).toHaveBeenCalledWith ('ぼっち 虹夏')
  })

  it ('does not fetch when the last token is blank', () => {
    const setValue = vi.fn ()
    render (<TagInput value="" setValue={setValue}/>)

    fireEvent.change (screen.getByRole ('textbox'), { target: { value: ' ' } })

    expect (api.apiGet).not.toHaveBeenCalled ()
    expect (setValue).toHaveBeenCalledWith (' ')
  })

  it ('sends nico=1 only when includeNico is true', async () => {
    const setValue = vi.fn ()
    api.apiGet.mockResolvedValueOnce ([buildTag ({ name: '虹夏', postCount: 2 })])

    render (<TagInput value="" setValue={setValue} includeNico={true}/>)

    fireEvent.change (screen.getByRole ('textbox'), { target: { value: '虹夏' } })

    await waitFor (() => {
      expect (api.apiGet).toHaveBeenCalledWith (
          '/tags/autocomplete',
          { params: { q: '虹夏', nico: '1' } },
      )
    })
  })
})
