import queryString from "query-string";
import { useLocation } from "react-router-dom";
import { useMutation, useQuery } from "@apollo/client";
import { MUTATION_TOGGLE_TASK_COMPLETED, MUTATION_TOGGLE_TASK_DELETED } from "../../graphql/tasks.queries.js";
import { pageLimit } from "../../utils/config.js";
import AlertComponent from "../alert/alert.component.jsx";
import React from "react";
import TaskListComponent from "./task-list.component.jsx";
import { notification } from "antd";
import { useTranslation } from "react-i18next";
import { connect, useDispatch } from "react-redux";
import { insertAuditTrail } from "../../redux/application/application.actions.js";
import AuditTrailMapping from "../../utils/AuditTrailMappings.js";
import { createStructuredSelector } from "reselect";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors.js";
import dayjs from "../../utils/day";

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

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

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

export function TaskListContainer({
  bodyshop,
  titleTranslation,
  query,
  relationshipType,
  relationshipId,
  currentUser,
  onlyMine,
  parentJobId,
  showRo = true,
  disableJobRefetch = false
}) {
  const { t } = useTranslation();
  const searchParams = queryString.parse(useLocation().search);
  const {
    page,
    sortcolumn,
    sortorder,
    deleted,
    completed //mine
  } = searchParams;
  const dispatch = useDispatch();

  const { loading, error, data, refetch } = useQuery(query[Object.keys(query)[0]], {
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    variables: {
      bodyshop: bodyshop.id,
      [relationshipType]: relationshipId,
      deleted: deleted === "true",
      completed: completed === "true", //TODO: Find where mine is set.
      assigned_to: onlyMine ? bodyshop?.employees?.find((e) => e.user_email === currentUser.email)?.id : undefined, // replace currentUserID with the actual ID of the current user
      offset: page ? (page - 1) * pageLimit : 0,
      limit: pageLimit,
      order: [
        {
          [sortcolumn || "created_at"]: sortorder ? (sortorder === "descend" ? "desc" : "asc") : "desc"
        }
      ]
    }
  });

  /**
   * Toggle task completed mutation
   */
  const [toggleTaskCompleted] = useMutation(MUTATION_TOGGLE_TASK_COMPLETED);

  /**
   * Toggle task completed status
   * @param id
   * @param currentStatus
   * @returns {Promise<void>}
   */
  const toggleCompletedStatus = async (id, currentStatus) => {
    const completed_at = !currentStatus ? dayjs().toISOString() : null;

    try {
      const toggledTaskObject = {
        variables: {
          id: id,
          completed: !currentStatus,
          completed_at: completed_at
        },
        refetchQueries: [Object.keys(query)[0]]
      };

      if (!disableJobRefetch) {
        toggledTaskObject.refetchQueries.push("GET_JOB_BY_PK");
      }

      const toggledTask = await toggleTaskCompleted(toggledTaskObject);

      if (!toggledTask.errors) {
        dispatch(
          insertAuditTrail({
            jobid: toggledTask.data.update_tasks_by_pk.jobid,
            operation: toggledTask?.data?.update_tasks_by_pk?.completed
              ? AuditTrailMapping.tasksCompleted(toggledTask.data.update_tasks_by_pk.title, currentUser.email)
              : AuditTrailMapping.tasksUncompleted(toggledTask.data.update_tasks_by_pk.title, currentUser.email),
            type: toggledTask?.data?.update_tasks_by_pk?.completed ? "tasksCompleted" : "tasksUncompleted"
          })
        );
      }

      notification["success"]({
        message: t("tasks.successes.completed")
      });
    } catch (err) {
      notification["error"]({
        message: t("tasks.failures.completed")
      });
    }
  };

  /**
   * Toggle task deleted mutation
   */
  const [toggleTaskDeleted] = useMutation(MUTATION_TOGGLE_TASK_DELETED);

  /**
   * Toggle task deleted status
   * @param id
   * @param currentStatus
   * @returns {Promise<void>}
   */

  const toggleDeletedStatus = async (id, currentStatus) => {
    const deleted_at = !currentStatus ? dayjs().toISOString() : null;
    try {
      const toggledTaskObject = {
        variables: {
          id: id,
          deleted: !currentStatus,
          deleted_at: deleted_at
        },
        refetchQueries: [Object.keys(query)[0]]
      };

      if (!disableJobRefetch) {
        toggledTaskObject.refetchQueries.push("GET_JOB_BY_PK");
      }

      const toggledTask = await toggleTaskDeleted(toggledTaskObject);

      if (!toggledTask.errors) {
        dispatch(
          insertAuditTrail({
            jobid: toggledTask.data.update_tasks_by_pk.jobid,
            operation: toggledTask?.data?.update_tasks_by_pk?.deleted
              ? AuditTrailMapping.tasksDeleted(toggledTask.data.update_tasks_by_pk.title, currentUser.email)
              : AuditTrailMapping.tasksUndeleted(toggledTask.data.update_tasks_by_pk.title, currentUser.email),
            type: toggledTask?.data?.update_tasks_by_pk?.deleted ? "tasksDeleted" : "tasksUndeleted"
          })
        );
      }

      notification["success"]({
        message: t("tasks.successes.deleted")
      });
    } catch (err) {
      notification["error"]({
        message: t("tasks.failures.deleted")
      });
    }
  };

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

  return (
    <TaskListComponent
      loading={loading}
      tasks={data ? data.tasks : null}
      total={data ? data.tasks_aggregate.aggregate.count : 0}
      titleTranslation={t(titleTranslation || "tasks.title")}
      refetch={refetch}
      toggleCompletedStatus={toggleCompletedStatus}
      toggleDeletedStatus={toggleDeletedStatus}
      relationshipType={relationshipType}
      relationshipId={relationshipId}
      onlyMine={onlyMine}
      showRo={showRo}
      parentJobId={parentJobId}
      bodyshop={bodyshop}
      query={query}
    />
  );
}
