import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { noop } from '../../../helpers/utils';
import {
  ConfirmDialog,
  ConfirmationConfig,
  ConfirmationMode,
  useConfirmationDelay,
} from '../../ConfirmDialog';
import { IconName, Icons } from '../../Icons';
import { ImgElement } from '../../VisualElements';
import {
  PageHeaderActionProps,
  PageHeaderActionType,
  PageHeaderJsActionProps,
  PageHeaderNavigationActionProps,
} from './PageHeaderAction.model';
import classes from './PageHeaderAction.scss';

/**
 * Simple Confirm message
 * @example
 * <SimpleConfirmDialog />
 */
const SimpleConfirmDialog: React.FC<{
  onConfirmOpen: ConfirmationConfig['onConfirmOpen'];
  data: { mode: ConfirmationMode };
}> = ({ onConfirmOpen, data }) => {
  useEffect(() => {
    onConfirmOpen && onConfirmOpen(true, data);
    return () => {
      onConfirmOpen && onConfirmOpen(false, data);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return <span data-test-id="confirm">Click again to confirm</span>;
};

/**
 * Used to create actions for the PageHeader component.
 * To generate anchor tag provide `path` property
 * To generate HTML element with event handler provide `onClick` property
 * (and optionally `confirmationMode`, `confirmationConfig`)
 * @example
 * // Action with JS clickHandler
 * <PageHeaderAction label={'Action Label'} onClick={clickHandler} />
 *
 * // Action with anchor tag
 * <PageHeaderAction label={'Action Label'} path={'/action-path'} />
 */
export const PageHeaderAction: React.FC<PageHeaderActionProps> = (props) =>
  isPageHeaderNavigationAction(props) ? (
    <PageHeaderNavigationAction {...props} />
  ) : (
    <PageHeaderJSAction {...props} />
  );

/**
 * Page header action with JS handler and optional confirmation mode
 */
const PageHeaderJSAction: React.FC<PageHeaderJsActionProps> = ({
  label,
  actionType = PageHeaderActionType.Context,
  icon,
  imgAlt,
  confirmationMode = 'None',
  confirmationConfig = {},
  disabled,
  className,
  onClick = noop,
  tag,
}) => {
  const [confirmation, setConfirmation] = useState<boolean>(false);
  const [referenceElement, setReferenceElement] = useState<HTMLElement>();
  const { isMouseOver, setIsMouseOver } = useConfirmationDelay({
    confirmationMode,
    confirmation,
    setConfirmation,
  });

  const { title, body, cancelButtonText, confirmButtonText, onConfirmOpen } =
    confirmationConfig;

  const onClickHandler = (
    event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
  ): void => {
    event.preventDefault();

    switch (confirmationMode) {
      case 'Simple':
        !confirmation
          ? setConfirmation(true)
          : (onClick(), setConfirmation(false));
        break;
      case 'Advanced':
        setConfirmation(true);
        break;
      default:
        onClick();
        setConfirmation(false);
        break;
    }
  };

  const onConfirmOpenHandler = (
    isOpen: boolean,
    data: { mode: ConfirmationMode },
  ): void => {
    if (confirmationMode === 'Advanced' && onConfirmOpen !== undefined) {
      onConfirmOpen(isOpen, data);
    }
  };

  return (
    <>
      <button
        className={clsx(
          classes.container,
          {
            [classes.context]: actionType === PageHeaderActionType.Context,
            [classes.active]: actionType === PageHeaderActionType.Active,
            [classes.highlight]: actionType === PageHeaderActionType.Hightlight,
            [classes.hasConfirm]: confirmation,
          },
          'page-header-action-container',
          className,
        )} // Show different bg-color when confirmation is displayed
        ref={setReferenceElement as React.LegacyRef<HTMLButtonElement>}
        onClick={onClickHandler}
        onMouseEnter={() => setIsMouseOver(true)}
        onMouseLeave={() => setIsMouseOver(false)}
        onMouseOver={() => {
          // Needed in cases where the mouse enters the component after another confirmation dialog was dismissed
          if (!isMouseOver) {
            setIsMouseOver(true);
          }
        }}
        disabled={disabled}
        data-test-id="action"
      >
        <div className={classes.icon}>
          {!confirmation &&
            (typeof icon === 'string' ? (
              <ImgElement
                src={icon}
                {...(imgAlt
                  ? { alt: imgAlt ?? `${label} icon` }
                  : { decorative: true })}
              />
            ) : (
              <Icons icon={icon} className={classes.pageHeaderActionsIcons} />
            ))}
        </div>
        <div className={classes.label}>
          {confirmation && confirmationMode === 'Simple' ? (
            <SimpleConfirmDialog
              onConfirmOpen={onConfirmOpen}
              data={{ mode: 'Simple' }}
            />
          ) : (
            <span data-test-id="label">{label}</span>
          )}
        </div>
        {tag && <div className={classes.tag}>{tag}</div>}
      </button>
      {confirmation && confirmationMode === 'Advanced' && (
        <ConfirmDialog
          referenceElement={referenceElement}
          title={title}
          cancelButtonText={cancelButtonText}
          confirmButtonText={confirmButtonText}
          onCancel={() => setConfirmation(false)}
          onConfirm={() => {
            onClick();
            setConfirmation(false);
          }}
          onConfirmOpen={(isOpen) =>
            onConfirmOpenHandler(isOpen, { mode: 'Advanced' })
          }
        >
          {body}
        </ConfirmDialog>
      )}
    </>
  );
};

/**
 * Page header action rendered as anchor tag
 */
const PageHeaderNavigationAction: React.FC<PageHeaderNavigationActionProps> = ({
  className,
  icon,
  imgAlt,
  label,
  openInNewTab = false,
  path,
  tag,
}) => {
  const headerIcon = icon ? icon : openInNewTab ? IconName.External : undefined;

  return (
    <Link
      className={clsx(
        classes.container,
        'page-header-action-container',
        className,
      )}
      data-test-id="action"
      to={path}
      target={openInNewTab ? '_blank' : undefined}
    >
      <div className={classes.icon}>
        {typeof headerIcon === 'string' ? (
          <ImgElement
            src={headerIcon}
            {...(imgAlt
              ? { alt: imgAlt ?? `${label} icon` }
              : { decorative: true })}
          />
        ) : (
          <Icons icon={headerIcon} className={classes.pageHeaderActionsIcons} />
        )}
      </div>
      <div className={classes.label}>
        <span data-test-id="label">{label}</span>
      </div>
      {tag && <div className={classes.tag}>{tag}</div>}
    </Link>
  );
};

/**
 * Determines whether an action data object is a PageHeaderNavigationActionProps object.
 * @param {PageHeaderActionProps} action - The action data object to check.
 * @returns {boolean} - Whether the action data object is a PageHeaderNavigationActionProps object.
 */
export function isPageHeaderNavigationAction(
  action: PageHeaderActionProps,
): action is PageHeaderNavigationActionProps {
  return 'path' in action && !!action.path;
}

/**
 * Determines whether an action data object is a PageHeaderJsActionProps object.
 * @param {PageHeaderActionProps} action - The action data object to check.
 * @returns {boolean} - Whether the action data object is a PageHeaderJsActionProps object.
 */
export function isPageHeaderJsAction(
  action: PageHeaderActionProps,
): action is PageHeaderJsActionProps {
  return 'onClick' in action && !!action.onClick;
}
