import { open } from "@tauri-apps/plugin-dialog";
import { revealItemInDir } from "@tauri-apps/plugin-opener";
import { getModel, settingsAtom, workspacesAtom } from "@yaakapp-internal/models";
import classNames from "classnames";
import { useAtomValue } from "jotai";
import { memo, useCallback, useMemo } from "react";
import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
import { openWorkspaceSettings } from "../commands/openWorkspaceSettings";
import { switchWorkspace } from "../commands/switchWorkspace";
import {
  activeWorkspaceAtom,
  activeWorkspaceIdAtom,
  activeWorkspaceMetaAtom,
} from "../hooks/useActiveWorkspace";
import { useCreateWorkspace } from "../hooks/useCreateWorkspace";
import { useDeleteSendHistory } from "../hooks/useDeleteSendHistory";
import { useWorkspaceActions } from "../hooks/useWorkspaceActions";
import { showDialog } from "../lib/dialog";
import { jotaiStore } from "../lib/jotai";
import { revealInFinderText } from "../lib/reveal";
import { CloneGitRepositoryDialog } from "./CloneGitRepositoryDialog";
import type { ButtonProps } from "./core/Button";
import { Button } from "./core/Button";
import type { DropdownItem } from "./core/Dropdown";
import { Icon } from "@yaakapp-internal/ui";
import type { RadioDropdownItem } from "./core/RadioDropdown";
import { RadioDropdown } from "./core/RadioDropdown";
import { SwitchWorkspaceDialog } from "./SwitchWorkspaceDialog";

type Props = Pick<ButtonProps, "className" | "justify" | "forDropdown" | "leftSlot">;

export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
  className,
  ...buttonProps
}: Props) {
  const workspaces = useAtomValue(workspacesAtom);
  const workspace = useAtomValue(activeWorkspaceAtom);
  const createWorkspace = useCreateWorkspace();
  const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom);
  const { mutate: deleteSendHistory } = useDeleteSendHistory();
  const workspaceActions = useWorkspaceActions();

  const openCloneGitRepositoryDialog = useCallback(() => {
    showDialog({
      id: "clone-git-repository",
      size: "md",
      title: "Clone Git Repository",
      render: ({ hide }) => <CloneGitRepositoryDialog hide={hide} />,
    });
  }, []);

  const { workspaceItems, itemsAfter, itemsBefore } = useMemo<{
    workspaceItems: RadioDropdownItem[];
    itemsAfter: DropdownItem[];
    itemsBefore: DropdownItem[];
  }>(() => {
    const workspaceItems: RadioDropdownItem[] = workspaces.map((w) => ({
      key: w.id,
      label: w.name,
      value: w.id,
      leftSlot: w.id === workspace?.id ? <Icon icon="check" /> : <Icon icon="empty" />,
    }));

    const itemsBefore: DropdownItem[] = [
      {
        label: "New Workspace",
        leftSlot: <Icon icon="plus" />,
        submenu: [
          {
            label: "Create Empty",
            leftSlot: <Icon icon="plus_circle" />,
            onSelect: createWorkspace,
          },
          {
            label: "Open Folder",
            leftSlot: <Icon icon="folder_open" />,
            onSelect: async () => {
              const dir = await open({
                title: "Select Workspace Directory",
                directory: true,
                multiple: false,
              });

              if (dir == null) return;
              openWorkspaceFromSyncDir.mutate(dir);
            },
          },
          {
            label: "Clone Git Repository",
            leftSlot: <Icon icon="hard_drive_download" />,
            onSelect: openCloneGitRepositoryDialog,
          },
        ],
      },
    ];
    const itemsAfter: DropdownItem[] = [
      ...workspaceActions.map((a) => ({
        label: a.label,
        leftSlot: <Icon icon={a.icon ?? "empty"} />,
        onSelect: async () => {
          if (workspace != null) await a.call(workspace);
        },
      })),
      ...(workspaceActions.length > 0 ? [{ type: "separator" as const }] : []),
      {
        label: "Workspace Settings",
        leftSlot: <Icon icon="settings" />,
        hotKeyAction: "workspace_settings.show",
        onSelect: openWorkspaceSettings,
      },
      {
        label: revealInFinderText,
        hidden: workspaceMeta == null || workspaceMeta.settingSyncDir == null,
        leftSlot: <Icon icon="folder_symlink" />,
        onSelect: async () => {
          if (workspaceMeta?.settingSyncDir == null) return;
          await revealItemInDir(workspaceMeta.settingSyncDir);
        },
      },
      {
        label: "Clear Send History",
        color: "warning",
        leftSlot: <Icon icon="history" />,
        onSelect: deleteSendHistory,
      },
    ];

    return { workspaceItems, itemsAfter, itemsBefore };
  }, [
    workspaces,
    workspaceMeta,
    deleteSendHistory,
    createWorkspace,
    openCloneGitRepositoryDialog,
    workspace?.id,
    workspace,
    workspaceActions.map,
    workspaceActions.length,
  ]);

  const handleSwitchWorkspace = useCallback(async (workspaceId: string | null) => {
    if (workspaceId == null) return;

    const settings = jotaiStore.get(settingsAtom);
    const activeWorkspaceId = jotaiStore.get(activeWorkspaceIdAtom);
    if (workspaceId === activeWorkspaceId) {
      // Always open a new window if the selected one is already active
      switchWorkspace.mutate({ workspaceId, inNewWindow: true });
      return;
    }
    if (typeof settings.openWorkspaceNewWindow === "boolean") {
      switchWorkspace.mutate({ workspaceId, inNewWindow: settings.openWorkspaceNewWindow });
      return;
    }

    const workspace = getModel("workspace", workspaceId);
    if (workspace == null) return;

    showDialog({
      id: "switch-workspace",
      size: "sm",
      title: "Switch Workspace",
      render: ({ hide }) => <SwitchWorkspaceDialog workspace={workspace} hide={hide} />,
    });
  }, []);

  return (
    <RadioDropdown
      items={workspaceItems}
      itemsAfter={itemsAfter}
      itemsBefore={itemsBefore}
      onChange={handleSwitchWorkspace}
      value={workspace?.id ?? null}
    >
      <Button
        size="sm"
        className={classNames(
          className,
          "text px-2! truncate",
          workspace === null && "italic opacity-disabled",
        )}
        {...buttonProps}
      >
        {workspace?.name ?? "Workspace"}
      </Button>
    </RadioDropdown>
  );
});
