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

import { useAssistant } from '@grafana/assistant';
import { FeatureState, type GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { Grid, Modal, useStyles2, Text, FeatureBadge } from '@grafana/ui';
import { getModKey } from 'app/core/utils/browser';

export interface HelpModalProps {
  onDismiss: () => void;
}

export const HelpModal = ({ onDismiss }: HelpModalProps): JSX.Element => {
  const styles = useStyles2(getStyles);
  const shortcuts = useShortcuts();
  return (
    <Modal title={t('help-modal.title', 'Shortcuts')} isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}>
      <Grid columns={{ xs: 1, sm: 2 }} gap={3} tabIndex={0}>
        {Object.values(shortcuts).map(({ category, shortcuts }) => (
          <section key={category}>
            <table className={styles.table}>
              <caption>
                <Text element="p" variant="h5">
                  {category}
                </Text>
              </caption>
              <thead className="sr-only">
                <tr>
                  <th>
                    <Trans i18nKey="help-modal.column-headers.keys">Keys</Trans>
                  </th>
                  <th>
                    <Trans i18nKey="help-modal.column-headers.description">Description</Trans>
                  </th>
                </tr>
              </thead>
              <tbody>
                {shortcuts.map(({ keys, description, isNew }) => (
                  <tr key={keys.join()}>
                    <td className={styles.keys}>
                      {keys.map((key) => (
                        <Key key={key}>{key}</Key>
                      ))}
                    </td>
                    <td>
                      <div className={styles.descriptionWrapper}>
                        <Text variant="bodySmall" element="p">
                          {description}
                        </Text>
                        {isNew && <FeatureBadge featureState={FeatureState.new} />}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </section>
        ))}
      </Grid>
    </Modal>
  );
};

export const useShortcuts = () => {
  const { isAvailable: assistantAvailable } = useAssistant();
  const modKey = useMemo(() => getModKey(), []);

  return useMemo(() => {
    const globalShortcuts = [
      {
        keys: ['g', 'h'],
        description: t('help-modal.shortcuts-description.go-to-home-dashboard', 'Go to Home Dashboard'),
      },
      {
        keys: ['g', 'd'],
        description: t('help-modal.shortcuts-description.go-to-dashboards', 'Go to Dashboards'),
      },
      { keys: ['g', 'e'], description: t('help-modal.shortcuts-description.go-to-explore', 'Go to Explore') },
      { keys: ['g', 'p'], description: t('help-modal.shortcuts-description.go-to-profile', 'Go to Profile') },
      { keys: ['g', 'a'], description: t('help-modal.shortcuts-description.open-alerting', 'Go to Alerting') },
      { keys: [`${modKey} + k`], description: t('help-modal.shortcuts-description.open-search', 'Open search') },
      {
        keys: ['esc'],
        description: t('help-modal.shortcuts-description.exit-edit/setting-views', 'Exit edit/setting views'),
      },
      {
        keys: ['?'],
        description: t('help-modal.shortcuts-description.show-all-shortcuts', 'Show all keyboard shortcuts'),
      },
      { keys: ['c', 't'], description: t('help-modal.shortcuts-description.change-theme', 'Change theme') },
    ];

    // Add assistant shortcut only if assistant is available
    if (assistantAvailable) {
      globalShortcuts.push({
        keys: [`${modKey} + .`],
        description: t('help-modal.shortcuts-description.open-assistant', 'Open Assistant'),
      });
    }

    return [
      {
        category: t('help-modal.shortcuts-category.global', 'Global'),
        shortcuts: globalShortcuts,
      },
      {
        category: t('help-modal.shortcuts-category.time-range', 'Time range'),
        shortcuts: [
          ...(config.featureToggles.newTimeRangeZoomShortcuts
            ? [
                {
                  keys: ['t', '+'],
                  description: t('help-modal.shortcuts-description.zoom-in-time-range', 'Zoom in time range'),
                  isNew: true,
                },
                {
                  keys: ['t', '-'],
                  description: t('help-modal.shortcuts-description.zoom-out-time-range', 'Zoom out time range'),
                  isNew: true,
                },
              ]
            : [
                {
                  keys: ['t', 'z'],
                  description: t('help-modal.shortcuts-description.zoom-out-time-range', 'Zoom out time range'),
                },
              ]),
          {
            keys: ['t', '←'],
            description: t('help-modal.shortcuts-description.move-time-range-back', 'Move time range back'),
          },
          {
            keys: ['t', '→'],
            description: t('help-modal.shortcuts-description.move-time-range-forward', 'Move time range forward'),
          },
          {
            keys: ['t', 'a'],
            description: t(
              'help-modal.shortcuts-description.make-time-range-permanent',
              'Make time range absolute/permanent'
            ),
          },
          {
            keys: ['t', 'c'],
            description: t('help-modal.shortcuts-description.copy-time-range', 'Copy time range'),
          },
          {
            keys: ['t', 'v'],
            description: t('help-modal.shortcuts-description.paste-time-range', 'Paste time range'),
          },
        ],
      },
      {
        category: t('help-modal.shortcuts-category.dashboard', 'Dashboard'),
        shortcuts: [
          {
            keys: [`${modKey} + s`],
            description: t('help-modal.shortcuts-description.save-dashboard', 'Save dashboard'),
          },
          {
            keys: ['d', 'r'],
            description: t('help-modal.shortcuts-description.refresh-all-panels', 'Refresh all panels'),
          },
          {
            keys: ['d', 's'],
            description: t('help-modal.shortcuts-description.dashboard-settings', 'Dashboard settings'),
          },
          {
            keys: ['d', 'v'],
            description: t('help-modal.shortcuts-description.toggle-active-mode', 'Toggle in-active / view mode'),
          },
          {
            keys: ['d', 'k'],
            description: t('help-modal.shortcuts-description.toggle-kiosk', 'Toggle kiosk mode (hides top nav)'),
          },
          {
            keys: ['d', '⇧ + e'],
            description: t('help-modal.shortcuts-description.expand-all-rows', 'Expand all rows'),
          },
          {
            keys: ['d', '⇧ + c'],
            description: t('help-modal.shortcuts-description.collapse-all-rows', 'Collapse all rows'),
          },
          {
            keys: ['d', 'a'],
            description: t(
              'help-modal.shortcuts-description.toggle-auto-fit',
              'Toggle auto fit panels (experimental feature)'
            ),
          },
          {
            keys: [`${modKey} + o`],
            description: t('help-modal.shortcuts-description.toggle-graph-crosshair', 'Toggle shared graph crosshair'),
          },
          {
            keys: ['d', 'l'],
            description: t('help-modal.shortcuts-description.toggle-all-panel-legends', 'Toggle all panel legends'),
          },
          {
            keys: ['d', 'x'],
            description: t('help-modal.shortcuts-description.toggle-exemplars', 'Toggle exemplars in all panel'),
          },
        ],
      },
      {
        category: t('help-modal.shortcuts-category.focused-panel', 'Focused panel'),
        shortcuts: [
          {
            keys: ['e'],
            description: t('help-modal.shortcuts-description.toggle-panel-edit', 'Toggle panel edit view'),
          },
          {
            keys: ['v'],
            description: t('help-modal.shortcuts-description.toggle-panel-fullscreen', 'Toggle panel fullscreen view'),
          },
          {
            keys: ['p', 'u'],
            description: t('help-modal.shortcuts-description.open-share-link-drawer', 'Share panel link'),
          },
          {
            keys: ['p', 'e'],
            description: t('help-modal.shortcuts-description.open-share-embed-drawer', 'Share panel embed'),
          },
          {
            keys: ['p', 's'],
            description: t('help-modal.shortcuts-description.open-shared-modal', 'Share panel snapshot'),
          },
          {
            keys: ['p', 'x'],
            description: t('help-modal.shortcuts-description.explore-panel', 'Explore panel'),
          },
          {
            keys: ['i'],
            description: t('help-modal.shortcuts-description.inspect-panel', 'Inspect panel'),
          },
          { keys: ['p', 'd'], description: t('help-modal.shortcuts-description.duplicate-panel', 'Duplicate Panel') },
          { keys: ['p', 'r'], description: t('help-modal.shortcuts-description.remove-panel', 'Remove Panel') },
          {
            keys: ['p', 'l'],
            description: t('help-modal.shortcuts-description.toggle-panel-legend', 'Toggle panel legend'),
          },
        ],
      },
    ];
  }, [modKey, assistantAvailable]);
};

interface KeyProps {
  children: string;
}

const Key = ({ children }: KeyProps) => {
  const styles = useStyles2(getStyles);
  const displayText = useMemo(() => replaceCustomKeyNames(children), [children]);
  const displayElement = <span dangerouslySetInnerHTML={{ __html: displayText }}></span>;
  return (
    <kbd className={styles.shortcutTableKey}>
      <Text variant="code">{displayElement}</Text>
    </kbd>
  );
};

function replaceCustomKeyNames(key: string) {
  let displayName;
  let srName;

  if (key.includes('ctrl')) {
    displayName = 'ctrl';
    srName = 'Control';
  } else if (key.includes('esc')) {
    displayName = 'esc';
    srName = 'Escape';
  } else {
    return key;
  }

  return key.replace(
    displayName,
    `<span class="sr-only">${srName}</span><span aria-hidden="true" role="none">${displayName}</span>`
  );
}

function getStyles(theme: GrafanaTheme2) {
  return {
    table: css({
      borderCollapse: 'separate',
      borderSpacing: theme.spacing(2),
      '& caption': {
        captionSide: 'top',
      },
    }),
    keys: css({
      textAlign: 'end',
      whiteSpace: 'nowrap',
      minWidth: 83, // To match column widths with the widest
    }),
    descriptionWrapper: css({
      display: 'flex',
      alignItems: 'center',
      gap: theme.spacing(0.75),
      flexWrap: 'nowrap',
    }),
    shortcutTableKey: css({
      display: 'inline-block',
      textAlign: 'center',
      marginRight: theme.spacing(0.5),
      padding: '3px 5px',
      lineHeight: '10px',
      verticalAlign: 'middle',
      border: `solid 1px ${theme.colors.border.medium}`,
      borderRadius: theme.shape.radius.default,
      color: theme.colors.text.primary,
      backgroundColor: theme.colors.background.secondary,
    }),
  };
}
