/* eslint-disable @next/next/no-img-element */
import React, { useState, MouseEvent, Fragment, useEffect } from 'react';
import styles from './FormProject.module.scss';
import { validateEmail } from '../../utils';
import DashedLine from '../DashedLine';
import WavyLink from '../Link/WavyLink';
import { fetchEstimateProject } from '../../api/estimateProject';
import FormMessage from '../FormMessage';
import { SubmitMessage } from '../../models/common';
import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
import useTranslation from 'next-translate/useTranslation';

interface ActionsInput {
  onChange: (value: string) => void;
}

interface Inputs {
  [key: string]: ActionsInput;
}

export type Props = {
  title: string;
};

const FormProject = (props: Props): JSX.Element => {
  const { title } = props;
  const [enteredName, setEnteredName] = useState('');
  const [enteredEmail, setEnteredEmail] = useState('');
  const [enteredCompany, setEnteredCompany] = useState('');
  const [enteredProject, setEnteredProject] = useState('');
  const [enteredEstimate, setEnteredEstimate] = useState('');
  const [enteredFindUs, setEnteredFindUs] = useState('');
  const [nameError, setNameError] = useState(false);
  const [emailError, setEmailError] = useState(false);
  const [companyError, setCompanyError] = useState(false);
  const [estimateError, setEstimateError] = useState(false);
  const [inputId, setCurrentHoverInputId] = useState(-1);
  const [active, setActive] = useState(-1);
  const [activeSubmit, setActiveSubmit] = useState(true);
  const [submitMessage, setSubmitMessage] = useState<SubmitMessage>();
  const { executeRecaptcha } = useGoogleReCaptcha();
  const { t } = useTranslation();

  const clearFields = () => {
    setEnteredName('');
    setEnteredEmail('');
    setEnteredCompany('');
    setEnteredEstimate('');
    setEnteredProject('');
    setEnteredFindUs('');
  };

  const clearErrors = () => {
    setNameError(false);
    setEmailError(false);
    setCompanyError(false);
    setEstimateError(false);
  };

  const handleRecaptcha = async () => {
    try {
      const token = executeRecaptcha
        ? await executeRecaptcha('estimate_form')
        : null;
      if (!token) throw new Error();
      return token;
    } catch (error) {
      setSubmitMessage({
        type: 'error',
        message: t('common:form.recaptcha.failed'),
      });
    }
  };

  const submitHandler = async (
    e: MouseEvent<HTMLButtonElement>
  ): Promise<void> => {
    try {
      e.preventDefault();
      const token = await handleRecaptcha();
      if (
        enteredName &&
        !emailError &&
        enteredCompany &&
        enteredEmail &&
        token
      ) {
        setActiveSubmit(false);
        clearErrors();
        const formData = {
          name: enteredName,
          email: enteredEmail,
          company: enteredCompany,
          project: enteredProject,
          estimate: enteredEstimate,
          findUs: enteredFindUs,
          token,
        };

        const result = await fetchEstimateProject(formData);
        await new Promise((resolve) => setTimeout(resolve, 3000));
        if (result.status !== 'success') throw new Error(result.status);
        else
          setSubmitMessage({
            type: 'success',
            message: t('common:form.success'),
          });
        clearFields();
      } else {
        setActiveSubmit(true);
        setNameError(enteredName ? false : true);
        setEmailError(validateEmail(enteredEmail) ? false : true);
        setCompanyError(enteredCompany ? false : true);
        setEstimateError(enteredEstimate ? false : true);
      }
    } catch (error) {
      setSubmitMessage({
        type: 'error',
        message: t('common:form.failed'),
      });
    } finally {
      setActiveSubmit(true);
    }
  };

  const data = [
    {
      id: 'estimate',
      title: t('common:form.estimate.dropdown.estimate.title'),
      placeholder: t('common:form.estimate.dropdown.placeholder'),
      value: enteredEstimate,
      error: estimateError,
      type: 'dropdown',
      options: t('common:form.estimate.dropdown.estimate.options').split(','),
    },
    {
      id: 'name',
      title: t('common:form.estimate.name.title'),
      placeholder: t('common:form.estimate.name.placeholder'),
      value: enteredName,
      error: nameError,
      type: 'input',
    },
    {
      id: 'email',
      title: t('common:form.estimate.email.title'),
      placeholder: t('common:form.estimate.email.placeholder'),
      value: enteredEmail,
      error: emailError,
      type: 'input',
    },
    {
      id: 'company',
      title: t('common:form.estimate.company.title'),
      placeholder: t('common:form.estimate.company.placeholder'),
      value: enteredCompany,
      error: companyError,
      type: 'input',
    },
    {
      id: 'project',
      title: t('common:form.estimate.project.title'),
      placeholder: t('common:form.estimate.project.placeholder'),
      value: enteredProject,
      type: 'input',
    },
    {
      id: 'findUs',
      title: t('common:form.estimate.dropdown.findUs.title'),
      placeholder: t('common:form.estimate.dropdown.placeholder'),
      value: enteredFindUs,
      type: 'dropdown',
      options: t('common:form.estimate.dropdown.findUs.options').split(','),
    },
  ];

  const runOnChange: Inputs = {
    name: {
      onChange: (value: string) => {
        setEnteredName(value);
        setNameError(value ? false : true);
      },
    },
    email: {
      onChange: (value: string) => {
        setEnteredEmail(value);
        if (!value) {
          setEmailError(false);
        } else {
          setEmailError(!validateEmail(value));
        }
      },
    },
    company: {
      onChange: (value: string) => {
        setEnteredCompany(value);
        setCompanyError(value ? false : true);
      },
    },
    project: {
      onChange: (value: string) => {
        setEnteredProject(value);
      },
    },
    estimate: {
      onChange: (value: string) => {
        setEnteredEstimate(value);
      },
    },
    findUs: {
      onChange: (value: string) => {
        setEnteredFindUs(value);
      },
    },
  };

  const closeDropdown = (e: Event) => {
    if ((e.target as HTMLElement).className.indexOf('detectClick') === -1) {
      setActive(-1);
      document.removeEventListener('click', closeDropdown);
    }
  };

  const activeDropdown = (id: number) => {
    const current = active === id ? -1 : id;
    if (active !== id) {
      document.addEventListener('click', closeDropdown);
    }

    setActive(current);
  };

  useEffect(() => {
    if (inputId !== -1 && active === -1) {
      const input = data.find((inputData, id) => inputId === id);
      if (input?.type === 'dropdown') setCurrentHoverInputId(-1);
    }
  }, [active]);

  return (
    <div className={styles.container}>
      <div className={styles.formContainer}>
        <div className={`h4_italic ${styles.h4_italic}`}>{title}</div>
        <form>
          {data.map((element, index) => {
            return (
              <Fragment key={index}>
                <div
                  className={`${styles.form_control} ${
                    element.error ? styles.error : ''
                  }`}
                >
                  <label
                    htmlFor={element.id}
                    className={`text_4 
                  ${
                    element.value
                      ? styles.filled
                      : element.error
                      ? styles.error
                      : ''
                  } 
                  ${element.value && element.error ? styles.error : ''}
                  `}
                  >
                    {element.title}
                  </label>
                  {element.type === 'input' && (
                    <input
                      type="text"
                      id={element.id}
                      className={`text_4`}
                      placeholder={element.placeholder}
                      value={element.value}
                      onChange={(event) => {
                        runOnChange[element.id].onChange(event.target.value);
                      }}
                      onFocus={() =>
                        requestAnimationFrame(() =>
                          setCurrentHoverInputId(index)
                        )
                      }
                      onBlur={() => setCurrentHoverInputId(-1)}
                      disabled={!activeSubmit}
                    />
                  )}
                  {element.type === 'dropdown' && (
                    <div className={styles.dropdownContainer}>
                      <div
                        className={`${styles.dropdown}`}
                        onClick={() => {
                          setCurrentHoverInputId(index);
                          activeDropdown(index);
                        }}
                      >
                        <div
                          className={`text_4 ${styles.detectClick} ${
                            !element.value ? styles.placeholder : ''
                          }`}
                        >
                          {element.value || element.placeholder}
                        </div>
                        {index === active && (
                          <img
                            src={'/imgs/icons/top_arrow_icon.svg'}
                            alt=""
                            className={`${styles.errorImage}`}
                          />
                        )}
                        {index !== active && (
                          <img
                            src={'/imgs/icons/bottom_arrow_icon.svg'}
                            alt=""
                            className={`${styles.errorImage}`}
                          />
                        )}
                      </div>
                      {index === active && (
                        <div className={styles.optionsContainer}>
                          <div className={styles.options}>
                            {index === active &&
                              element.options?.map((option, idx) => {
                                return (
                                  <div
                                    key={idx}
                                    className={styles.option}
                                    onClick={() => {
                                      setEstimateError(false);
                                      runOnChange[element.id].onChange(option);
                                      setActive(-1);
                                    }}
                                  >
                                    <div className={`text_4 ${styles.text_4}`}>
                                      {option}
                                    </div>
                                  </div>
                                );
                              })}
                          </div>
                        </div>
                      )}
                    </div>
                  )}
                  {element.type !== 'dropdown' ? (
                    <img
                      src={'/imgs/icons/red_cancel_icon.svg'}
                      alt=""
                      className={`${styles.errorImage} ${
                        element.error ? styles.showErrorImage : ''
                      }`}
                    />
                  ) : null}
                  <div
                    className={`${styles.containerLine} ${
                      element.error ? styles.containerLineError : ''
                    }`}
                  >
                    <DashedLine
                      key={index}
                      animate={
                        inputId === index || element.error
                          ? 'active'
                          : 'inactive'
                      }
                    />
                  </div>
                </div>
              </Fragment>
            );
          })}
          {submitMessage ? (
            <FormMessage
              {...submitMessage}
              hideComplete={() => {
                setSubmitMessage(undefined);
              }}
            />
          ) : null}
          <button
            aria-label=""
            type="submit"
            onClick={submitHandler}
            disabled={!activeSubmit}
          >
            <div className={`h5 ${styles.h5}`}>
              <WavyLink loading={!activeSubmit} isIconFirst={true}>
                <span>{t('common:form.button.label')}</span>
              </WavyLink>
            </div>
          </button>
        </form>
      </div>
    </div>
  );
};

export default FormProject;
