import React, { useEffect, useRef, useState } from 'react';
import { render, fireEvent, waitFor, screen, cleanup } from '@testing-library/react';
import { FormHandles } from '@unform/core';
import { Form } from '@unform/web';
import { SelectAutocomplete } from '.';
import 'jest-styled-components';
import { Observable } from 'rxjs';
import { Textarea } from '../Textarea/web';

const fetchGroupMock = (): Observable<any> =>
   new Observable((observable) => {
      setTimeout(() => {
         observable.next([
            { disabled: true, name: 'Bairro', title: true },
            { name: 'Mogi das cruzes' },
            { name: 'Suzano' },
            { disabled: true, name: 'Cidade', title: true },
            { name: 'São Paulo' },
            { name: 'Suzano' },
            { name: 'Guarulhos' },
         ]);
         observable.complete();
         observable.unsubscribe();
      }, 10);
   });

const fetchSimpleMock = (): Observable<any> =>
   new Observable((observable) => {
      setTimeout(() => {
         observable.next(['São Paulo', 'Suzano', 'Guarulhos']);
         observable.complete();
         observable.unsubscribe();
      }, 10);
   });

it('renderizar default', () => {
   function Component(): any {
      return (
         <Form onSubmit={() => {}}>
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               title="Select AutoComplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

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

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

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

      return (
         <Form onSubmit={() => {}} ref={formRef}>
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

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

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

it('renderizar valor inicial', () => {
   function Component(): any {
      return (
         <Form onSubmit={() => {}} initialData={{ autocomplete: 'Suzano' }}>
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               title="Select AutoComplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

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

it('renderizar valor inicial object', () => {
   function Component(): any {
      return (
         <Form
            onSubmit={() => {}}
            initialData={{ autocomplete: { label: 'Suzano', value: { id: 1, name: 'Suzano' } } }}
         >
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

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

it('renderizar abrir/fechar popup', async () => {
   function Component(): any {
      return (
         <Form onSubmit={() => {}}>
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

   fireEvent.input(screen.getByTestId('autocomplete--input'), { target: { value: 'Suzano' } });

   // Deve aparecer popup
   await waitFor(() => !!screen.getByTestId('autocomplete-list'));
   expect(screen.getByTestId('autocomplete-list--row-0').innerHTML).toEqual('<div>São Paulo</div>');
   expect(screen.getByTestId('autocomplete-list--row-1').innerHTML).toEqual('<div>Suzano</div>');
   expect(screen.getByTestId('autocomplete-list--row-2').innerHTML).toEqual('<div>Guarulhos</div>');
   expect(container.firstChild).toMatchSnapshot();

   // Deve sumir popup
   fireEvent.blur(screen.getByTestId('autocomplete--input'));

   await waitFor(() => expect(screen.queryByTestId('autocomplete-list')).toBeNull());

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

it('selecionar item popup', async () => {
   function Component(): any {
      return (
         <Form onSubmit={() => {}}>
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
         </Form>
      );
   }

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

   fireEvent.input(screen.getByTestId('autocomplete--input'), { target: { value: 'Suzano' } });

   // Deve aparecer popup
   await waitFor(() => !!screen.getByTestId('autocomplete-list'));
   expect(screen.getByTestId('autocomplete-list--row-0').innerHTML).toEqual('<div>São Paulo</div>');
   expect(screen.getByTestId('autocomplete-list--row-1').innerHTML).toEqual('<div>Suzano</div>');
   expect(screen.getByTestId('autocomplete-list--row-2').innerHTML).toEqual('<div>Guarulhos</div>');
   fireEvent.mouseDown(screen.getByTestId('autocomplete-list--row-2'));
   fireEvent.blur(screen.getByTestId('autocomplete--input'));

   await waitFor(() => expect((screen.queryByTestId('autocomplete--input') as any).value).toEqual(''));
   await waitFor(() => expect(screen.queryByTestId('autocomplete--text-placeholder').innerHTML).toEqual('Guarulhos'));

   // Esperar fechar popup
   await waitFor(() => expect(screen.queryByTestId('autocomplete-list')).toBeNull());

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

it('verificar dados submit com string', (done) => {
   function Component(): any {
      const formRef = useRef<FormHandles>();

      return (
         <Form
            onSubmit={(data) => {
               expect(data.autocomplete).toEqual('Suzano');
               done();
            }}
            initialData={{ autocomplete: 'Suzano' }}
            ref={formRef}
         >
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
            <button type="submit" data-testid="submit" />
         </Form>
      );
   }

   render(<Component />);

   // Deve mostrar string de label
   fireEvent.change(screen.getByTestId('autocomplete--input'), { target: { value: 'Suzano' } });
   fireEvent.click(screen.getByTestId('submit'));
});

it('verificar dados submit com objeto', (done) => {
   function Component(): any {
      const formRef = useRef<FormHandles>();

      return (
         <Form
            onSubmit={(data) => {
               expect(data.autocomplete).toEqual({ label: 'Suzano', value: { id: 1, name: 'Suzano' } });
               done();
            }}
            initialData={{ autocomplete: { label: 'Suzano', value: { id: 1, name: 'Suzano' } } }}
            ref={formRef}
         >
            <SelectAutocomplete<any>
               fetch={fetchSimpleMock}
               name="autocomplete"
               getValue={(v) => v}
               renderInput={(item: any) => <div>{item}</div>}
            />
            <button type="submit" data-testid="submit" />
         </Form>
      );
   }

   render(<Component />);

   // Deve mostrar string de label
   fireEvent.change(screen.getByTestId('autocomplete--input'), { target: { value: 'Suzano' } });
   fireEvent.click(screen.getByTestId('submit'));
});
