/**
 * Copyright (c) 2023-present Pi Dash Software, Inc. and contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 * See the LICENSE file for details.
 */

import { useState, useRef, useEffect } from "react";
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
import { observer } from "mobx-react";
import { useParams, usePathname } from "next/navigation";
import { Ellipsis } from "lucide-react";
import { Disclosure, Transition } from "@headlessui/react";
// pi dash imports
import {
  EUserPermissions,
  EUserPermissionsLevel,
  PROJECT_TRACKER_ELEMENTS,
  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS,
  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS,
} from "@pi-dash/constants";
import { useTranslation } from "@pi-dash/i18n";
import { PlusIcon, ChevronRightIcon } from "@pi-dash/propel/icons";
import { IconButton } from "@pi-dash/propel/icon-button";
import { TOAST_TYPE, setToast } from "@pi-dash/propel/toast";
import { Tooltip } from "@pi-dash/propel/tooltip";
import { Loader } from "@pi-dash/ui";
import { copyUrlToClipboard, cn, orderJoinedProjects } from "@pi-dash/utils";
// components
import { CreateProjectModal } from "@/components/project/create-project-modal";
import { SidebarNavItem } from "@/components/sidebar/sidebar-navigation";
// hooks
import { useAppTheme } from "@/hooks/store/use-app-theme";
import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useProject } from "@/hooks/store/use-project";
import { useUserPermissions } from "@/hooks/store/user";
import { usePersonalNavigationPreferences, useProjectNavigationPreferences } from "@/hooks/use-navigation-preferences";
// pi dash web imports
import { SidebarItem } from "@/pi-dash-web/components/workspace/sidebar/sidebar-item";
import type { TProject } from "@/pi-dash-web/types";
// local imports
import { SidebarProjectsListItem } from "./projects-list-item";

export const SidebarProjectsList = observer(function SidebarProjectsList() {
  // states
  const [isAllProjectsListOpen, setIsAllProjectsListOpen] = useState(true);
  const [isProjectModalOpen, setIsProjectModalOpen] = useState(false);
  const [isScrolled, setIsScrolled] = useState(false); // scroll animation state
  // refs
  const containerRef = useRef<HTMLDivElement | null>(null);
  // store hooks
  const { t } = useTranslation();
  const { toggleCreateProjectModal } = useCommandPalette();
  const { allowPermissions } = useUserPermissions();
  const { preferences: projectPreferences } = useProjectNavigationPreferences();
  const { preferences: personalPreferences } = usePersonalNavigationPreferences();
  const isDraftsEnabled = personalPreferences.items.drafts?.enabled ?? true;
  const { isExtendedProjectSidebarOpened, toggleExtendedProjectSidebar } = useAppTheme();

  const { loader, getPartialProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject();
  // router params
  const { workspaceSlug } = useParams();
  const pathname = usePathname();

  // auth
  const isAuthorizedUser = allowPermissions(
    [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
    EUserPermissionsLevel.WORKSPACE
  );

  // Compute limited projects for main sidebar
  const displayedProjects = projectPreferences.showLimitedProjects
    ? joinedProjects.slice(0, projectPreferences.limitedProjectsCount)
    : joinedProjects;

  // Check if there are more projects to show
  const hasMoreProjects =
    projectPreferences.showLimitedProjects && joinedProjects.length > projectPreferences.limitedProjectsCount;

  const handleCopyText = async (projectId: string) => {
    try {
      await copyUrlToClipboard(`${workspaceSlug}/projects/${projectId}/issues`);
      setToast({
        type: TOAST_TYPE.SUCCESS,
        title: t("Link copied"),
        message: t("Project link copied to clipboard"),
      });
    } catch {
      setToast({
        type: TOAST_TYPE.ERROR,
        title: t("Error"),
        message: t("Something went wrong"),
      });
    }
  };

  const handleOnProjectDrop = (
    sourceId: string | undefined,
    destinationId: string | undefined,
    shouldDropAtEnd: boolean
  ) => {
    if (!sourceId || !destinationId || !workspaceSlug) return;
    if (sourceId === destinationId) return;

    const joinedProjectsList: TProject[] = [];
    joinedProjects.map((projectId) => {
      const projectDetails = getPartialProjectById(projectId);
      if (projectDetails) joinedProjectsList.push(projectDetails);
    });

    const sourceIndex = joinedProjects.indexOf(sourceId);
    const destinationIndex = shouldDropAtEnd ? joinedProjects.length : joinedProjects.indexOf(destinationId);

    if (joinedProjectsList.length <= 0) return;

    const updatedSortOrder = orderJoinedProjects(sourceIndex, destinationIndex, sourceId, joinedProjectsList);
    if (updatedSortOrder != undefined)
      updateProjectView(workspaceSlug.toString(), sourceId, { sort_order: updatedSortOrder }).catch(() => {
        setToast({
          type: TOAST_TYPE.ERROR,
          title: t("Error"),
          message: t("Something went wrong"),
        });
      });
  };

  /**
   * Implementing scroll animation styles based on the scroll length of the container
   */
  useEffect(() => {
    const handleScroll = () => {
      if (containerRef.current) {
        const scrollTop = containerRef.current.scrollTop;
        setIsScrolled(scrollTop > 0);
      }
    };
    const currentContainerRef = containerRef.current;
    if (currentContainerRef) {
      currentContainerRef.addEventListener("scroll", handleScroll);
    }
    return () => {
      if (currentContainerRef) {
        currentContainerRef.removeEventListener("scroll", handleScroll);
      }
    };
  }, [containerRef]);

  useEffect(() => {
    const element = containerRef.current;

    if (!element) return;

    return combine(
      autoScrollForElements({
        element,
        canScroll: ({ source }) => source?.data?.dragInstanceId === "PROJECTS",
        getAllowedAxis: () => "vertical",
      })
    );
  }, [containerRef]);

  const toggleListDisclosure = (isOpen: boolean) => {
    setIsAllProjectsListOpen(isOpen);
    localStorage.setItem("isAllProjectsListOpen", isOpen.toString());
  };
  // The Projects disclosure also hosts Drafts and Work Items; auto-open it
  // whenever the user lands on any of those routes so the active row is not
  // hidden behind a collapsed disclosure.
  useEffect(() => {
    if (pathname.includes("projects") || pathname.includes("/drafts") || pathname.includes("/workspace-views")) {
      setIsAllProjectsListOpen(true);
      localStorage.setItem("isAllProjectsListOpen", "true");
    }
  }, [pathname]);
  return (
    <>
      {workspaceSlug && (
        <CreateProjectModal
          isOpen={isProjectModalOpen}
          onClose={() => setIsProjectModalOpen(false)}
          setToFavorite={false}
          workspaceSlug={workspaceSlug.toString()}
        />
      )}
      <div
        ref={containerRef}
        className={cn({
          "border-t border-strong": isScrolled,
        })}
      >
        <>
          <Disclosure as="div" className="flex flex-col" defaultOpen={isAllProjectsListOpen}>
            <div className="group flex w-full items-center justify-between rounded-sm px-2 py-1.5 text-placeholder hover:bg-layer-transparent-hover">
              <Disclosure.Button
                as="button"
                type="button"
                className="flex w-full items-center gap-1 text-left text-13 font-semibold whitespace-nowrap text-placeholder"
                onClick={() => toggleListDisclosure(!isAllProjectsListOpen)}
                aria-label={t(
                  isAllProjectsListOpen
                    ? "Close projects menu"
                    : "Open projects menu"
                )}
              >
                <span className="text-13 font-semibold">{t("Projects")}</span>
              </Disclosure.Button>
              <div className="flex items-center gap-1">
                {isAuthorizedUser && (
                  <Tooltip tooltipHeading={t("Create project")} tooltipContent="">
                    <IconButton
                      variant="ghost"
                      size="sm"
                      icon={PlusIcon}
                      onClick={() => {
                        setIsProjectModalOpen(true);
                      }}
                      data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_TOOLTIP}
                      className="hidden text-placeholder group-hover:inline-flex"
                      aria-label={t("Create new project")}
                    />
                  </Tooltip>
                )}
                <IconButton
                  variant="ghost"
                  size="sm"
                  icon={ChevronRightIcon}
                  onClick={() => toggleListDisclosure(!isAllProjectsListOpen)}
                  className="text-placeholder"
                  iconClassName={cn("transition-transform", {
                    "rotate-90": isAllProjectsListOpen,
                  })}
                  aria-label={t(
                    isAllProjectsListOpen
                      ? "Close projects menu"
                      : "Open projects menu"
                  )}
                />
              </div>
            </div>
            <Transition
              show={isAllProjectsListOpen}
              enter="transition duration-100 ease-out"
              enterFrom="transform scale-95 opacity-0"
              enterTo="transform scale-100 opacity-100"
              leave="transition duration-75 ease-out"
              leaveFrom="transform scale-100 opacity-100"
              leaveTo="transform scale-95 opacity-0"
            >
              {loader === "init-loader" && (
                <Loader className="w-full space-y-1.5">
                  {["a", "b", "c", "d"].map((id) => (
                    <Loader.Item key={`loader-${id}`} height="28px" />
                  ))}
                </Loader>
              )}
              {isAllProjectsListOpen && (
                <Disclosure.Panel as="div" className="flex flex-col gap-0.5" static>
                  <>
                    {isDraftsEnabled && WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["drafts"] && (
                      <SidebarItem item={WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["drafts"]} />
                    )}
                    {WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["views"] && (
                      <SidebarItem
                        item={{
                          ...WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["views"],
                          labelTranslationKey: "Work Items",
                          // The base highlight only matches /workspace-views/all-issues/.
                          // Since this row is now labelled "Work Items" (the section,
                          // not a single page) it should stay active on every
                          // /workspace-views/* route.
                          highlight: (path: string) => path.includes("/workspace-views"),
                        }}
                        additionalStaticItems={["views"]}
                      />
                    )}
                    {displayedProjects.map((projectId, index) => (
                      <SidebarProjectsListItem
                        key={projectId}
                        projectId={projectId}
                        handleCopyText={() => handleCopyText(projectId)}
                        projectListType={"JOINED"}
                        disableDrag={false}
                        disableDrop={false}
                        isLastChild={index === displayedProjects.length - 1}
                        handleOnProjectDrop={handleOnProjectDrop}
                      />
                    ))}
                    {hasMoreProjects && (
                      <SidebarNavItem>
                        <button
                          type="button"
                          onClick={() => toggleExtendedProjectSidebar()}
                          className="flex flex-grow items-center gap-1.5 text-13 font-medium text-tertiary"
                          id="extended-project-sidebar-toggle"
                          aria-label={t(
                            isExtendedProjectSidebarOpened
                              ? "Close extended sidebar"
                              : "Open extended sidebar"
                          )}
                        >
                          <Ellipsis className="size-4 flex-shrink-0" />
                          <span>{isExtendedProjectSidebarOpened ? "Hide" : "More"}</span>
                        </button>
                      </SidebarNavItem>
                    )}
                  </>
                </Disclosure.Panel>
              )}
            </Transition>
          </Disclosure>
        </>

        {isAuthorizedUser && joinedProjects?.length === 0 && (
          <button
            type="button"
            data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_BUTTON}
            className="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-13 leading-5 font-medium text-secondary hover:bg-surface-2"
            onClick={() => {
              toggleCreateProjectModal(true);
            }}
          >
            {t("Add project")}
          </button>
        )}
      </div>
    </>
  );
});
