import clsx from 'clsx';
import React, { useCallback, useEffect, useState } from 'react';
import { noop } from '../../../helpers/utils';
import { useExpand } from '../../../hooks/useExpand/useExpand';
import { uuid } from '../../../utils/GenerateId';
import { ConfirmationMode } from '../../ConfirmDialog';
import { IconName } from '../../Icons';
import {
  PageHeaderAction,
  isPageHeaderJsAction,
} from '../PageHeaderAction/PageHeaderAction';
import {
  PageHeaderActionProps,
  PageHeaderActionType,
} from '../PageHeaderAction/PageHeaderAction.model';
import classes from './PageHeaderActionsGroup.scss';
import { PageHeaderActionsGroupContext } from './PageHeaderActionsGroupsContext';

export interface PageHeaderActionsGroupProps {
  /** Array of Actions to be rendered (default: []) */
  actions: PageHeaderActionProps[];
  /** Whether group is disabled (default: false) */
  disabled?: boolean;
  /** Whether actions in the group are disabled or not (default: false)*/
  groupActionsDisabled?: boolean;
  /** CSS Class name for additional styles */
  className?: string;
  /** The label of the action. */
  label: string;
  /** Optional built in icon. This prop also accepts an img src. */
  icon?: IconName | string;
  /** Whether group actions are shown by default. (default: false) */
  openActionsGroupOnStart?: boolean;
  /** The number of actions that can be displayed in the group. (default: actions.length) */
  availableActionSpace?: number;
  /**
   * Callback to emit when Group Actions is toggled
   * The expanded state is supplied as an argument
   */
  onActionsGroupToggled?: (expanded: boolean) => Promise<void>;
}

/**
 * Used to perform group operations from the PageHeader component.
 * @example
 * <PageHeaderActionsGroup>
 *   <PageHeaderAction action={action} onActionsGroupToggled={onActionsGroupToggledHandler} />
 * </PageHeaderActionsGroup>
 */
export const PageHeaderActionsGroup: React.FC<PageHeaderActionsGroupProps> = ({
  actions = [],
  openActionsGroupOnStart = false,
  label,
  icon,
  onActionsGroupToggled = noop,
  groupActionsDisabled = false,
  disabled = false,
  availableActionSpace = actions.length,
  className = '',
}) => {
  const [uniqueId] = useState<string>(uuid());
  const { isExpanded, toggleExpanded, collapse } = useExpand(
    openActionsGroupOnStart,
  );

  const { registerCollapse, collapseAll } = React.useContext(
    PageHeaderActionsGroupContext,
  );

  const customCollapse = useCallback(
    () => Promise.resolve(onActionsGroupToggled(false)).then(() => collapse()),
    [collapse, onActionsGroupToggled],
  );

  useEffect(() => {
    registerCollapse(customCollapse, uniqueId);
  }, [customCollapse, registerCollapse, uniqueId]);

  const {
    isExpanded: isMoreExpanded,
    expand: moreExpanded,
    collapse: moreCollapse,
    toggleExpanded: toggleMoreExpanded,
  } = useExpand();

  const [isMouseOverMore, setIsMouseOverMore] = useState<boolean>(false);
  const [isConfirmOpen, setIsConfirmOpen] = useState<Record<string, boolean>>(
    {},
  );

  const onConfirmToggled = (
    isOpen: boolean,
    data: { id: string; mode: ConfirmationMode },
  ): void => {
    setIsConfirmOpen((prevState) => {
      return { ...prevState, [data.id]: isOpen };
    });
  };

  useEffect(() => {
    const hasConfirm: boolean = Object.values(isConfirmOpen).includes(true);

    // open drop down
    if (isMouseOverMore) {
      moreExpanded();
      // close drop down if no confirmation is active
    } else if (!isMouseOverMore && !hasConfirm) {
      moreCollapse();
      // keep the drop down open if confirmation is active
    } else if (!isMouseOverMore && hasConfirm) {
      return;
    }
  }, [isConfirmOpen, isMouseOverMore, moreCollapse, moreExpanded]);

  const showMore = actions.length > availableActionSpace && actions.length > 1;
  const visibleActions = showMore
    ? Math.max(availableActionSpace, 1)
    : actions.length;

  const actionsSlice = showMore
    ? Math.max(availableActionSpace - 1, 0)
    : actions.length;

  return (
    <div
      className={clsx(
        classes.container,
        'page-header-group-action-container',
        className,
      )}
      onMouseLeave={() => setIsMouseOverMore(false)}
    >
      <PageHeaderAction
        label={label}
        actionType={
          isExpanded
            ? PageHeaderActionType.Active
            : PageHeaderActionType.Context
        }
        icon={icon}
        onClick={async () => {
          try {
            if (!isExpanded) {
              await collapseAll(uniqueId);
            }
            await onActionsGroupToggled(!isExpanded);
            toggleExpanded();
          } catch (_) {
            // Abort the action if an error occurs
            return;
          }
        }}
        disabled={disabled}
      />
      <div
        style={{
          maxWidth: isExpanded ? `${visibleActions * 121}px` : `0px`,
          opacity: isExpanded ? 1 : 0,
        }}
        className={classes.actions}
      >
        {actions.slice(0, actionsSlice).map((action, idx) =>
          isPageHeaderJsAction(action) ? (
            <PageHeaderAction
              key={idx}
              {...action}
              disabled={groupActionsDisabled}
              confirmationConfig={{
                ...action.confirmationConfig,
                onConfirmOpen: (isOpen: boolean, args: unknown) => {
                  onConfirmToggled(
                    isOpen,
                    args as { id: string; mode: ConfirmationMode },
                  );
                  action.confirmationConfig?.onConfirmOpen?.(isOpen, args);
                },
              }}
            />
          ) : (
            <PageHeaderAction key={idx} {...action} />
          ),
        )}
        {showMore && (
          <div onMouseEnter={() => setIsMouseOverMore(true)}>
            <PageHeaderAction
              label="More"
              icon={IconName.Ellipsis}
              actionType={
                isMoreExpanded
                  ? PageHeaderActionType.Active
                  : PageHeaderActionType.Context
              }
              onClick={() => toggleMoreExpanded()}
            />
          </div>
        )}
      </div>
      {isMoreExpanded && (
        <div className={clsx(classes.dropDownList)}>
          {actions.slice(actionsSlice).map((action, idx) =>
            isPageHeaderJsAction(action) ? (
              <PageHeaderAction
                key={idx}
                {...action}
                tag={undefined}
                label={
                  action.tag ? `${action.label} (${action.tag})` : action.label
                }
                disabled={groupActionsDisabled}
                onClick={() => {
                  action.onClick();
                  moreCollapse();
                  setIsMouseOverMore(false);
                }}
                className={clsx(classes.dropDown)}
                confirmationConfig={{
                  ...action.confirmationConfig,
                  onConfirmOpen: (isOpen, args) => {
                    onConfirmToggled(
                      isOpen,
                      args as { id: string; mode: ConfirmationMode },
                    );
                    action.confirmationConfig?.onConfirmOpen?.(isOpen, args);
                  },
                }}
              />
            ) : (
              <PageHeaderAction key={idx} {...action} />
            ),
          )}
        </div>
      )}
    </div>
  );
};
