import React from "react"
import { screen, render, act } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import AutosuggestInput from "."

describe("AutosuggestInput", () => {
  it("suggests values that have been previously entered", async () => {
    render(<AutosuggestInput aria-label="myInput" />)
    const input = screen.getByRole("textbox", { name: "myInput" })
    const suggestion = screen.getByTestId("suggestion")
    await act(() => userEvent.type(input, "Spaghetti"))
    await act(() => userEvent.tab())
    await act(() => userEvent.clear(input))
    expect(input).toHaveValue("")
    await act(() => userEvent.type(input, "Spag"))
    expect(suggestion).toHaveTextContent("Spaghetti")
  })

  it("shows no suggestion when input matches no stored suggestions", async () => {
    render(<AutosuggestInput aria-label="myInput" />)
    const input = screen.getByRole("textbox", { name: "myInput" })
    const suggestion = screen.getByTestId("suggestion")
    await act(() => userEvent.type(input, "Lasagna"))
    expect(suggestion).toHaveTextContent("")
  })

  it("uses case sensitive suggestions", async () => {
    render(<AutosuggestInput aria-label="myInput" />)
    const input = screen.getByRole("textbox", { name: "myInput" })
    const suggestion = screen.getByTestId("suggestion")
    await act(() => userEvent.type(input, "FETTUCCINE"))
    await act(() => userEvent.tab())
    await act(() => userEvent.clear(input))
    expect(input).toHaveValue("")
    await act(() => userEvent.type(input, "fett"))
    expect(suggestion).toHaveTextContent("")
  })

  it("uses right arrow key to complete input with matching suggestion", async () => {
    render(<AutosuggestInput aria-label="myInput" />)
    const input = screen.getByRole("textbox", { name: "myInput" })
    await act(() => userEvent.type(input, "Linguine"))
    await act(() => userEvent.tab())
    await act(() => userEvent.clear(input))
    expect(input).toHaveValue("")
    await act(() => userEvent.type(input, "Ling{arrowright}"))
    expect(input).toHaveValue("Linguine")
  })

  it("updates onChange callback when right arrow key changes input", async () => {
    const onChangeCallback = jest.fn()
    render(
      <AutosuggestInput aria-label="myInput" onChange={onChangeCallback} />
    )
    const input = screen.getByRole("textbox", { name: "myInput" })
    await act(() => userEvent.type(input, "Gnocchi")) // calls onchange 7x -> length of string
    await act(() => userEvent.tab())
    await act(() => userEvent.clear(input)) // calls onchange once -> 1 + 7  = 8
    await act(() => userEvent.type(input, "G{arrowright}")) // calls onchange 2x -> G and arrow right key -> 2 + 8 = 10
    expect(onChangeCallback).toHaveBeenCalledTimes(10)
  })

  it("does not fill empty suggestion to input", async () => {
    render(<AutosuggestInput aria-label="myInput" />)
    const input = screen.getByRole("textbox", { name: "myInput" })
    const suggestion = screen.getByTestId("suggestion")
    await act(() => userEvent.type(input, "Orzo{arrowright}"))
    expect(input).toHaveValue("Orzo")
    expect(suggestion).toHaveTextContent("")
  })
})
