import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
import waitForExpect from 'wait-for-expect';
import { Alert } from './Alert';
import 'jest-styled-components';

describe('Modal', () => {
   beforeAll(() => {
      (ReactDOM.createPortal as any) = jest.fn((element, node) => {
         return element;
      });
   });

   afterEach(() => {
      (ReactDOM.createPortal as any).mockClear();
   });

   it('snapshot - closed', async () => {
      function ComponentExample(): any {
         function openAlert(): void {
            Alert.show({
               title: 'Hello, how are you?',
               message: 'Welcome, click the confirm button to win a bonus!',
               titleColor: 'orange',
               iconColor: 'orange',
               buttons: [
                  {
                     text: 'Cancel',
                     bgColor: '#bbb',
                     onPress: () => {},
                  },
                  {
                     text: 'Confirm',
                     bgColor: '#222',
                     onPress: () => {},
                  },
               ],
            });
         }

         return (
            <div>
               <button onClick={openAlert} data-testid="button">
                  button
               </button>
               <Alert />
            </div>
         );
      }

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

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

   it('snapshot - opened', async () => {
      function ComponentExample(): any {
         function openAlert(): void {
            Alert.show({
               title: 'Hello, how are you?',
               message: 'Welcome, click the confirm button to win a bonus!',
               titleColor: 'orange',
               iconColor: 'orange',
               buttons: [
                  {
                     text: 'Cancel',
                     bgColor: '#bbb',
                     onPress: () => {},
                  },
                  {
                     text: 'Confirm',
                     bgColor: '#222',
                     onPress: () => {},
                  },
               ],
            });
         }

         return (
            <div>
               <button onClick={openAlert} data-testid="button">
                  button
               </button>
               <Alert />
            </div>
         );
      }

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

      // não deve mostrar modal
      expect(screen.queryByText('Hello, how are you?')).toBeNull();

      // abrir modal
      fireEvent.click(screen.getByTestId('button'));

      // deve mostrar modal
      await waitFor(() => screen.getByText('Hello, how are you?'));

      // mostrar modal
      expect(screen.queryByText('Hello, how are you?')).not.toBeNull();

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

   it('open by Alert.show', async () => {
      const onHide = jest.fn();
      function ComponentExample(): any {
         function openAlert(): void {
            Alert.show({
               title: 'Hello, how are you?',
               message: 'Welcome, click the confirm button to win a bonus!',
               titleColor: 'orange',
               iconColor: 'orange',
               buttons: [
                  {
                     text: 'Cancel',
                     bgColor: '#bbb',
                     onPress: () => {},
                  },
                  {
                     text: 'Confirm',
                     bgColor: '#222',
                     onPress: () => {},
                  },
               ],
            });
         }

         return (
            <>
               <button onClick={openAlert} data-testid="button">
                  button
               </button>
               <Alert />
            </>
         );
      }

      render(<ComponentExample />);

      // não deve mostrar modal
      expect(screen.queryByText('Hello, how are you?')).toBeNull();

      // abrir modal
      fireEvent.click(screen.getByTestId('button'));

      // deve mostrar modal
      await waitFor(() => screen.getByText('Hello, how are you?'));

      // mostrar modal
      expect(screen.queryByText('Hello, how are you?')).not.toBeNull();

      // fechar modal
      fireEvent.click(screen.getByTestId('close-btn'));

      // calledo
      await waitFor(() => {
         expect(screen.queryByText('Hello, how are you?')).toBeNull();
      });
      await waitForExpect(() => expect(screen.queryByText('Hello, how are you?')).toBeNull());
   });

   it('click buttons Alert should close', async () => {
      const onClose = jest.fn();
      const onConfirm = jest.fn();

      function ComponentExample(): any {
         function openAlert(): void {
            Alert.show({
               title: 'Hello, how are you?',
               message: 'Welcome, click the confirm button to win a bonus!',
               titleColor: 'orange',
               iconColor: 'orange',
               buttons: [
                  {
                     text: 'Confirm',
                     bgColor: '#222',
                     onPress: onConfirm,
                  },
               ],
               onClose,
            });
         }

         return (
            <>
               <button onClick={openAlert} data-testid="button">
                  button
               </button>
               <Alert />
            </>
         );
      }

      render(<ComponentExample />);

      // não deve mostrar modal
      expect(screen.queryByText('Hello, how are you?')).toBeNull();

      // abrir modal
      fireEvent.click(screen.getByTestId('button'));

      // deve mostrar modal
      await waitFor(() => screen.getByText('Hello, how are you?'));

      // mostrar modal
      expect(screen.queryByText('Hello, how are you?')).not.toBeNull();

      // Clicar nos dois botões
      fireEvent.click(screen.getByTestId('alert-btn-0'));

      // called
      await waitForExpect(() => expect(onConfirm).toHaveBeenCalled());
      await waitForExpect(() => expect(onClose).toHaveBeenCalled());
      await waitFor(() => {
         expect(screen.queryByText('Hello, how are you?')).toBeNull();
      });
      await waitForExpect(() => expect(screen.queryByText('Hello, how are you?')).toBeNull());
   });
});
