import { css } from '@emotion/css';
import type { JSX } from 'react';

import { type GrafanaTheme2 } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Box, ClipboardButton, Stack, Text, Tooltip, useStyles2 } from '@grafana/ui';

type DetailTextProps = {
  id: string;
  label: string;
  value: string | JSX.Element | null;
  /** Should the value be displayed using monospace font family? */
  monospace?: boolean;
  /** Optional string to display in a tooltip on hover of the value */
  tooltipValue?: string;
} & ConditionalProps;

type ConditionalProps =
  // Require either both copy props or neither
  | {
      /** Should we show a button for copying the value to clipboard? */
      showCopyButton: boolean;
      /**
       * Value to use for copying to clipboard, when enabled.
       * Needed as the value could be an element
       */
      copyValue: string;
    }
  | { showCopyButton?: never; copyValue?: never };

const Value = ({ children }: { children: React.ReactNode }) => {
  const styles = useStyles2(getStyles);
  return <span className={styles.value}>{children}</span>;
};

const getStyles = (_theme: GrafanaTheme2) => ({
  value: css({
    overflowWrap: 'break-word',
    wordBreak: 'break-word',
  }),
});

export const DetailText = ({
  id,
  label,
  value,
  monospace,
  showCopyButton,
  copyValue,
  tooltipValue,
}: DetailTextProps) => {
  const copyToClipboardLabel = t('alerting.copy-to-clipboard', 'Copy "{{label}}" to clipboard', { label });
  return (
    <Box>
      <Stack direction="column" gap={0}>
        <Text color="secondary" id={id}>
          {label}
        </Text>
        <Text aria-labelledby={id} color="primary" variant={monospace ? 'code' : 'body'}>
          {tooltipValue ? (
            <Tooltip content={tooltipValue}>
              <span>
                <Value>{value}</Value>
              </span>
            </Tooltip>
          ) : (
            <Value>{value}</Value>
          )}
          {showCopyButton && (
            <ClipboardButton
              aria-label={copyToClipboardLabel}
              fill="text"
              variant="secondary"
              icon="copy"
              size="sm"
              getText={() => copyValue}
            />
          )}
        </Text>
      </Stack>
    </Box>
  );
};
