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

import { useState, useMemo, useCallback, useEffect, useLayoutEffect, useRef } from "react";
import { Command } from "cmdk";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { createPortal } from "react-dom";
import { useTranslation } from "@plane/i18n";
// hooks
import { CloseIcon, SearchIcon } from "@plane/propel/icons";
import { cn } from "@plane/utils";
// power-k
import type { TPowerKCommandConfig, TPowerKContext } from "@/components/power-k/core/types";
import { ProjectsAppPowerKCommandsList } from "@/components/power-k/ui/modal/commands-list";
import { PowerKModalFooter } from "@/components/power-k/ui/modal/footer";
import { useIssueDetail } from "@/hooks/store/use-issue-detail";
import { usePowerK } from "@/hooks/store/use-power-k";
import { useUser } from "@/hooks/store/user";
import { useAppRouter } from "@/hooks/use-app-router";
import { useExpandableSearch } from "@/hooks/use-expandable-search";

type TTopNavPowerKProps = {
  variant?: "top-navigation" | "sidebar";
};

export const TopNavPowerK = observer((props: TTopNavPowerKProps) => {
  const { variant = "top-navigation" } = props;
  const { t } = useTranslation();
  // router
  const router = useAppRouter();
  const params = useParams();
  const { projectId: routerProjectId, workItem: workItemIdentifier } = params;

  // states
  const [searchTerm, setSearchTerm] = useState("");
  const [activeCommand, setActiveCommand] = useState<TPowerKCommandConfig | null>(null);
  const [shouldShowContextBasedActions, setShouldShowContextBasedActions] = useState(true);
  const [isWorkspaceLevel, setIsWorkspaceLevel] = useState(false);
  const [sidebarSearchPosition, setSidebarSearchPosition] = useState<{
    left: number;
    top: number;
    width: number;
  } | null>(null);

  const sidebarSearchPortalRef = useRef<HTMLDivElement>(null);
  const sidebarSearchButtonRef = useRef<HTMLButtonElement>(null);

  // store hooks
  const { activeContext, setActivePage, activePage, setTopNavInputRef } = usePowerK();
  const { data: currentUser } = useUser();

  const handleOnClose = useCallback(() => {
    setSearchTerm("");
    setActivePage(null);
    setActiveCommand(null);
  }, [setSearchTerm, setActivePage, setActiveCommand]);

  // expandable search hook
  const {
    isOpen,
    containerRef,
    inputRef,
    handleClose: closePanel,
    handleMouseDown,
    handleFocus,
    openPanel,
  } = useExpandableSearch({
    onClose: handleOnClose,
    additionalRefs: [sidebarSearchPortalRef],
  });

  // derived values
  const {
    issue: { getIssueById, getIssueIdByIdentifier },
  } = useIssueDetail();

  const workItemId = workItemIdentifier ? getIssueIdByIdentifier(workItemIdentifier.toString()) : undefined;
  const workItemDetails = workItemId ? getIssueById(workItemId) : undefined;
  const projectId: string | string[] | undefined | null = routerProjectId ?? workItemDetails?.project_id;

  // Build command context
  const context: TPowerKContext = useMemo(
    () => ({
      currentUserId: currentUser?.id,
      activeCommand,
      activeContext,
      shouldShowContextBasedActions,
      setShouldShowContextBasedActions,
      params: {
        ...params,
        projectId,
      },
      router,
      closePalette: closePanel,
      setActiveCommand,
      setActivePage,
    }),
    [
      currentUser?.id,
      activeCommand,
      activeContext,
      shouldShowContextBasedActions,
      params,
      projectId,
      router,
      setActivePage,
      closePanel,
    ]
  );

  // Register input ref with PowerK store for keyboard shortcut access
  useEffect(() => {
    setTopNavInputRef(inputRef);
    return () => {
      setTopNavInputRef(null);
    };
  }, [setTopNavInputRef]);

  const handleClear = () => {
    setSearchTerm("");
    inputRef.current?.focus();
  };

  const updateSidebarSearchPosition = useCallback(() => {
    if (variant !== "sidebar" || !sidebarSearchButtonRef.current || typeof window === "undefined") return;

    const rect = sidebarSearchButtonRef.current.getBoundingClientRect();
    const width = 320;
    const viewportPadding = 16;
    const left = Math.min(rect.left, window.innerWidth - width - viewportPadding);
    const top = rect.bottom + 10;

    setSidebarSearchPosition({
      left,
      top,
      width,
    });
  }, [variant]);

  useLayoutEffect(() => {
    if (!isOpen || variant !== "sidebar") return;

    updateSidebarSearchPosition();

    const handlePositionUpdate = () => updateSidebarSearchPosition();
    window.addEventListener("resize", handlePositionUpdate);
    window.addEventListener("scroll", handlePositionUpdate, true);

    return () => {
      window.removeEventListener("resize", handlePositionUpdate);
      window.removeEventListener("scroll", handlePositionUpdate, true);
    };
  }, [isOpen, updateSidebarSearchPosition, variant]);

  // Handle command selection
  const handleCommandSelect = useCallback(
    (command: TPowerKCommandConfig) => {
      if (command.type === "action") {
        command.action(context);
        // Always close on command selection
        context.closePalette();
      } else if (command.type === "change-page") {
        context.setActiveCommand(command);
        setActivePage(command.page);
        setSearchTerm("");
      }
    },
    [context, setActivePage]
  );

  // Handle selection page item selection
  const handlePageDataSelection = useCallback(
    (data: unknown) => {
      if (context.activeCommand?.type === "change-page") {
        context.activeCommand.onSelect(data, context);
      }
      // Always close on page data selection
      context.closePalette();
    },
    [context]
  );

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      // Cmd/Ctrl+K closes the search dropdown
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        closePanel();
        return;
      }

      if (e.key === "Escape") {
        e.preventDefault();
        if (searchTerm) {
          setSearchTerm("");
        }
        closePanel();
        return;
      }

      if (e.key === "Backspace" && !searchTerm) {
        if (activePage) {
          e.preventDefault();
          setActivePage(null);
          context.setActiveCommand(null);
        } else if (shouldShowContextBasedActions) {
          // Optional: logic to hide context actions if desired, similar to wrapper
          context.setShouldShowContextBasedActions(false);
        }
        return;
      }

      // Arrow down/up keys to navigate command items
      if ((e.key === "ArrowDown" || e.key === "ArrowUp") && isOpen) {
        e.preventDefault();
        // Get the Command.List element
        const commandList = containerRef.current?.querySelector("[cmdk-list]") as HTMLElement;
        if (commandList) {
          // Create and dispatch a keyboard event on the list to trigger cmdk navigation
          const syntheticEvent = new KeyboardEvent("keydown", {
            key: e.key,
            bubbles: true,
            cancelable: true,
          });
          commandList.dispatchEvent(syntheticEvent);

          // Also try to focus the first/selected item
          if (e.key === "ArrowDown") {
            const firstItem = commandList.querySelector('[cmdk-item]:not([aria-disabled="true"])') as HTMLElement;
            if (firstItem) {
              firstItem.focus();
            }
          }
        }
        return;
      }

      // Enter key to execute selected command
      if (e.key === "Enter" && isOpen) {
        e.preventDefault();
        // Find the currently selected/focused item
        const selectedItem = containerRef.current?.querySelector('[cmdk-item][aria-selected="true"]') as HTMLElement;
        if (selectedItem) {
          // Trigger click on the selected item
          selectedItem.click();
        }
        return;
      }
    },
    [searchTerm, activePage, context, shouldShowContextBasedActions, setActivePage, closePanel]
  );

  const searchCommandContent = (
    <Command
      filter={(i18nValue: string, search: string) => {
        if (i18nValue === "no-results") return 1;
        if (i18nValue.toLowerCase().includes(search.toLowerCase())) return 1;
        return 0;
      }}
      shouldFilter={searchTerm.length > 0}
      className="flex h-full w-full flex-col"
    >
      <Command.Input value={searchTerm} hidden />
      <Command.List className="vertical-scrollbar scrollbar-sm max-h-[60vh] overflow-y-auto px-2 pb-4 outline-none">
        <ProjectsAppPowerKCommandsList
          activePage={activePage}
          context={context}
          handleCommandSelect={handleCommandSelect}
          handlePageDataSelection={handlePageDataSelection}
          isWorkspaceLevel={isWorkspaceLevel}
          searchTerm={searchTerm}
          setSearchTerm={setSearchTerm}
          handleSearchMenuClose={() => closePanel()}
        />
      </Command.List>
      <PowerKModalFooter
        isWorkspaceLevel={isWorkspaceLevel}
        projectId={context.params.projectId?.toString()}
        onWorkspaceLevelChange={setIsWorkspaceLevel}
      />
    </Command>
  );

  return (
    <div ref={containerRef} className="relative">
      {variant === "top-navigation" ? (
        <div
          className={cn("relative z-30 flex w-[364px] items-center transition-all duration-300 ease-in-out", {
            "w-[554px]": isOpen,
          })}
        >
          <div
            className={cn(
              "flex h-7 w-full items-center rounded-lg border border-subtle-1 bg-layer-2 p-2 transition-colors duration-200",
              {
                "bg-layer-1": isOpen,
              }
            )}
            onClick={() => inputRef.current?.focus()}
            role="button"
          >
            <SearchIcon className="mr-2 size-3.5 shrink-0 text-placeholder" />
            <input
              ref={inputRef}
              type="text"
              value={searchTerm}
              onChange={(e) => {
                setSearchTerm(e.target.value);
                if (!isOpen) openPanel();
              }}
              onMouseDown={handleMouseDown}
              onFocus={handleFocus}
              onKeyDown={handleKeyDown}
              placeholder={t("power_k.search_menu.quick_command_placeholder")}
              className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
            />
            {searchTerm && (
              <button type="button" onClick={handleClear} className="ml-2 shrink-0">
                <CloseIcon className="size-3.5 text-placeholder hover:text-primary" />
              </button>
            )}
          </div>
        </div>
      ) : (
        <div className="relative z-30 h-8 w-8">
          <button
            ref={sidebarSearchButtonRef}
            type="button"
            className={cn(
              "absolute left-0 top-0 z-[161] flex size-8 items-center justify-center rounded-full border-0 bg-white/[0.04] text-placeholder backdrop-blur-[18px] outline-none transition-all hover:bg-white/[0.07]"
            )}
            onClick={() => {
              if (isOpen) {
                closePanel();
                return;
              }
              openPanel();
              requestAnimationFrame(() => inputRef.current?.focus());
            }}
            aria-label="Поиск"
          >
            <SearchIcon className="size-3.5 shrink-0 text-placeholder" />
          </button>
        </div>
      )}
      {variant === "top-navigation" && (
        <div
          className={cn(
            "absolute z-20 flex flex-col overflow-hidden px-0 transition-all duration-300 ease-in-out",
            {
              "max-h-[80vh] w-[574px] opacity-100": isOpen,
              "h-0 w-0 opacity-0": !isOpen,
              "-top-[6px] left-1/2 -translate-x-1/2 rounded-md border border-subtle bg-surface-1 shadow-lg pt-10":
                true,
            }
          )}
        >
          {isOpen && searchCommandContent}
        </div>
      )}
      {variant === "sidebar" &&
        isOpen &&
        sidebarSearchPosition &&
        typeof document !== "undefined" &&
        createPortal(
          <div
            ref={sidebarSearchPortalRef}
            className="fixed z-[160]"
            style={{
              left: `${sidebarSearchPosition.left}px`,
              top: `${sidebarSearchPosition.top}px`,
              width: `${sidebarSearchPosition.width}px`,
            }}
          >
            <div className="relative">
              <div className="nodedc-glass-modal nodedc-glass-popup-surface flex h-8 w-full items-center overflow-hidden rounded-full pl-11 pr-3">
                <input
                  ref={inputRef}
                  type="text"
                  value={searchTerm}
                  onChange={(e) => {
                    setSearchTerm(e.target.value);
                    if (!isOpen) openPanel();
                  }}
                  onMouseDown={handleMouseDown}
                onFocus={handleFocus}
                onKeyDown={handleKeyDown}
                placeholder={t("power_k.search_menu.quick_command_placeholder")}
                className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
                autoFocus
              />
                {searchTerm && (
                  <button type="button" onClick={handleClear} className="ml-2 shrink-0">
                    <CloseIcon className="size-3.5 text-placeholder hover:text-primary" />
                  </button>
                )}
              </div>
              <div className="nodedc-glass-modal nodedc-glass-popup-surface absolute top-full left-0 mt-3 flex max-h-[70vh] w-full flex-col overflow-hidden rounded-[1.5rem] pt-3">
                <div className="px-4 pb-2">
                  <div className="text-[13px] font-medium text-secondary">
                    {t("power_k.search_menu.quick_access_title")}
                  </div>
                </div>
                {searchCommandContent}
              </div>
            </div>
          </div>,
          document.body
        )}
    </div>
  );
});
