import React, { useEffect, useRef, useState } from 'react';
import { Button } from 'react-native';
import { render, fireEvent } from '@testing-library/react-native';
import { Form } from '@unform/mobile';
import { Select, ISelectItems } from '.';

const items: ISelectItems[] = [
   { name: 'Eren', id: 'Eren' },
   { name: 'Levi', id: 'Levi' },
   { name: 'Rainer', id: 'Rainer' },
   { name: 'Falco', id: 'Falco' },
];

it('snapshot - default', () => {
   const { toJSON, getByTestId } = render(
      <Form onSubmit={() => {}}>
         <Select name="default" items={items} />
      </Form>,
   );

   expect(toJSON()).toMatchSnapshot();
});

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

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

   expect(toJSON()).toMatchSnapshot();
});

it('snapshot - with initial value', () => {
   function Component(): any {
      return (
         <Form onSubmit={() => {}} initialData={{ default: 'Falco' }}>
            <Select name="default" items={items} title="Characters" />
         </Form>
      );
   }

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

   expect(toJSON()).toMatchSnapshot();
});

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

      useEffect(() => {
         formRef.current.setFieldError('default', 'Field Invalid');
      }, []);

      return (
         <Form onSubmit={() => {}} ref={formRef}>
            <Select name="default" items={items} title="Characters" />
         </Form>
      );
   }

   const { toJSON, queryByTestId } = render(<Component />);

   expect(toJSON()).toMatchSnapshot();
   expect(queryByTestId('select-error')).not.toBeNull();
});

it('snapshot - select value', () => {
   const onSubmit = jest.fn();

   function Component(): any {
      const formRef = useRef(null);

      useEffect(() => {
         formRef.current.setFieldError('default', 'Field Invalid');
      }, []);

      return (
         <Form onSubmit={(data) => onSubmit(data)} ref={formRef}>
            <Select name="default" items={items} title="Characters" />

            <Button
               testID="submit"
               title="Submit"
               onPress={() => {
                  formRef.current.submitForm();
               }}
            />
         </Form>
      );
   }

   const { toJSON, getByTestId } = render(<Component />);

   expect(toJSON()).toMatchSnapshot();

   // Open select
   fireEvent.press(getByTestId('select'));
   fireEvent.press(getByTestId('option-Falco'));
   fireEvent.press(getByTestId('submit'));

   expect(onSubmit).toHaveBeenCalled();
   expect(onSubmit).toHaveBeenCalledWith({
      default: 'Falco',
   });
});

it('snapshot - submit on initial value [name]', () => {
   const onSubmit = jest.fn();

   function Component(): any {
      const formRef = useRef(null);

      useEffect(() => {
         formRef.current.setFieldError('default', 'Field Invalid');
      }, []);

      return (
         <Form onSubmit={(data) => onSubmit(data)} initialData={{ default: 'Falco' }} ref={formRef}>
            <Select name="default" items={items} title="Characters" />

            <Button
               testID="submit"
               title="Submit"
               onPress={() => {
                  formRef.current.submitForm();
               }}
            />
         </Form>
      );
   }

   const { toJSON, getByTestId } = render(<Component />);

   expect(toJSON()).toMatchSnapshot();

   // Open select
   fireEvent.press(getByTestId('submit'));

   expect(onSubmit).toHaveBeenCalled();
   expect(onSubmit).toHaveBeenCalledWith({
      default: 'Falco',
   });
});

it('snapshot - submit on initial value with object', () => {
   const onSubmit = jest.fn();

   const itemsW: ISelectItems[] = [
      { name: 'Eren', id: 'Eren', value: { name: 'Eren' } },
      { name: 'Levi', id: 'Levi', value: { name: 'Levi' } },
      { name: 'Rainer', id: 'Rainer', value: { name: 'Rainer' } },
      { name: 'Falco', id: 'Falco', value: { name: 'Falco' } },
   ];

   function Component(): any {
      const formRef = useRef(null);

      useEffect(() => {
         formRef.current.setFieldError('default', 'Field Invalid');
      }, []);

      return (
         <Form onSubmit={(data) => onSubmit(data)} initialData={{ default: { name: 'Falco' } }} ref={formRef}>
            <Select name="default" items={itemsW} title="Characters" />

            <Button
               testID="submit"
               title="Submit"
               onPress={() => {
                  formRef.current.submitForm();
               }}
            />
         </Form>
      );
   }

   const { toJSON, getByTestId } = render(<Component />);

   expect(toJSON()).toMatchSnapshot();

   // Open select
   fireEvent.press(getByTestId('submit'));

   expect(onSubmit).toHaveBeenCalled();
   expect(onSubmit).toHaveBeenCalledWith({
      default: { name: 'Falco' },
   });
});

it('snapshot - submit on initial value not found', () => {
   const onSubmit = jest.fn();

   const itemsW: ISelectItems[] = [
      { name: 'Eren', id: 'Eren', value: { name: 'Eren' } },
      { name: 'Levi', id: 'Levi', value: { name: 'Levi' } },
      { name: 'Rainer', id: 'Rainer', value: { name: 'Rainer' } },
      { name: 'Falco', id: 'Falco', value: { name: 'Falco' } },
   ];

   function Component(): any {
      const formRef = useRef(null);

      useEffect(() => {
         formRef.current.setFieldError('default', 'Field Invalid');
      }, []);

      return (
         <Form onSubmit={(data) => onSubmit(data)} initialData={{ default: { name: 'Falco2' } }} ref={formRef}>
            <Select name="default" items={itemsW} title="Characters" />

            <Button
               testID="submit"
               title="Submit"
               onPress={() => {
                  formRef.current.submitForm();
               }}
            />
         </Form>
      );
   }

   const { toJSON, getByTestId } = render(<Component />);

   expect(toJSON()).toMatchSnapshot();

   // Open select
   fireEvent.press(getByTestId('submit'));

   expect(onSubmit).toHaveBeenCalled();
   expect(onSubmit).toHaveBeenCalledWith({
      default: null,
   });
});
