import React, { memo } from 'react';

import type { JSX } from 'react';
import type { TooltipProps } from '@redocly/theme/core/types';
import type { ButtonProps } from '@redocly/theme/components/Button/Button';

import { ClipboardService } from '@redocly/theme/core/utils';
import { useThemeHooks, useControl } from '@redocly/theme/core/hooks';
import { Button } from '@redocly/theme/components/Button/Button';
import { CopyIcon } from '@redocly/theme/icons/CopyIcon/CopyIcon';
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';

export type CopyButtonProps = {
  data: unknown;
  type?: 'icon' | 'text' | 'compound';
  toasterPlacement?: TooltipProps['placement'];
  toasterText?: string;
  toasterDuration?: number;
  buttonText?: string;
  onCopyClick?: (e: React.MouseEvent<HTMLElement>) => void;
  dataTestId?: string;
  className?: string;

  // Generic button props
  variant?: ButtonProps['variant'];
  size?: ButtonProps['size'];
  disabled?: ButtonProps['disabled'];
  fullWidth?: ButtonProps['fullWidth'];
  tone?: ButtonProps['tone'];
  extraClass?: ButtonProps['extraClass'];
  iconPosition?: ButtonProps['iconPosition'];
};

function CopyButtonComponent({
  data,
  type = 'icon',
  toasterPlacement = 'top',
  toasterText,
  toasterDuration,
  buttonText,
  onCopyClick,
  dataTestId = 'copy-button',
  className,
  variant = 'text',
  size = 'small',
  disabled,
  fullWidth,
  tone,
  extraClass,
  iconPosition,
}: CopyButtonProps): JSX.Element {
  const { useTranslate } = useThemeHooks();
  const tooltip = useControl();
  const { translate } = useTranslate();

  const showTooltip = (duration: number = 1500): void => {
    tooltip.handleOpen();

    setTimeout(() => {
      tooltip.handleClose();
    }, duration);
  };

  const copy = (e: React.MouseEvent<HTMLElement>, duration?: number): void => {
    const content = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
    ClipboardService.copyCustom(content);
    showTooltip(duration);
    onCopyClick?.(e);
  };

  return (
    <Tooltip
      className={`copy-button ${className ? className : ''}`}
      tip={translate('codeSnippet.copy.buttonText', toasterText || 'Copied!')}
      isOpen={tooltip.isOpened}
      placement={toasterPlacement}
      width="fit-content"
    >
      <Button
        data-component-name="Buttons/CopyButton"
        onClick={(e) => copy(e, toasterDuration)}
        data-testid={dataTestId}
        icon={type === 'icon' || type === 'compound' ? <CopyIcon /> : undefined}
        size={size}
        variant={variant}
        disabled={disabled}
        fullWidth={fullWidth}
        tone={tone}
        extraClass={extraClass}
        iconPosition={iconPosition}
        aria-label="Copy"
      >
        {(type === 'text' || type === 'compound') &&
          (buttonText || translate('codeSnippet.copy.toasterText', 'Copy'))}
      </Button>
    </Tooltip>
  );
}

export const CopyButton = memo<CopyButtonProps>(CopyButtonComponent);
