import { Formik } from 'formik'
import React from 'react'
import { render, fireEvent, waitFor, screen } from '../../tests/with-app-context.js'
import { PatternInput } from './pattern-input.js'

describe('Base Components: PatternInput', () => {
  const cases: [{ value: string; pattern: string }, string][] = [
    [{ value: '12', pattern: '999-99' }, '12'],
    [{ value: '123456789', pattern: '999-99' }, '123-45'],
    [{ value: '1 2 + 3 456 789', pattern: '999-99' }, '123-45'],
    [{ value: '34234324', pattern: '' }, ''],
  ]

  it.each(cases)("<PatternInput {...%s} /> should have the value '%s'", async (props, expected) => {
    const testId = 'pattern-input-test-id'
    const valueTestId = 'value-test-id'
    const { value, ...rest } = props

    render(
      <Formik
        initialValues={{
          test: value,
        }}
        onSubmit={() => {}}
      >
        {({ values }) => (
          <>
            <PatternInput name="test" data-testid={testId} {...rest} />
            <div data-testid={valueTestId}>{values.test}</div>
          </>
        )}
      </Formik>
    )

    const input = screen.getByTestId(testId) as HTMLInputElement
    const valueEl = screen.getByTestId(valueTestId) as HTMLDivElement

    await waitFor(() => {
      expect(valueEl.textContent).toBe(expected)
      expect(input.value).toBe(expected)
    })
  })

  it('does not allow extra characters past end of pattern', async () => {
    const testId = 'pattern-input-test-id'
    const valueTestId = 'value-test-id'

    render(
      <Formik
        initialValues={{
          test: '',
        }}
        onSubmit={() => {}}
      >
        {({ values }) => (
          <>
            <PatternInput name="test" pattern="999-99" data-testid={testId} />
            <div data-testid={valueTestId}>{values.test}</div>
          </>
        )}
      </Formik>
    )

    const input = screen.getByTestId(testId) as HTMLInputElement
    const valueEl = screen.getByTestId(valueTestId) as HTMLDivElement

    await waitFor(() => {
      expect(valueEl.textContent).toBe('')
      expect(input.value).toBe('')
    })

    fireEvent.change(input, { target: { value: '12345' } })
    fireEvent.blur(input)

    await waitFor(() => {
      expect(valueEl.textContent).toBe('123-45')
      expect(input.value).toBe('123-45')
    })

    fireEvent.change(input, { target: { value: '123456' } })
    fireEvent.blur(input)

    await waitFor(() => {
      expect(valueEl.textContent).toBe('123-45')
      expect(input.value).toBe('123-45')
    })
  })
})
