import { useMutation, useQuery } from "@apollo/client/react";
import { Form } from "antd";
import queryString from "query-string";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import {
  DELETE_PHONEBOOK,
  INSERT_NEW_PHONEBOOK,
  QUERY_PHONEBOOK_BY_ID,
  UPDATE_PHONEBOOK
} from "../../graphql/phonebook.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import PhonebookFormComponent from "./phonebook-form.component";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop
});

function PhonebookFormContainer({ refetch, bodyshop }) {
  const history = useNavigate();
  const location = useLocation();

  // Parse once per render; do not mutate this object later.
  const search = queryString.parse(location.search);
  const phonebookentry = search?.phonebookentry;

  const [formLoading, setFormLoading] = useState(false);
  const [form] = Form.useForm();
  const { t } = useTranslation();

  const { loading, error, data } = useQuery(QUERY_PHONEBOOK_BY_ID, {
    variables: { id: phonebookentry },
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    skip: !phonebookentry || phonebookentry === "new"
  });

  const [updatePhonebook] = useMutation(UPDATE_PHONEBOOK);
  const [insertPhonebook] = useMutation(INSERT_NEW_PHONEBOOK);
  const [deletePhonebook] = useMutation(DELETE_PHONEBOOK);

  const notification = useNotification();

  const navigateWithoutPhonebookentry = () => {
    // Immutable omit (no delete/mutation)
    const { ...nextSearch } = search || {};
    history({ search: queryString.stringify(nextSearch) });
  };

  const handleDelete = async () => {
    setFormLoading(true);

    const result = await deletePhonebook({
      variables: { id: phonebookentry },
      refetchQueries: ["QUERY_PHONEBOOK_PAGINATED"]
    });

    if (!result.errors) {
      notification.success({
        title: t("phonebook.successes.deleted")
      });

      navigateWithoutPhonebookentry();

      if (refetch) {
        refetch().then(() => {
          form.resetFields();
        });
      }
    } else {
      notification.error({
        title: t("phonebook.errors.deleting", {
          message: JSON.stringify(result.errors)
        })
      });
    }

    setFormLoading(false);
  };

  const handleFinish = async (values) => {
    setFormLoading(true);

    if (phonebookentry && phonebookentry !== "new") {
      // It's a phonebook to update.
      const result = await updatePhonebook({
        variables: { id: phonebookentry, phonebook: values },
        refetchQueries: ["QUERY_PHONEBOOK_PAGINATED"]
      });

      if (!result.errors) {
        notification.success({
          title: t("phonebook.successes.saved")
        });

        if (refetch) await refetch();

        form.setFieldsValue(data.phonebook_by_pk);
        form.resetFields();

        setFormLoading(false);
      } else {
        notification.error({
          title: t("phonebook.errors.saving", {
            error: JSON.stringify(result.errors)
          })
        });

        setFormLoading(false);
      }
    } else {
      // It's a new phonebook to insert.
      const result = await insertPhonebook({
        variables: {
          phonebook_entry: [{ ...values, bodyshopid: bodyshop.id }]
        },
        refetchQueries: ["QUERY_PHONEBOOK_PAGINATED"]
      });

      if (!result.errors) {
        notification.success({
          title: t("phonebook.successes.saved")
        });

        if (refetch) await refetch();

        form.resetFields();
        form.resetFields();

        navigateWithoutPhonebookentry();

        setFormLoading(false);
      } else {
        notification.error({
          title: t("phonebook.errors.saving")
        });

        setFormLoading(false);
      }
    }
  };

  useEffect(() => {
    if (data || phonebookentry === "new") form.resetFields();
  }, [data, form, phonebookentry]);

  if (loading) return <LoadingSpinner />;
  if (error) return <AlertComponent title={error.message} type="error" />;

  return (
    <Form
      onFinish={handleFinish}
      form={form}
      layout="vertical"
      autoComplete="new-password"
      initialValues={data ? data.phonebook_by_pk : null}
    >
      {phonebookentry ? (
        <PhonebookFormComponent form={form} formLoading={formLoading} handleDelete={handleDelete} />
      ) : (
        t("phonebook.labels.noneselected")
      )}
    </Form>
  );
}

export default connect(mapStateToProps, null)(PhonebookFormContainer);
