import { useCallback, useEffect, useRef, useState } from "react";
import { Button, Card, Checkbox, Col, Form, Input, Modal, Row } from "antd";
import Markdown from "react-markdown";
import { createStructuredSelector } from "reselect";
import { selectCurrentEula, selectCurrentUser } from "../../redux/user/user.selectors";
import { connect } from "react-redux";
import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries";
import { useMutation } from "@apollo/client/react";
import { acceptEula } from "../../redux/user/user.actions";
import { useTranslation } from "react-i18next";
import dayjs from "../../utils/day";

import "./eula.styles.scss";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";

const Eula = ({ currentEula, currentUser, acceptEula }) => {
  const [formReady, setFormReady] = useState(false);
  const [hasEverScrolledToBottom, setHasEverScrolledToBottom] = useState(false);
  const [insertEulaAcceptance] = useMutation(INSERT_EULA_ACCEPTANCE);
  const [form] = Form.useForm();
  const markdownCardRef = useRef(null);
  const { t } = useTranslation();
  const notification = useNotification();

  const handleScroll = useCallback(
    (e) => {
      if (!e.target) return;
      const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight;
      if (bottom && !hasEverScrolledToBottom) {
        setHasEverScrolledToBottom(true);
      } else if (e.target.scrollHeight <= e.target.clientHeight && !hasEverScrolledToBottom) {
        setHasEverScrolledToBottom(true);
      }
    },
    [hasEverScrolledToBottom, setHasEverScrolledToBottom]
  );

  useEffect(() => {
    if (markdownCardRef.current) {
      handleScroll({ target: markdownCardRef.current });
    }
  }, [handleScroll]);

  const handleChange = useCallback(() => {
    form
      .validateFields({ validateOnly: true })
      .then(() => setFormReady(hasEverScrolledToBottom))
      .catch(() => setFormReady(false));
  }, [form, hasEverScrolledToBottom]);

  useEffect(() => {
    handleChange();
  }, [handleChange, hasEverScrolledToBottom, form]);

  const onFinish = async ({ ...formValues }) => {
    const eulaId = currentEula.id;
    const useremail = currentUser.email;

    try {
      // eslint-disable-next-line no-unused-vars
      const { accepted_terms, ...otherFormValues } = formValues;

      // Trim the values of the fields before submitting
      const trimmedFormValues = Object.entries(otherFormValues).reduce((acc, [key, value]) => {
        acc[key] = typeof value === "string" ? value?.trim() : value;
        return acc;
      }, {});

      await insertEulaAcceptance({
        variables: {
          eulaAcceptance: {
            eulaid: eulaId,
            useremail,
            ...otherFormValues,
            ...trimmedFormValues,
            date_accepted: new Date()
          }
        }
      });
      acceptEula();
    } catch (err) {
      notification.error({
        title: t("eula.errors.acceptance.message"),
        description: t("eula.errors.acceptance.description")
      });
      console.log(`${t("eula.errors.acceptance.message")}`);
      console.dir({
        message: err.message,
        stack: err.stack
      });
    }
  };

  return (
    <Modal
      title={t("eula.titles.modal")}
      className="eula-modal"
      width={"100vh"}
      open={currentEula}
      footer={() => (
        <Button
          className="eula-accept-button"
          form="tosForm"
          type="primary"
          size="large"
          htmlType="submit"
          disabled={!formReady}
        >
          {t("eula.buttons.accept")}
        </Button>
      )}
      closable={false}
    >
      <Card type="inner" className="eula-markdown-card" onScroll={handleScroll} ref={markdownCardRef}>
        <div id="markdowndiv" className="eula-markdown-div">
          <Markdown>{currentEula?.content?.replace(/\\n|\\r|\\n\\r|\\r\\n/g, "\n")}</Markdown>
        </div>
      </Card>

      <EulaFormComponent form={form} handleChange={handleChange} onFinish={onFinish} t={t} />

      {!hasEverScrolledToBottom && (
        <Card className="eula-never-scrolled" type="inner">
          <h3>{t("eula.content.never_scrolled")}</h3>
        </Card>
      )}
    </Modal>
  );
};

const EulaFormComponent = ({ form, handleChange, onFinish, t }) => (
  <Card type="inner" title={t("eula.titles.upper_card")} style={{ marginTop: "10px" }}>
    <Form id="tosForm" onChange={handleChange} onFinish={onFinish} form={form}>
      <Row gutter={24}>
        <Col span={12}>
          <Form.Item
            label={t("eula.labels.first_name")}
            name="first_name"
            rules={[
              {
                required: true,
                validator: (_, value) =>
                  value?.trim() !== "" ? Promise.resolve() : Promise.reject(new Error(t("eula.messages.first_name")))
              }
            ]}
          >
            <Input placeholder={t("eula.labels.first_name")} aria-label={t("eula.labels.first_name")} />
          </Form.Item>
        </Col>
        <Col span={12}>
          <Form.Item
            label={t("eula.labels.last_name")}
            name="last_name"
            rules={[
              {
                required: true,
                validator: (_, value) =>
                  value?.trim() !== "" ? Promise.resolve() : Promise.reject(new Error(t("eula.messages.last_name")))
              }
            ]}
          >
            <Input placeholder={t("eula.labels.last_name")} aria-label={t("eula.labels.last_name")} />
          </Form.Item>
        </Col>
      </Row>
      <Row gutter={24}>
        <Col span={12}>
          <Form.Item
            label={t("eula.labels.business_name")}
            name="business_name"
            rules={[
              {
                required: true,
                validator: (_, value) =>
                  value?.trim() !== "" ? Promise.resolve() : Promise.reject(new Error(t("eula.messages.business_name")))
              }
            ]}
          >
            <Input placeholder={t("eula.labels.business_name")} aria-label={t("eula.labels.business_name")} />
          </Form.Item>
        </Col>
        <Col span={12}>
          <Form.Item
            label={t("eula.labels.phone_number")}
            name="phone_number"
            rules={[
              {
                pattern: /^(\+\d{1,2}\s?)?1?-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/,
                message: t("eula.messages.phone_number")
              }
            ]}
          >
            <Input placeholder={t("eula.labels.phone_number")} aria-label={t("eula.labels.phone_number")} />
          </Form.Item>
        </Col>
      </Row>
      <Row gutter={24}>
        <Col span={12}>
          <Form.Item label={t("eula.labels.address")} name="address">
            <Input placeholder={t("eula.labels.address")} aria-label={t("eula.labels.address")} />
          </Form.Item>
        </Col>
        <Col span={12}>
          <Form.Item
            label={t("eula.labels.date_accepted")}
            name="date_accepted"
            rules={[
              {
                required: true,
                validator: (_, value) => {
                  if (dayjs(value).isSame(dayjs(), "day")) {
                    return Promise.resolve();
                  }
                  return Promise.reject(new Error(t("eula.messages.date_accepted")));
                }
              }
            ]}
          >
            <DateTimePicker isDateOnly onChange={handleChange} onlyToday aria-label={t("eula.labels.date_accepted")} />
          </Form.Item>
        </Col>
      </Row>
      <Row gutter={24}>
        <Col span={24}>
          <Form.Item
            name="accepted_terms"
            valuePropName="checked"
            rules={[
              {
                required: true,
                validator: (_, value) =>
                  value ? Promise.resolve() : Promise.reject(new Error(t("eula.messages.accepted_terms")))
              }
            ]}
          >
            <Checkbox aria-label={t("eula.labels.accepted_terms")}>{t("eula.labels.accepted_terms")}</Checkbox>
          </Form.Item>
        </Col>
      </Row>
    </Form>
  </Card>
);

const mapStateToProps = createStructuredSelector({
  currentEula: selectCurrentEula,
  currentUser: selectCurrentUser
});

const mapDispatchToProps = (dispatch) => ({
  acceptEula: () => dispatch(acceptEula())
});

export default connect(mapStateToProps, mapDispatchToProps)(Eula);
