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 './core/Icon';
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>
  );
});
