import React from 'react';
import { render, waitFor, fireEvent } from '@testing-library/react';
import { Button } from 'reactstrap';
import * as yup from 'yup';

import { Form, Checkbox, CheckboxGroup } from '../src';

describe('CheckboxGroup', () => {
  test('renders with group class name', () => {
    const { getByTestId } = render(
      <Form
        initialValues={{
          hello: [],
        }}
        onSubmit={vi.fn()}
         
        validationSchema={yup.object().shape({
          hello: yup.array().required('At least one checkbox is required'),
        })}
      >
        <CheckboxGroup name="hello" label="Checkbox Group" groupClassName="some-group">
          <Checkbox label="Check One" value="uno" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    const formControl = getByTestId('check-items-hello');

    expect(formControl.className).toContain('some-group');
  });

  test('renders danger className when invalid form', async () => {
    const { getByText, getByTestId } = render(
      <Form
        initialValues={{
          hello: [],
        }}
        onSubmit={vi.fn()}
        validationSchema={yup.object().shape({
          hello: yup.array().min(1, 'At least one checkbox is required'),
        })}
      >
        <CheckboxGroup name="hello" label="Checkbox Group">
          <Checkbox label="Chcek One" value="uno" />
          <Checkbox label="Check Two" value="dos" />
          <Checkbox label="Check Three" value="tres" />
          <Checkbox label={<>Check Four</>} value="cuatro" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    fireEvent.click(getByText('Submit'));

    await waitFor(() => {
      const checkboxGroup = getByTestId('check-items-hello');

      expect(checkboxGroup.className).toContain('is-touched');
      expect(checkboxGroup.className).toContain('is-invalid');
    });
  });

  test('renders with field help icon', () => {
    const { getByTestId } = render(
      <Form
        initialValues={{
          hello: '',
        }}
        onSubmit={vi.fn()}
      >
        <CheckboxGroup name="hello" label="Checkbox Group" helpId="helloHelpTopic">
          <Checkbox label="Check One" value="uno" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    expect(getByTestId('field-help-icon')).toBeDefined();
  });

  test('renders with required asterisk', () => {
    const { getByTestId } = render(
      <Form
        initialValues={{
          hello: '',
        }}
        onSubmit={vi.fn()}
      >
        <CheckboxGroup name="hello" label="Checkbox Group" required>
          <Checkbox label="Check One" value="uno" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    expect(getByTestId('required-asterisk')).toBeDefined();
  });

  test('submits with proper radio values', async () => {
    const onSubmit = vi.fn();
    const { getByText } = render(
      <Form
        initialValues={{
          hello: [],
        }}
         
        onSubmit={onSubmit}
        validationSchema={yup.object().shape({
          hello: yup.array().required('At least one checkbox is required'),
        })}
      >
        <CheckboxGroup name="hello" label="Checkbox Group">
          <Checkbox label="Check One" value="uno" />
          <Checkbox label="Check Two" value="dos" />
          <Checkbox label="Check Three" value="tres" />
          <Checkbox label={<>Check Four</>} value="cuatro" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    fireEvent.click(getByText('Check One'));
    fireEvent.click(getByText('Check Two'));

    fireEvent.click(getByText('Submit'));

    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledWith(
        expect.objectContaining({
          hello: ['uno', 'dos'],
        }),
        expect.anything()
      );
    });
  });

  test('submits with unchecked radio values', async () => {
    const onSubmit = vi.fn();
    const { getByText } = render(
      <Form
        initialValues={{
          hello: ['uno', 'dos'],
        }}
         
        onSubmit={onSubmit}
        validationSchema={yup.object().shape({
          hello: yup.array(),
        })}
      >
        <CheckboxGroup name="hello" label="Checkbox Group">
          <Checkbox label="Check One" value="uno" />
          <Checkbox label="Check Two" value="dos" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    fireEvent.click(getByText('Check One'));
    fireEvent.click(getByText('Check Two'));

    fireEvent.click(getByText('Submit'));

    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledWith(
        expect.objectContaining({
          hello: [],
        }),
        expect.anything()
      );
    });
  });

  test('calls on change callback', async () => {
    const onChange = vi.fn();

    const { getByText } = render(
      <Form
        initialValues={{
          hello: [],
        }}
        validationSchema={yup.object().shape({
          hello: yup.array(),
        })}
        onSubmit={vi.fn()}
      >
        <CheckboxGroup onChange={onChange} name="hello" label="Checkbox Group">
          <Checkbox label="Check One" value="uno" />
          <Checkbox label="Check Two" value="dos" />
        </CheckboxGroup>
        <Button type="submit">Submit</Button>
      </Form>
    );

    fireEvent.click(getByText('Check One'));

    await waitFor(() => {
      expect(onChange.mock.calls[0][0][0]).toBe('uno');
    });
  });
});
