import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { FormProvider, useForm } from 'react-hook-form';
import { ThemeProvider } from '../../../theme';
import RhfControlGroup from './RhfControlGroup';

interface Values {
  gender: string | null;
}

function Harness({ onSubmit }: { onSubmit: (values: Values) => void }) {
  const form = useForm<Values>({ mode: 'onTouched', defaultValues: { gender: null } });
  return (
    <FormProvider {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <RhfControlGroup<Values>
          name="gender"
          label="Gender"
          hint="Required for same-gender matching"
          rules={{ validate: (value) => value != null || 'Pick one' }}
        >
          {({ field, hasError }) => (
            <button type="button" data-invalid={hasError} onClick={() => field.onChange('female')}>
              Female
            </button>
          )}
        </RhfControlGroup>
        <button type="submit">Save</button>
      </form>
    </FormProvider>
  );
}

function renderGroup() {
  const onSubmit = jest.fn();
  render(
    <ThemeProvider>
      <Harness onSubmit={onSubmit} />
    </ThemeProvider>,
  );
  return { onSubmit };
}

describe('<RhfControlGroup/> component', () => {
  it('gives a non-input control the same label + hint shell as a text field', () => {
    renderGroup();
    expect(screen.getByText('Gender')).toBeInTheDocument();
    expect(screen.getByText('Required for same-gender matching')).toBeInTheDocument();
  });

  it('surfaces the rule message and flags the control when validation fails', async () => {
    const user = userEvent.setup();
    const { onSubmit } = renderGroup();
    await user.click(screen.getByText('Save'));
    expect(await screen.findByText('Pick one')).toBeInTheDocument();
    expect(screen.getByText('Female')).toHaveAttribute('data-invalid', 'true');
    expect(onSubmit).not.toHaveBeenCalled();
  });

  it('writes the control’s value into form state', async () => {
    const user = userEvent.setup();
    const { onSubmit } = renderGroup();
    await user.click(screen.getByText('Female'));
    await user.click(screen.getByText('Save'));
    expect(onSubmit).toHaveBeenCalledWith({ gender: 'female' }, expect.anything());
  });
});
