import { useState } from "react";

import { useRouter } from "next/router";

import { mutate } from "swr";

// services
import stateService from "services/state.service";
// ui
import { Tooltip } from "components/ui";
// icons
import {
  ArrowDownIcon,
  ArrowUpIcon,
  PencilSquareIcon,
  TrashIcon,
} from "@heroicons/react/24/outline";
import { getStateGroupIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
import { groupBy, orderArrayBy } from "helpers/array.helper";
import { orderStateGroups } from "helpers/state.helper";
// types
import { ICurrentUserResponse, IState } from "types";
// fetch-keys
import { STATES_LIST } from "constants/fetch-keys";

type Props = {
  index: number;
  state: IState;
  statesList: IState[];
  handleEditState: () => void;
  handleDeleteState: () => void;
  user: ICurrentUserResponse | undefined;
};

export const SingleState: React.FC<Props> = ({
  index,
  state,
  statesList,
  handleEditState,
  handleDeleteState,
  user,
}) => {
  const [isSubmitting, setIsSubmitting] = useState(false);

  const router = useRouter();
  const { workspaceSlug, projectId } = router.query;

  const groupStates = statesList.filter((s) => s.group === state.group);
  const groupLength = groupStates.length;

  const handleMakeDefault = () => {
    setIsSubmitting(true);

    const currentDefaultState = statesList.find((s) => s.default);

    let newStatesList = statesList.map((s) => ({
      ...s,
      default: s.id === state.id ? true : s.id === currentDefaultState?.id ? false : s.default,
    }));
    newStatesList = orderArrayBy(newStatesList, "sequence", "ascending");

    mutate(
      STATES_LIST(projectId as string),
      orderStateGroups(groupBy(newStatesList, "group")),
      false
    );

    if (currentDefaultState)
      stateService
        .patchState(
          workspaceSlug as string,
          projectId as string,
          currentDefaultState?.id ?? "",
          {
            default: false,
          },
          user
        )
        .then(() => {
          stateService
            .patchState(
              workspaceSlug as string,
              projectId as string,
              state.id,
              {
                default: true,
              },
              user
            )
            .then(() => {
              mutate(STATES_LIST(projectId as string));
              setIsSubmitting(false);
            })
            .catch(() => {
              setIsSubmitting(false);
            });
        });
    else
      stateService
        .patchState(
          workspaceSlug as string,
          projectId as string,
          state.id,
          {
            default: true,
          },
          user
        )
        .then(() => {
          mutate(STATES_LIST(projectId as string));
          setIsSubmitting(false);
        })
        .catch(() => {
          setIsSubmitting(false);
        });
  };

  const handleMove = (state: IState, direction: "up" | "down") => {
    let newSequence = 15000;

    if (direction === "up") {
      if (index === 1) newSequence = groupStates[0].sequence - 15000;
      else newSequence = (groupStates[index - 2].sequence + groupStates[index - 1].sequence) / 2;
    } else {
      if (index === groupLength - 2) newSequence = groupStates[groupLength - 1].sequence + 15000;
      else newSequence = (groupStates[index + 2].sequence + groupStates[index + 1].sequence) / 2;
    }

    let newStatesList = statesList.map((s) => ({
      ...s,
      sequence: s.id === state.id ? newSequence : s.sequence,
    }));
    newStatesList = orderArrayBy(newStatesList, "sequence", "ascending");

    mutate(
      STATES_LIST(projectId as string),
      orderStateGroups(groupBy(newStatesList, "group")),
      false
    );

    stateService
      .patchState(
        workspaceSlug as string,
        projectId as string,
        state.id,
        {
          sequence: newSequence,
        },
        user
      )
      .then((res) => {
        console.log(res);
        mutate(STATES_LIST(projectId as string));
      })
      .catch((err) => {
        console.error(err);
      });
  };

  return (
    <div className="group flex items-center justify-between gap-2 border-custom-border-200 bg-custom-background-100 p-5 first:rounded-t-[10px] last:rounded-b-[10px]">
      <div className="flex items-center gap-3">
        {getStateGroupIcon(state.group, "20", "20", state.color)}
        <div>
          <h6 className="text-sm">{addSpaceIfCamelCase(state.name)}</h6>
          <p className="text-xs text-custom-text-200">{state.description}</p>
        </div>
      </div>
      <div className="flex items-center gap-2">
        {index !== 0 && (
          <button
            type="button"
            className="hidden text-custom-text-200 group-hover:inline-block"
            onClick={() => handleMove(state, "up")}
          >
            <ArrowUpIcon className="h-4 w-4" />
          </button>
        )}
        {!(index === groupLength - 1) && (
          <button
            type="button"
            className="hidden text-custom-text-200 group-hover:inline-block"
            onClick={() => handleMove(state, "down")}
          >
            <ArrowDownIcon className="h-4 w-4" />
          </button>
        )}
        {state.default ? (
          <span className="text-xs text-custom-text-200">Default</span>
        ) : (
          <button
            type="button"
            className="hidden text-xs text-custom-text-200 group-hover:inline-block"
            onClick={handleMakeDefault}
            disabled={isSubmitting}
          >
            Set as default
          </button>
        )}

        <button type="button" className="grid place-items-center" onClick={handleEditState}>
          <PencilSquareIcon className="h-4 w-4 text-custom-text-200" />
        </button>
        <button
          type="button"
          className={`${
            state.default || groupLength === 1 ? "cursor-not-allowed" : ""
          } grid place-items-center`}
          onClick={handleDeleteState}
          disabled={state.default || groupLength === 1}
        >
          {state.default ? (
            <Tooltip tooltipContent="Cannot delete the default state.">
              <TrashIcon className="h-4 w-4 text-red-500" />
            </Tooltip>
          ) : groupLength === 1 ? (
            <Tooltip tooltipContent="Cannot have an empty group.">
              <TrashIcon className="h-4 w-4 text-red-500" />
            </Tooltip>
          ) : (
            <TrashIcon className="h-4 w-4 text-red-500" />
          )}
        </button>
      </div>
    </div>
  );
};