import { render, screen } from '@testing-library/react'
import { useForm } from 'react-hook-form'
import userEvent from '@testing-library/user-event'
import { createRef } from 'react'
import { axe, toHaveNoViolations } from 'jest-axe'
import { PktButton } from './Button'
import '@testing-library/jest-dom'

expect.extend(toHaveNoViolations)

// Mock Form Component
const MockForm = ({ buttonPosition }: { buttonPosition: 'inside' | 'outside' }) => {
  const { register, handleSubmit, reset } = useForm()
  const onSubmit = jest.fn()

  return (
    <>
      <form id="test-form" onSubmit={handleSubmit(onSubmit)}>
        <input {...register('name')} placeholder="Name" />
        {buttonPosition === 'inside' && <PktButton type="submit">Submit</PktButton>}
        {buttonPosition === 'inside' && (
          <PktButton type="reset" onClick={() => reset()}>
            Reset
          </PktButton>
        )}
      </form>
      {buttonPosition === 'outside' && (
        <PktButton type="submit" form="test-form">
          Submit
        </PktButton>
      )}
      {buttonPosition === 'outside' && (
        <PktButton type="reset" form="test-form" onClick={() => reset()}>
          Reset
        </PktButton>
      )}
    </>
  )
}
// Ligger button utenfor form i React Hook Form må bruker sende inn reset  selv
// dette gjelder ikke native knapper som er assosiert med native form elementer, men de fleste brukerene våre
// bruker nok også våre input elementer også
//https://react-hook-form.com/api/useform/reset

describe('PktButton Form Behavior', () => {
  test('PktButton submits form when inside form element', async () => {
    render(<MockForm buttonPosition="inside" />)

    await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe')
    await userEvent.click(screen.getByText('Submit'))

    expect(screen.getByPlaceholderText('Name')).toHaveValue('Shawn Joe')
  })

  test('PktButton resets form when inside form element', async () => {
    render(<MockForm buttonPosition="inside" />)

    await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe')
    await userEvent.click(screen.getByText('Reset'))

    expect(screen.getByPlaceholderText('Name')).toHaveValue('')
  })

  test('PktButton submits form when outside but linked via form attribute', async () => {
    render(<MockForm buttonPosition="outside" />)

    await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe')
    await userEvent.click(screen.getByText('Submit'))

    expect(screen.getByPlaceholderText('Name')).toHaveValue('Shawn Joe')
  })

  test('PktButton resets form when outside but linked via form attribute', async () => {
    render(<MockForm buttonPosition="outside" />)

    await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe')
    await userEvent.click(screen.getByText('Reset'))

    // Wait for the form state update
    await screen.findByPlaceholderText('Name')

    expect(screen.getByPlaceholderText('Name')).toHaveValue('')
  })
})

test('forwardRef works correctly', async () => {
  const ref = createRef<HTMLButtonElement>()
  render(<PktButton ref={ref}>Click me</PktButton>)

  await userEvent.click(screen.getByText('Click me'))

  expect(ref.current).toBe(screen.getByRole('button'))
})

test('PktButton triggers click when focused and enter is pressed', async () => {
  const handleClick = jest.fn()
  render(<PktButton onClick={handleClick}>trøkk her</PktButton>)

  const button = screen.getByRole('button', { name: /trøkk her/i })

  button.focus()
  expect(button).toHaveFocus()

  await userEvent.keyboard('{Enter}')
  expect(handleClick).toHaveBeenCalledTimes(1)
})

test('PktButton triggers click when focused and space is pressed', async () => {
  const handleClick = jest.fn()
  render(<PktButton onClick={handleClick}>Trøkk igjen</PktButton>)

  const button = screen.getByRole('button')

  button.focus()
  expect(button).toHaveFocus()

  await userEvent.keyboard(' ')

  expect(handleClick).toHaveBeenCalledTimes(1)
})

describe('accessibility', () => {
  it('renders with no wcag errors with axe', async () => {
    const { container } = render(<PktButton title="Normal" skin="primary"></PktButton>)
    const results = await axe(container)

    expect(results).toHaveNoViolations()
  })
})
