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

import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeField'

describe ('PostOriginalCreatedTimeField', () => {
  it ('updates from and before values', () => {
    const setFrom = vi.fn ()
    const setBefore = vi.fn ()

    render (
        <PostOriginalCreatedTimeField
            originalCreatedFrom={null}
            setOriginalCreatedFrom={setFrom}
            originalCreatedBefore={null}
            setOriginalCreatedBefore={setBefore}/>,
    )

    const inputs = screen.getAllByDisplayValue ('')
    fireEvent.change (inputs[0], { target: { value: '2026-01-02T03:04' } })
    fireEvent.change (inputs[1], { target: { value: '2026-01-03T03:04' } })

    expect (setFrom).toHaveBeenCalledWith (expect.stringMatching (
	/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z$/))
    expect (setBefore).toHaveBeenCalledWith (expect.stringMatching (
	/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z$/))
  })

  it ('infers an exclusive before value on blur', () => {
    const setBefore = vi.fn ()

    render (
        <PostOriginalCreatedTimeField
            originalCreatedFrom={null}
            setOriginalCreatedFrom={vi.fn ()}
            originalCreatedBefore={null}
            setOriginalCreatedBefore={setBefore}/>,
    )

    const input = screen.getAllByDisplayValue ('')[0]
    fireEvent.blur (input, { target: { value: '2026-01-02T03:04' } })

    const value = setBefore.mock.calls.at (-1)?.[0]
    expect (value).toMatch (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z$/)
    expect (new Date (value).getTime () - new Date ('2026-01-02T03:04').getTime ())
	.toBe (60_000)
  })

  it ('does not rewrite mounted values that only differ by offset notation', () => {
    const setFrom = vi.fn ()
    const setBefore = vi.fn ()

    render (
        <PostOriginalCreatedTimeField
            originalCreatedFrom="2024-01-01T12:34+09:00"
            setOriginalCreatedFrom={setFrom}
            originalCreatedBefore="2024-01-01T12:35+09:00"
            setOriginalCreatedBefore={setBefore}/>,
    )

    expect (setFrom).not.toHaveBeenCalled ()
    expect (setBefore).not.toHaveBeenCalled ()
  })

  it ('emits minute-precision UTC values only when the user edits the input', () => {
    const setFrom = vi.fn ()

    render (
        <PostOriginalCreatedTimeField
            originalCreatedFrom="2024-01-01T12:34+09:00"
            setOriginalCreatedFrom={setFrom}
            originalCreatedBefore={null}
            setOriginalCreatedBefore={vi.fn ()}/>,
    )

    const input = screen.getByDisplayValue ('2024-01-01T12:34')
    fireEvent.change (input, { target: { value: '2024-01-01T12:35' } })

    expect (setFrom).toHaveBeenCalledWith ('2024-01-01T03:35Z')
  })

  it ('resets both values', () => {
    const setFrom = vi.fn ()
    const setBefore = vi.fn ()

    render (
        <PostOriginalCreatedTimeField
            originalCreatedFrom="2026-01-01T00:00:00Z"
            setOriginalCreatedFrom={setFrom}
            originalCreatedBefore="2026-01-02T00:00:00Z"
            setOriginalCreatedBefore={setBefore}/>,
    )

    const buttons = screen.getAllByRole ('button', { name: 'リセット' })
    fireEvent.click (buttons[0])
    fireEvent.click (buttons[1])

    expect (setFrom).toHaveBeenCalledWith (null)
    expect (setBefore).toHaveBeenCalledWith (null)
  })
})
