import React, { useEffect, useRef, useState } from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import { FormHandles } from '@devesharp/unform-core';
import { Form } from '@devesharp/unform-web';
import { ThemeProvider } from 'styled-components';
import { Checkbox } from './Checkbox';
import 'jest-styled-components';

describe('checkbox', () => {
   it('snapshot - default', () => {
      function Component(): any {
         const [checked, setChecked] = useState();

         return <Checkbox title="Checkbox" checked={checked} onChange={setChecked} />;
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with color', () => {
      function Component(): any {
         return <Checkbox title="Checkbox" color="orange" checked />;
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with variant', () => {
      function Component(): any {
         return <Checkbox title="Checkbox" color="orange" checked />;
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with size', () => {
      function Component(): any {
         return <Checkbox checked size={100} />;
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with rounded', () => {
      function Component(): any {
         return <Checkbox checked rounded />;
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with object value', () => {
      function Component(): any {
         return (
            <>
               <Checkbox title="Checkbox" color="red" checked />
            </>
         );
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with error', () => {
      function Component(): any {
         const [checked, setChecked] = useState();

         return <Checkbox title="Checkbox" color="red" error="sdsd" checked={checked} onChange={setChecked} />;
      }

      const { container } = render(<Component />);

      expect(screen.getByTestId('input-error')).not.toBeUndefined();

      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with global theme', () => {
      function Component(): any {
         const [checked, setChecked] = useState();

         return (
            <ThemeProvider
               theme={{
                  checkbox: {
                     defaultColor: 'pink',
                     size: 180,
                     rounded: true,
                  },
               }}
            >
               <Checkbox title="Checkbox" checked={checked} onChange={setChecked} />;
            </ThemeProvider>
         );
      }

      const { container } = render(<Component />);
      expect(container.firstChild).toMatchSnapshot();
   });

   it('snapshot - with disabled', () => {
      function Component(): any {
         const [checked, setChecked] = useState();

         return <Checkbox title="Checkbox" disabled checked={checked} onChange={setChecked} />;
      }

      const { container } = render(<Component />);

      expect(screen.getByTestId('input-checkbox-error').className).toContain('disabled');

      expect(container.firstChild).toMatchSnapshot();
   });

   it('check onChange', () => {
      const onChange = jest.fn();

      function Component(): any {
         const [checked, setChecked] = useState(false);

         return (
            <>
               <Checkbox
                  title="Checkbox"
                  checked={checked}
                  onChange={(v: any) => {
                     setChecked(!!v);
                     onChange(v);
                  }}
                  data-testid="checkbox"
               />
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('checkbox'));
      fireEvent.click(screen.getByTestId('checkbox'));

      expect(onChange).toHaveBeenCalled();
      expect(onChange).toHaveBeenCalledWith(true);
      expect(onChange).toHaveBeenCalledWith(false);
   });

   it('check onChange with valueTrue and valueFalse', () => {
      const onChange = jest.fn();

      function Component(): any {
         const [checked, setChecked] = useState(false);

         return (
            <>
               <Checkbox
                  title="Checkbox"
                  checked={checked}
                  onChange={(v: any) => {
                     setChecked(!!v);
                     onChange(v);
                  }}
                  valueTrue="yes"
                  valueFalse="no"
                  data-testid="checkbox"
               />
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('checkbox'));
      fireEvent.click(screen.getByTestId('checkbox'));

      expect(onChange).toHaveBeenCalled();
      expect(onChange).toHaveBeenCalledWith('yes');
      expect(onChange).toHaveBeenCalledWith('no');
   });

   it('unform - snapshot - default', () => {
      function Component(): any {
         return (
            <Form onSubmit={() => {}}>
               <Checkbox name="default" title="Checkbox" />
            </Form>
         );
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - snapshot - with color', () => {
      function Component(): any {
         return (
            <Form onSubmit={() => {}} initialData={{ checkbox: true }}>
               <Checkbox name="checkbox" title="Checkbox" color="orange" />
            </Form>
         );
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - snapshot - with object value', () => {
      function Component(): any {
         return (
            <>
               <Form onSubmit={() => {}} initialData={{ checkbox: { id: 1 } }}>
                  <Checkbox name="checkbox" title="Checked" color="red" valueTrue={{ id: 1 }} />
               </Form>
               <Form onSubmit={() => {}} initialData={{ checkbox: { id: 2 } }}>
                  <Checkbox name="checkbox" title="Not Checked" color="red" valueTrue={{ id: 1 }} />
               </Form>
            </>
         );
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - snapshot - with object value async', () => {
      function Component(): any {
         const formRef = useRef<FormHandles>();

         useEffect(() => {
            formRef.current.setFieldValue('checkbox', { id: 1 });
         }, []);

         return (
            <Form onSubmit={() => {}} initialData={{ checkbox: { id: 2 } }} ref={formRef}>
               <Checkbox name="checkbox" title="Checkbox" color="red" value={{ id: 1 }} />
            </Form>
         );
      }

      const { container } = render(<Component />);

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - snapshot - with error', () => {
      function Component(): any {
         const formRef = useRef<FormHandles>();

         useEffect(() => {
            formRef.current.setFieldError('checkbox', 'Field is required');
         }, []);

         return (
            <Form onSubmit={() => {}} initialData={{ checkbox: { id: 2 } }} ref={formRef}>
               <Checkbox name="checkbox" title="Checkbox" color="red" value={{ id: 1 }} />
            </Form>
         );
      }

      const { container } = render(<Component />);

      expect(screen.getByTestId('input-error')).not.toBeUndefined();

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - snapshot - with disabled', () => {
      function Component(): any {
         const formRef = useRef<FormHandles>();

         useEffect(() => {
            formRef.current.setFieldError('checkbox', 'Field is required');
         }, []);

         return (
            <Form onSubmit={() => {}} initialData={{ checkbox: { id: 2 } }} ref={formRef}>
               <Checkbox name="checkbox" title="Checkbox" disabled value={{ id: 1 }} />
            </Form>
         );
      }

      const { container } = render(<Component />);

      expect(screen.getByTestId('input-checkbox-error').className).toContain('disabled');

      expect(container.firstChild).toMatchSnapshot();
   });

   it('unform - get value on onSubmit - initial value object', () => {
      const onSubmit = jest.fn();

      function Component(): any {
         const formRef = useRef<FormHandles>();

         return (
            <>
               <Form onSubmit={(v) => onSubmit(v)} initialData={{ checkbox: { id: 1 } }} ref={formRef}>
                  <Checkbox name="checkbox" title="Checkbox" valueTrue={{ id: 1 }} />
                  <button
                     data-testid="submit"
                     title="submit"
                     onClick={() => {
                        formRef.current.submitForm();
                     }}
                  />
               </Form>
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('submit'));

      expect(onSubmit).toHaveBeenCalled();
      expect(onSubmit).toHaveBeenCalledWith({
         checkbox: { id: 1 },
      });
   });

   it('unform - get value on onSubmit - initial value default', () => {
      const onSubmit = jest.fn();

      function Component(): any {
         const formRef = useRef<FormHandles>();

         return (
            <>
               <Form onSubmit={(v) => onSubmit(v)} initialData={{ checkbox: true }} ref={formRef}>
                  <Checkbox name="checkbox" title="Checkbox" />
                  <button
                     data-testid="submit"
                     title="submit"
                     onClick={() => {
                        formRef.current.submitForm();
                     }}
                  />
               </Form>
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('submit'));

      expect(onSubmit).toHaveBeenCalled();
      expect(onSubmit).toHaveBeenCalledWith({
         checkbox: true,
      });
   });

   it('unform - get value on onSubmit - clear form', () => {
      const onSubmit = jest.fn();

      function Component(): any {
         const formRef = useRef<FormHandles>();

         function clearForm(): void {
            formRef.current.reset();
         }

         return (
            <>
               <Form onSubmit={(v) => onSubmit(v)} initialData={{ checkbox: true }} ref={formRef}>
                  <Checkbox name="checkbox" title="Checkbox" />
                  <button
                     data-testid="submit"
                     title="submit"
                     onClick={() => {
                        formRef.current.submitForm();
                     }}
                  />
                  <button data-testid="clear" title="clear" onClick={clearForm} />
               </Form>
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('clear'));
      fireEvent.click(screen.getByTestId('submit'));

      expect(onSubmit).toHaveBeenCalled();
      expect(onSubmit).toHaveBeenCalledWith({
         checkbox: false,
      });
   });

   it('unform - get value on onSubmit - clear form with valueFalse', () => {
      const onSubmit = jest.fn();

      function Component(): any {
         const formRef = useRef<FormHandles>();

         function clearForm(): void {
            formRef.current.reset();
         }

         return (
            <>
               <Form onSubmit={(v) => onSubmit(v)} initialData={{ checkbox: true }} ref={formRef}>
                  <Checkbox name="checkbox" title="Checkbox" valueFalse="none" />
                  <button
                     data-testid="submit"
                     title="submit"
                     onClick={() => {
                        formRef.current.submitForm();
                     }}
                  />
                  <button data-testid="clear" title="clear" onClick={clearForm} />
               </Form>
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('clear'));
      fireEvent.click(screen.getByTestId('submit'));

      expect(onSubmit).toHaveBeenCalled();
      expect(onSubmit).toHaveBeenCalledWith({
         checkbox: 'none',
      });
   });

   it('unform - get value on onSubmit - set data', () => {
      const onSubmit = jest.fn();

      function Component(): any {
         const formRef = useRef<FormHandles>();

         function setData(): void {
            formRef.current.setFieldValue('checkbox', true);
         }

         return (
            <>
               <Form onSubmit={(v) => onSubmit(v)} ref={formRef}>
                  <Checkbox name="checkbox" title="Checkbox" />
                  <button data-testid="setData" title="setData" onClick={setData} />
                  <button
                     data-testid="submit"
                     title="submit"
                     onClick={() => {
                        formRef.current.submitForm();
                     }}
                  />
               </Form>
            </>
         );
      }

      render(<Component />);

      fireEvent.click(screen.getByTestId('setData'));
      fireEvent.click(screen.getByTestId('submit'));

      expect(onSubmit).toHaveBeenCalled();
      expect(onSubmit).toHaveBeenCalledWith({
         checkbox: true,
      });
   });
});
