import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { noop } from '../../../../helpers/utils';
import { NumericTextFilter } from './NumericTextFilter';

describe('NumericTextFilter', () => {
  it('Filter input is rendered', () => {
    const { container } = render(<NumericTextFilter onSelect={noop} />);
    expect(container.querySelector('.inputValue')).toBeInTheDocument();
  });

  it('Entered number on filter should be popped', () => {
    const spy = vi.fn();
    const sample = 123;
    const { container } = render(<NumericTextFilter onSelect={spy} />);
    const input = container.querySelector('.inputValue') as HTMLInputElement;

    fireEvent.change(input, { target: { value: sample.toString() } });
    fireEvent.keyDown(input, { key: 'Enter' });

    expect(spy).toHaveBeenCalledWith(sample);
  });

  it('displays an error for text inputs', () => {
    const spy = vi.fn();
    const onErrorSpy = vi.fn();
    const textInput = 'test';
    const { container } = render(
      <NumericTextFilter onSelect={spy} onError={onErrorSpy} />,
    );
    const input = container.querySelector('.inputValue') as HTMLInputElement;

    // Don't use fireEvent.change for type="number" with invalid text
    // Instead, directly test the keyDown handler with a non-numeric value
    Object.defineProperty(input, 'value', {
      writable: true,
      value: textInput,
    });

    fireEvent.keyDown(input, { key: 'Enter' });

    expect(spy).not.toHaveBeenCalled();
    expect(onErrorSpy).toHaveBeenCalled();

    const error = container.querySelector('small');

    expect(error).toBeInTheDocument();
    expect(error?.textContent).toBe('Enter a number');
  });

  it('Executes validator and displays message', () => {
    const spy = vi.fn();
    const { container } = render(
      <NumericTextFilter onSelect={spy} onValidate={() => 'invalid'} />,
    );
    const input = container.querySelector('.inputValue') as HTMLInputElement;

    fireEvent.change(input, { target: { value: '123' } });
    fireEvent.keyDown(input, { key: 'Enter' });

    expect(spy).toHaveBeenCalledTimes(0);

    const error = container.querySelector('small');

    expect(error).toBeInTheDocument();
    expect(error?.textContent).toBe('invalid');
  });
});
