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

import WikiNewPage from '@/pages/wiki/WikiNewPage'
import { buildUser, buildWikiPage } from '@/test/factories'
import { renderWithProviders } from '@/test/render'

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

const toastApi = vi.hoisted (() => ({
  toast: vi.fn (),
}))

vi.mock ('@/lib/api', () => api)
vi.mock ('@/components/ui/use-toast', () => toastApi)
vi.mock ('react-markdown-editor-lite', () => ({
  default: ({ value, onChange }: {
    value:    string
    onChange: (event: { text: string }) => void
  }) => (
      <textarea
          aria-label="本文エディタ"
          value={value}
          onChange={ev => onChange ({ text: ev.target.value })}/>
  ),
}))

describe ('WikiNewPage', () => {
  it ('blocks guests', () => {
    renderWithProviders (<WikiNewPage user={buildUser ({ role: 'guest' })}/>)

    expect (screen.getByText ('403')).toBeInTheDocument ()
  })

  it ('creates a wiki page from title query and body', async () => {
    api.apiPost.mockResolvedValueOnce (buildWikiPage ({ title: '作成済み' }))

    renderWithProviders (
        <WikiNewPage user={buildUser ({ role: 'member' })}/>,
        { route: '/wiki/new?title=%E4%B8%8B%E6%9B%B8%E3%81%8D' },
    )

    expect (screen.getAllByRole ('textbox')[0]).toHaveValue ('下書き')
    fireEvent.change (screen.getByLabelText ('本文エディタ'), { target: { value: '本文' } })
    fireEvent.click (screen.getByRole ('button', { name: '追加' }))

    await waitFor (() => {
      expect (api.apiPost).toHaveBeenCalledWith (
          '/wiki',
          expect.any (FormData),
          { headers: { 'Content-Type': 'multipart/form-data' } },
      )
    })
    const formData = api.apiPost.mock.calls[0]?.[1] as FormData
    expect (formData.get ('title')).toBe ('下書き')
    expect (formData.get ('body')).toBe ('本文')
    expect (toastApi.toast).toHaveBeenCalledWith ({ title: '投稿成功!' })
  })
})
