import { action, computed, makeObservable, observable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./issue.store";

export interface IIssueKanBanViewStore {
  kanBanToggle: {
    groupByHeaderMinMax: string[];
    subgroupByIssuesVisibility: string[];
  };
  // computed
  canUserDragDrop: boolean;
  canUserDragDropVertically: boolean;
  canUserDragDropHorizontally: boolean;
  // actions
  handleKanBanToggle: (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => void;
  handleSwimlaneDragDrop: (source: any, destination: any) => void;
  handleDragDrop: (source: any, destination: any) => void;
}

export class IssueKanBanViewStore implements IIssueKanBanViewStore {
  kanBanToggle: {
    groupByHeaderMinMax: string[];
    subgroupByIssuesVisibility: string[];
  } = { groupByHeaderMinMax: [], subgroupByIssuesVisibility: [] };
  // root store
  rootStore;

  constructor(_rootStore: RootStore) {
    makeObservable(this, {
      kanBanToggle: observable,
      // computed
      canUserDragDrop: computed,
      canUserDragDropVertically: computed,
      canUserDragDropHorizontally: computed,

      // actions
      handleKanBanToggle: action,
      handleSwimlaneDragDrop: action,
      handleDragDrop: action,
    });

    this.rootStore = _rootStore;
  }

  get canUserDragDrop() {
    if (this.rootStore.issueDetail.peekId) return false;
    if (
      this.rootStore?.issueFilter?.userDisplayFilters?.order_by &&
      this.rootStore?.issueFilter?.userDisplayFilters?.order_by === "sort_order" &&
      this.rootStore?.issueFilter?.userDisplayFilters?.group_by &&
      ["state", "priority"].includes(this.rootStore?.issueFilter?.userDisplayFilters?.group_by)
    ) {
      if (!this.rootStore?.issueFilter?.userDisplayFilters?.sub_group_by) return true;
      if (
        this.rootStore?.issueFilter?.userDisplayFilters?.sub_group_by &&
        ["state", "priority"].includes(this.rootStore?.issueFilter?.userDisplayFilters?.sub_group_by)
      )
        return true;
    }
    return false;
  }

  get canUserDragDropVertically() {
    return false;
  }

  get canUserDragDropHorizontally() {
    return false;
  }

  handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => {
    this.kanBanToggle = {
      ...this.kanBanToggle,
      [toggle]: this.kanBanToggle[toggle].includes(value)
        ? this.kanBanToggle[toggle].filter((v) => v !== value)
        : [...this.kanBanToggle[toggle], value],
    };
  };

  handleSwimlaneDragDrop = async (source: any, destination: any) => {
    const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
    const projectId = this.rootStore?.project?.projectId;
    const issueType: IIssueType | null = this.rootStore?.issue?.getIssueType;
    const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
    const currentIssues: any = this.rootStore.issue.getIssues;

    const sortOrderDefaultValue = 65535;

    if (workspaceSlug && projectId && issueType && issueLayout === "kanban" && currentIssues) {
      // update issue payload
      let updateIssue: any = {
        workspaceSlug: workspaceSlug,
        projectId: projectId,
      };

      // source, destination group and sub group id
      let droppableSourceColumnId = source?.droppableId || null;
      droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
      let droppableDestinationColumnId = destination?.droppableId || null;
      droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
      if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;

      const source_group_id: string = droppableSourceColumnId[0];
      const source_sub_group_id: string = droppableSourceColumnId[1] === "null" ? null : droppableSourceColumnId[1];

      const destination_group_id: string = droppableDestinationColumnId[0];
      const destination_sub_group_id: string =
        droppableDestinationColumnId[1] === "null" ? null : droppableDestinationColumnId[1];

      if (source_sub_group_id === destination_sub_group_id) {
        if (source_group_id === destination_group_id) {
          const _issues = currentIssues[source_sub_group_id][source_group_id];

          // update the sort order
          if (destination.index === 0) {
            updateIssue = {
              ...updateIssue,
              sort_order: _issues[destination.index].sort_order - sortOrderDefaultValue,
            };
          } else if (destination.index === _issues.length - 1) {
            updateIssue = {
              ...updateIssue,
              sort_order: _issues[destination.index].sort_order + sortOrderDefaultValue,
            };
          } else {
            updateIssue = {
              ...updateIssue,
              sort_order: (_issues[destination.index - 1].sort_order + _issues[destination.index].sort_order) / 2,
            };
          }

          const [removed] = _issues.splice(source.index, 1);
          _issues.splice(destination.index, 0, { ...removed, sort_order: updateIssue.sort_order });
          updateIssue = { ...updateIssue, issueId: removed?.id };
          currentIssues[source_sub_group_id][source_group_id] = _issues;
        }

        if (source_group_id != destination_group_id) {
          const _sourceIssues = currentIssues[source_sub_group_id][source_group_id];
          let _destinationIssues = currentIssues[destination_sub_group_id][destination_group_id] || [];

          if (_destinationIssues && _destinationIssues.length > 0) {
            if (destination.index === 0) {
              updateIssue = {
                ...updateIssue,
                sort_order: _destinationIssues[destination.index].sort_order - sortOrderDefaultValue,
              };
            } else if (destination.index === _destinationIssues.length) {
              updateIssue = {
                ...updateIssue,
                sort_order: _destinationIssues[destination.index - 1].sort_order + sortOrderDefaultValue,
              };
            } else {
              updateIssue = {
                ...updateIssue,
                sort_order:
                  (_destinationIssues[destination.index - 1].sort_order +
                    _destinationIssues[destination.index].sort_order) /
                  2,
              };
            }
          } else {
            updateIssue = {
              ...updateIssue,
              sort_order: sortOrderDefaultValue,
            };
          }

          let issueStatePriority = {};
          if (this.rootStore.issueFilter?.userDisplayFilters?.group_by === "state") {
            updateIssue = { ...updateIssue, state: destination_group_id };
            issueStatePriority = { ...issueStatePriority, state: destination_group_id };
          }
          if (this.rootStore.issueFilter?.userDisplayFilters?.group_by === "priority") {
            updateIssue = { ...updateIssue, priority: destination_group_id };
            issueStatePriority = { ...issueStatePriority, priority: destination_group_id };
          }

          const [removed] = _sourceIssues.splice(source.index, 1);
          if (_destinationIssues && _destinationIssues.length > 0)
            _destinationIssues.splice(destination.index, 0, {
              ...removed,
              sort_order: updateIssue.sort_order,
              ...issueStatePriority,
            });
          else
            _destinationIssues = [
              ..._destinationIssues,
              { ...removed, sort_order: updateIssue.sort_order, ...issueStatePriority },
            ];
          updateIssue = { ...updateIssue, issueId: removed?.id };

          currentIssues[source_sub_group_id][source_group_id] = _sourceIssues;
          currentIssues[destination_sub_group_id][destination_group_id] = _destinationIssues;
        }
      }

      if (source_sub_group_id != destination_sub_group_id) {
        const _sourceIssues = currentIssues[source_sub_group_id][source_group_id];
        let _destinationIssues = currentIssues[destination_sub_group_id][destination_group_id] || [];

        if (_destinationIssues && _destinationIssues.length > 0) {
          if (destination.index === 0) {
            updateIssue = {
              ...updateIssue,
              sort_order: _destinationIssues[destination.index].sort_order - sortOrderDefaultValue,
            };
          } else if (destination.index === _destinationIssues.length) {
            updateIssue = {
              ...updateIssue,
              sort_order: _destinationIssues[destination.index - 1].sort_order + sortOrderDefaultValue,
            };
          } else {
            updateIssue = {
              ...updateIssue,
              sort_order:
                (_destinationIssues[destination.index - 1].sort_order +
                  _destinationIssues[destination.index].sort_order) /
                2,
            };
          }
        } else {
          updateIssue = {
            ...updateIssue,
            sort_order: sortOrderDefaultValue,
          };
        }

        let issueStatePriority = {};
        if (source_group_id === destination_group_id) {
          if (this.rootStore.issueFilter?.userDisplayFilters?.sub_group_by === "state") {
            updateIssue = { ...updateIssue, state: destination_sub_group_id };
            issueStatePriority = { ...issueStatePriority, state: destination_sub_group_id };
          }
          if (this.rootStore.issueFilter?.userDisplayFilters?.sub_group_by === "priority") {
            updateIssue = { ...updateIssue, priority: destination_sub_group_id };
            issueStatePriority = { ...issueStatePriority, priority: destination_sub_group_id };
          }
        } else {
          if (this.rootStore.issueFilter?.userDisplayFilters?.sub_group_by === "state") {
            updateIssue = { ...updateIssue, state: destination_sub_group_id, priority: destination_group_id };
            issueStatePriority = {
              ...issueStatePriority,
              state: destination_sub_group_id,
              priority: destination_group_id,
            };
          }
          if (this.rootStore.issueFilter?.userDisplayFilters?.sub_group_by === "priority") {
            updateIssue = { ...updateIssue, state: destination_group_id, priority: destination_sub_group_id };
            issueStatePriority = {
              ...issueStatePriority,
              state: destination_group_id,
              priority: destination_sub_group_id,
            };
          }
        }

        const [removed] = _sourceIssues.splice(source.index, 1);
        if (_destinationIssues && _destinationIssues.length > 0)
          _destinationIssues.splice(destination.index, 0, {
            ...removed,
            sort_order: updateIssue.sort_order,
            ...issueStatePriority,
          });
        else
          _destinationIssues = [
            ..._destinationIssues,
            { ...removed, sort_order: updateIssue.sort_order, ...issueStatePriority },
          ];

        updateIssue = { ...updateIssue, issueId: removed?.id };
        currentIssues[source_sub_group_id][source_group_id] = _sourceIssues;
        currentIssues[destination_sub_group_id][destination_group_id] = _destinationIssues;
      }

      const reorderedIssues = {
        ...this.rootStore?.issue.issues,
        [projectId]: {
          ...this.rootStore?.issue.issues?.[projectId],
          [issueType]: {
            ...this.rootStore?.issue.issues?.[projectId]?.[issueType],
            [issueType]: currentIssues,
          },
        },
      };

      runInAction(() => {
        this.rootStore.issue.issues = { ...reorderedIssues };
      });

      this.rootStore.issueDetail?.updateIssue(
        updateIssue.workspaceSlug,
        updateIssue.projectId,
        updateIssue.issueId,
        updateIssue
      );
    }
  };

  handleDragDrop = async (source: any, destination: any) => {
    const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
    const projectId = this.rootStore?.project?.projectId;
    const issueType: IIssueType | null = this.rootStore?.issue?.getIssueType;
    const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
    const currentIssues: any = this.rootStore.issue.getIssues;

    const sortOrderDefaultValue = 65535;

    if (workspaceSlug && projectId && issueType && issueLayout === "kanban" && currentIssues) {
      // update issue payload
      let updateIssue: any = {
        workspaceSlug: workspaceSlug,
        projectId: projectId,
      };

      // source, destination group and sub group id
      let droppableSourceColumnId = source?.droppableId || null;
      droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
      let droppableDestinationColumnId = destination?.droppableId || null;
      droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
      if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;

      const source_group_id: string = droppableSourceColumnId[0];
      const destination_group_id: string = droppableDestinationColumnId[0];

      if (this.canUserDragDrop) {
        // vertical
        if (source_group_id === destination_group_id) {
          const _issues = currentIssues[source_group_id];

          // update the sort order
          if (destination.index === 0) {
            updateIssue = {
              ...updateIssue,
              sort_order: _issues[destination.index].sort_order - sortOrderDefaultValue,
            };
          } else if (destination.index === _issues.length - 1) {
            updateIssue = {
              ...updateIssue,
              sort_order: _issues[destination.index].sort_order + sortOrderDefaultValue,
            };
          } else {
            updateIssue = {
              ...updateIssue,
              sort_order: (_issues[destination.index - 1].sort_order + _issues[destination.index].sort_order) / 2,
            };
          }

          const [removed] = _issues.splice(source.index, 1);
          _issues.splice(destination.index, 0, { ...removed, sort_order: updateIssue.sort_order });
          updateIssue = { ...updateIssue, issueId: removed?.id };
          currentIssues[source_group_id] = _issues;
        }

        // horizontal
        if (source_group_id != destination_group_id) {
          const _sourceIssues = currentIssues[source_group_id];
          let _destinationIssues = currentIssues[destination_group_id] || [];

          if (_destinationIssues && _destinationIssues.length > 0) {
            if (destination.index === 0) {
              updateIssue = {
                ...updateIssue,
                sort_order: _destinationIssues[destination.index].sort_order - sortOrderDefaultValue,
              };
            } else if (destination.index === _destinationIssues.length) {
              updateIssue = {
                ...updateIssue,
                sort_order: _destinationIssues[destination.index - 1].sort_order + sortOrderDefaultValue,
              };
            } else {
              updateIssue = {
                ...updateIssue,
                sort_order:
                  (_destinationIssues[destination.index - 1].sort_order +
                    _destinationIssues[destination.index].sort_order) /
                  2,
              };
            }
          } else {
            updateIssue = {
              ...updateIssue,
              sort_order: sortOrderDefaultValue,
            };
          }

          let issueStatePriority = {};
          if (this.rootStore.issueFilter?.userDisplayFilters?.group_by === "state") {
            updateIssue = { ...updateIssue, state: destination_group_id };
            issueStatePriority = { ...issueStatePriority, state: destination_group_id };
          }
          if (this.rootStore.issueFilter?.userDisplayFilters?.group_by === "priority") {
            updateIssue = { ...updateIssue, priority: destination_group_id };
            issueStatePriority = { ...issueStatePriority, priority: destination_group_id };
          }

          const [removed] = _sourceIssues.splice(source.index, 1);
          if (_destinationIssues && _destinationIssues.length > 0)
            _destinationIssues.splice(destination.index, 0, {
              ...removed,
              sort_order: updateIssue.sort_order,
              ...issueStatePriority,
            });
          else
            _destinationIssues = [
              ..._destinationIssues,
              { ...removed, sort_order: updateIssue.sort_order, ...issueStatePriority },
            ];
          updateIssue = { ...updateIssue, issueId: removed?.id };

          currentIssues[source_group_id] = _sourceIssues;
          currentIssues[destination_group_id] = _destinationIssues;
        }
      }

      // user can drag the issues only vertically
      if (this.canUserDragDropVertically && destination_group_id === destination_group_id) {
      }

      // user can drag the issues only horizontally
      if (this.canUserDragDropHorizontally && destination_group_id != destination_group_id) {
      }

      const reorderedIssues = {
        ...this.rootStore?.issue.issues,
        [projectId]: {
          ...this.rootStore?.issue.issues?.[projectId],
          [issueType]: {
            ...this.rootStore?.issue.issues?.[projectId]?.[issueType],
            [issueType]: currentIssues,
          },
        },
      };

      runInAction(() => {
        this.rootStore.issue.issues = { ...reorderedIssues };
      });

      this.rootStore.issueDetail?.updateIssue(
        updateIssue.workspaceSlug,
        updateIssue.projectId,
        updateIssue.issueId,
        updateIssue
      );
    }
  };
}