import React, { useState } from 'react';
import styled from 'styled-components';

import type { JSX } from 'react';

import { concatClassNames } from '@redocly/theme/core/utils';
import { useColorSwitcher } from '@redocly/theme/core/hooks';
import { useThemeHooks } from '@redocly/theme/core/hooks';
import { SvgViewer } from '@redocly/theme/components/SvgViewer/SvgViewer';

type DiagramProps = {
  id?: string;
  diagramHtml: string;
  diagramHtmlDark?: string;
  diagramError?: string;
  diagramType: string;
  align?: 'left' | 'center' | 'right';
  width?: string;
  'data-source'?: string;
  'data-hash'?: string;
  className?: string;
};

export function Diagram({
  id,
  diagramHtml,
  diagramHtmlDark,
  diagramError,
  diagramType,
  align,
  width,
  'data-source': dataSource,
  'data-hash': dataHash,
  className,
}: DiagramProps): JSX.Element {
  const { useTranslate } = useThemeHooks();
  const { translate } = useTranslate();
  const { activeColorMode } = useColorSwitcher();
  const [isOpen, setIsOpen] = useState(false);
  const activeDiagramHtml =
    activeColorMode === 'dark' ? diagramHtmlDark || diagramHtml : diagramHtml;

  const open = () => setIsOpen(true);
  const close = () => setIsOpen(false);
  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      open();
    }
  };

  if (diagramError) {
    return (
      <ErrorWrapper id={id} className={concatClassNames('diagram-error', className)}>
        {diagramError}
      </ErrorWrapper>
    );
  }

  return (
    <>
      <Wrapper
        id={id}
        $width={width}
        className={concatClassNames(`diagram-wrapper diagram-${diagramType}`, className)}
        data-component-name="Markdoc/Diagram/Diagram"
        data-diagram-type={diagramType}
        data-source={dataSource}
        data-hash={dataHash}
        onClick={open}
        onKeyDown={handleKeyDown}
        role="button"
        tabIndex={0}
        aria-label={translate('diagram.openFullscreen', 'Click to open diagram in fullscreen')}
      >
        <DiagramVariant
          $align={align}
          $colorMode="light"
          className={`diagram-variant diagram-variant-light diagram-${diagramType}`}
          dangerouslySetInnerHTML={{ __html: diagramHtml }}
        />
        {diagramHtmlDark ? (
          <DiagramVariant
            $align={align}
            $colorMode="dark"
            className={`diagram-variant diagram-variant-dark diagram-${diagramType}`}
            dangerouslySetInnerHTML={{ __html: diagramHtmlDark }}
          />
        ) : null}
      </Wrapper>
      <SvgViewer
        isOpen={isOpen}
        onClose={close}
        labels={{
          zoomIn: translate('diagram.zoomIn', 'Zoom in'),
          zoomOut: translate('diagram.zoomOut', 'Zoom out'),
          fitToView: translate('diagram.reset', 'Fit to view'),
          close: translate('diagram.close', 'Close'),
          dialogLabel: translate('diagram.viewer', 'Diagram viewer'),
        }}
      >
        <ViewerContent
          className={`diagram-viewer-content diagram-${diagramType}`}
          dangerouslySetInnerHTML={{ __html: activeDiagramHtml }}
        />
      </SvgViewer>
    </>
  );
}

const Wrapper = styled.div<{ $width?: string }>`
  background-color: var(--diagram-bg-color);
  border-radius: var(--diagram-border-radius);
  cursor: pointer;
  transition: box-shadow 0.2s ease;

  &:hover,
  &:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--border-color-input-focus);
  }

  svg {
    max-width: 100%;
    display: block;
    ${({ $width }) => ($width ? `width: ${$width} !important;     height: auto !important;` : '')}
  }
`;

const DiagramVariant = styled.div<{ $colorMode: 'light' | 'dark'; $align?: DiagramProps['align'] }>`
  display: flex;
  justify-content: ${({ $align }) => {
    switch ($align) {
      case 'center':
        return 'center';
      case 'right':
        return 'flex-end';
      default:
        return 'flex-start';
    }
  }};
  width: 100%;
  ${({ $colorMode }) =>
    $colorMode === 'dark'
      ? `
    html:not(.dark) && {
      display: none;
    }
  `
      : `
    html.dark && {
      display: none;
    }
  `}
`;

const ErrorWrapper = styled.div`
  border: 1px solid var(--color-error-border);
  border-radius: var(--diagram-border-radius);
  background: var(--color-error-bg);
  color: var(--color-error-text);
  font-size: var(--font-size-sm);
  padding: var(--spacing-sm);
  white-space: pre-wrap;
  word-break: break-word;
`;

const ViewerContent = styled.div`
  svg {
    display: block;
    max-width: none !important;
  }
`;
