import { Action } from '@/action-menu/actions/components/Action';
import { ActionScope } from '@/action-menu/actions/types/ActionScope';
import { ActionType } from '@/action-menu/actions/types/ActionType';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
import { HeadlessFrontComponentAction } from '@/action-menu/actions/display/components/HeadlessFrontComponentAction';
import { useOpenFrontComponentInCommandMenu } from '@/command-menu/hooks/useOpenFrontComponentInCommandMenu';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useMountHeadlessFrontComponent } from '@/front-components/hooks/useMountHeadlessFrontComponent';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type IconComponent, useIcons } from 'twenty-ui/display';

import { COMMAND_MENU_DEFAULT_ICON } from '@/workflow/workflow-trigger/constants/CommandMenuDefaultIcon';
import {
  type CommandMenuItemFieldsFragment,
  CommandMenuItemAvailabilityType,
  FeatureFlagKey,
  useFindManyCommandMenuItemsQuery,
} from '~/generated-metadata/graphql';

type CommandMenuItemWithFrontComponent = CommandMenuItemFieldsFragment & {
  frontComponentId: string;
};

type BuildActionFromItemParams = {
  item: CommandMenuItemWithFrontComponent;
  scope: ActionScope;
  index: number;
  isPinned: boolean;
  getIcon: ReturnType<typeof useIcons>['getIcon'];
  openFrontComponentInCommandMenu: (params: {
    frontComponentId: string;
    pageTitle: string;
    pageIcon: IconComponent;
  }) => void;
  mountHeadlessFrontComponent: (frontComponentId: string) => void;
};

const buildActionFromItem = ({
  item,
  scope,
  index,
  isPinned,
  getIcon,
  openFrontComponentInCommandMenu,
  mountHeadlessFrontComponent,
}: BuildActionFromItemParams) => {
  const displayLabel = item.label;

  const Icon = getIcon(item.icon, COMMAND_MENU_DEFAULT_ICON);

  const isHeadless = item.frontComponent?.isHeadless === true;

  const handleClick = () => {
    if (isHeadless) {
      mountHeadlessFrontComponent(item.frontComponentId);
    } else {
      openFrontComponentInCommandMenu({
        frontComponentId: item.frontComponentId,
        pageTitle: displayLabel,
        pageIcon: Icon,
      });
    }
  };

  return {
    type: ActionType.FrontComponent,
    key: `command-menu-item-front-component-${item.id}`,
    scope,
    label: displayLabel,
    shortLabel: displayLabel,
    position: index,
    isPinned,
    Icon,
    shouldBeRegistered: () => true,
    component: isHeadless ? (
      <HeadlessFrontComponentAction
        frontComponentId={item.frontComponentId}
        onClick={handleClick}
      />
    ) : (
      <Action onClick={handleClick} />
    ),
  };
};

export const useCommandMenuItemFrontComponentActions = () => {
  const { getIcon } = useIcons();
  const { openFrontComponentInCommandMenu } =
    useOpenFrontComponentInCommandMenu();
  const mountHeadlessFrontComponent = useMountHeadlessFrontComponent();

  const isPageInEditMode = useRecoilComponentValueV2(
    contextStoreIsPageInEditModeComponentState,
  );

  const { actionMenuType } = useContext(ActionMenuContext);

  const currentObjectMetadataItemId = useRecoilComponentValueV2(
    contextStoreCurrentObjectMetadataItemIdComponentState,
  );

  const targetedRecordsRule = useRecoilComponentValueV2(
    contextStoreTargetedRecordsRuleComponentState,
  );

  const isCommandMenuItemEnabled = useIsFeatureEnabled(
    FeatureFlagKey.IS_COMMAND_MENU_ITEM_ENABLED,
  );

  const { data } = useFindManyCommandMenuItemsQuery({
    skip:
      !isCommandMenuItemEnabled ||
      (actionMenuType !== 'command-menu' &&
        actionMenuType !== 'command-menu-show-page-action-menu-dropdown'),
  });

  const frontComponentItems =
    data?.commandMenuItems?.filter(
      (item): item is CommandMenuItemWithFrontComponent =>
        isDefined(item.frontComponentId),
    ) ?? [];

  const selectedRecordCount =
    targetedRecordsRule.mode === 'selection'
      ? targetedRecordsRule.selectedRecordIds.length
      : 0;

  const objectMatches = (item: CommandMenuItemWithFrontComponent) =>
    !isDefined(item.availabilityObjectMetadataId) ||
    item.availabilityObjectMetadataId === currentObjectMetadataItemId;

  const globalItems = frontComponentItems.filter(
    (item) => item.availabilityType === CommandMenuItemAvailabilityType.GLOBAL,
  );

  const recordScopedItems = frontComponentItems.filter((item) => {
    if (!objectMatches(item)) return false;
    if (item.availabilityType === CommandMenuItemAvailabilityType.SINGLE_RECORD)
      return selectedRecordCount === 1;
    if (item.availabilityType === CommandMenuItemAvailabilityType.BULK_RECORDS)
      return selectedRecordCount >= 1;
    return false;
  });

  const globalActions = globalItems.map((item, index) =>
    buildActionFromItem({
      item,
      scope: ActionScope.Global,
      index,
      isPinned: !isPageInEditMode && item.isPinned,
      getIcon,
      openFrontComponentInCommandMenu,
      mountHeadlessFrontComponent,
    }),
  );

  const recordScopedActions = recordScopedItems.map((item, index) =>
    buildActionFromItem({
      item,
      scope: ActionScope.RecordSelection,
      index,
      isPinned: !isPageInEditMode && item.isPinned,
      getIcon,
      openFrontComponentInCommandMenu,
      mountHeadlessFrontComponent,
    }),
  );

  return [...globalActions, ...recordScopedActions];
};
