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

import PostImportSourcePage from '@/pages/posts/PostImportSourcePage'
import { buildUser } from '@/test/factories'
import { renderWithProviders } from '@/test/render'

const router = vi.hoisted (() => ({ navigate: vi.fn () }))

vi.mock ('react-router-dom', async importOriginal => ({
  ...await importOriginal<typeof import('react-router-dom')> (),
  useNavigate: () => router.navigate }))

describe ('PostImportSourcePage', () => {
  beforeEach (() => {
    sessionStorage.clear ()
    vi.clearAllMocks ()
  })

  it ('validates an empty source only after Next is pressed', () => {
    renderWithProviders (<PostImportSourcePage user={buildUser ()}/>)

    expect (screen.queryByText ('URL を入力してください．')).not.toBeInTheDocument ()

    fireEvent.click (screen.getByRole ('button', { name: '次へ' }))

    expect (screen.getByText ('URL を入力してください．')).toBeInTheDocument ()
    expect (router.navigate).not.toHaveBeenCalled ()
  })

  it ('reports frontend URL issues with original line numbers', () => {
    renderWithProviders (<PostImportSourcePage user={buildUser ()}/>)
    const input = screen.getByRole ('textbox', { name: '' })

    fireEvent.change (input, {
      target: { value: '\nftp://example.com/file\nhttps://example.com/valid' } })
    fireEvent.click (screen.getByRole ('button', { name: '次へ' }))

    expect (screen.getByText (/2 行目: HTTP または HTTPS/)).toBeInTheDocument ()
    expect (screen.getByText ('ftp://example.com/file')).toBeInTheDocument ()
    expect (input).toHaveAttribute ('aria-invalid', 'true')
    expect (router.navigate).not.toHaveBeenCalled ()
  })

  it ('navigates with individually encoded URLs without calling an API', () => {
    renderWithProviders (<PostImportSourcePage user={buildUser ()}/>)

    fireEvent.change (screen.getByRole ('textbox', { name: '' }), {
      target: {
	value: 'https://example.com/one+a\nhttps://example.com/two?value=b+c' } })
    fireEvent.click (screen.getByRole ('button', { name: '次へ' }))

    expect (router.navigate).toHaveBeenCalledWith (
	'/posts/new?urls=https%3A%2F%2Fexample.com%2Fone%2Ba'
	+ '+https%3A%2F%2Fexample.com%2Ftwo%3Fvalue%3Db%2Bc')
  })

  it ('disables Next when the encoded request target reaches 4096 bytes', () => {
    renderWithProviders (<PostImportSourcePage user={buildUser ()}/>)
    const input = screen.getByRole ('textbox', { name: '' })

    fireEvent.change (input, {
      target: { value: `https://example.com/${ 'a'.repeat (6_200) }` } })

    expect (screen.getByRole ('button', { name: '次へ' })).toBeDisabled ()
  })
})
