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

import type { CodeBlockControlsProps } from '@redocly/theme/components/CodeBlock/CodeBlockControls';

import { CodeBlock } from '@redocly/theme/components/CodeBlock/CodeBlock';

import { JsonValue } from './helpers';

export type JsonProps = {
  title?: CodeBlockControlsProps['title'];
  data: any;
  className?: string;
  expandLevel: number;
  startLineNumber?: number;
  onCopyClick?: () => void;
};

function JsonComponent({
  data,
  expandLevel = 1,
  className,
  onCopyClick,
  title,
}: JsonProps): JSX.Element {
  const showFoldingButtons =
    data && Object.values(data).some((value) => typeof value === 'object' && value !== null);

  const [expandAllSignal, setExpandAllSignal] = React.useState<boolean | undefined>(undefined);

  const expandAll = () => {
    setExpandAllSignal(true);
    setTimeout(() => {
      setExpandAllSignal(undefined);
    });
  };

  const collapseAll = () => {
    setExpandAllSignal(false);
    setTimeout(() => {
      setExpandAllSignal(undefined);
    });
  };

  const source = JSON.stringify(data, null, 2);

  return (
    <JsonViewerWrap
      data-testid="json-viewer"
      data-component-name="JsonViewer/JsonViewer"
      className={className}
    >
      <CodeBlock
        header={{
          title,
          className: 'code-block-header',
          controls: {
            copy: { data, onClick: onCopyClick, handleOutside: true },
            expand: showFoldingButtons ? { onClick: expandAll } : undefined,
            collapse: showFoldingButtons ? { onClick: collapseAll } : undefined,
          },
        }}
        source={source}
      >
        <FoldingWrap>
          <JsonValue
            value={data}
            level={0}
            standalone={true}
            expandAllSignal={expandAllSignal}
            defaultExpandLevel={Math.max(1, expandLevel)}
          />
        </FoldingWrap>
      </CodeBlock>
    </JsonViewerWrap>
  );
}

export const JsonViewer = memo<JsonProps>(JsonComponent);

const FoldingWrap = styled.div`
  position: relative;
`;

export const JsonViewerWrap = styled.div`
  display: flex;
  flex-direction: column;
  flex: 1;

  & > div {
    border: none;
    margin: 0;
  }

  pre {
    contain: content;
    overflow-x: auto;
    position: relative;
    border-radius: 0 0 var(--border-radius) var(--border-radius);
  }

  .code-block-header {
    border-bottom: 0;
    padding-right: var(--spacing-sm);
  }
`;
