import React from 'react';
import styled from 'styled-components';
import * as Sampler from 'openapi-sampler';

import type { CatalogEntityConfig } from '@redocly/config';
import type { BffCatalogEntity, BffCatalogRelatedEntity } from '@redocly/theme/core/types';

import { useCatalogEntityDetails, useThemeHooks } from '@redocly/theme/core/hooks';
import { useCatalogEntitySchema } from '@redocly/theme/core/hooks';
import { JsonViewer } from '@redocly/theme/components/JsonViewer/JsonViewer';
import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';

export type CatalogEntitySchemaProps = {
  entity: BffCatalogEntity;
  relatedEntity: BffCatalogRelatedEntity | null;
  catalogConfig: CatalogEntityConfig;
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
  RedocSchema: React.ComponentType<any>;
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
  StoreProvider: React.ComponentType<any>;
  GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>;
};

export function CatalogEntitySchema({
  entity,
  relatedEntity,
  catalogConfig,
  RedocSchema,
  StoreProvider,
  GraphqlTypeRenderer,
}: CatalogEntitySchemaProps) {
  const { useTranslate, useTelemetry } = useThemeHooks();
  const telemetry = useTelemetry();
  const { translate } = useTranslate();
  const { definition, parsedSchema, rawSchema } = useCatalogEntitySchema({ entity, relatedEntity });
  const isGraphql = entity.metadata?.specType === 'graphql';
  const graphqlSDL = entity?.metadata?.sdl;
  const { getEntityDetailsLink } = useCatalogEntityDetails({
    catalogConfig,
  });

  return (
    <MetadataWrapper data-component-name="Catalog/CatalogEntity/CatalogEntitySchema">
      <HeaderWrapper>
        <Heading>{translate('catalog.entity.schema.title')}</Heading>
        {!isGraphql && (
          <CopyButton
            data={rawSchema}
            buttonText="Copy Schema"
            type="compound"
            variant="secondary"
            iconPosition="right"
            size="medium"
            onCopyClick={() =>
              telemetry.sendCatalogEntitiesCopyDataSchemaClickedMessage([
                {
                  id: entity.id,
                  object: 'catalog_entity',
                  uri: getEntityDetailsLink(entity),
                },
              ])
            }
          ></CopyButton>
        )}
      </HeaderWrapper>
      <SplitViewWrapper>
        <SchemaContentWrapper>
          {isGraphql && graphqlSDL && GraphqlTypeRenderer ? (
            <GraphqlTypeRenderer sdl={graphqlSDL} typeName={entity.title} />
          ) : (
            <StoreProvider definition={definition}>
              <RedocSchema schema={parsedSchema} />
            </StoreProvider>
          )}
        </SchemaContentWrapper>

        {!isGraphql && (
          <SchemaSampleWrapper>
            <JsonViewer data={Sampler.sample({ ...parsedSchema })} expandLevel={3} />
          </SchemaSampleWrapper>
        )}
      </SplitViewWrapper>
    </MetadataWrapper>
  );
}

const MetadataWrapper = styled.div`
  display: flex;
  flex-direction: column;
  border-radius: var(--border-radius);
  background-color: var(--catalog-metadata-bg-color);
  margin-bottom: var(--spacing-lg);
`;

const SchemaContentWrapper = styled.div`
  flex: 1;
  & > div > div {
    padding-left: 0;
    padding-top: 0;
  }
`;

const HeaderWrapper = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm);
`;

const Heading = styled.h2`
  font-size: var(--catalog-metadata-heading-size);
  line-height: var(--line-height-lg);
  margin: 0;
`;

const SplitViewWrapper = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--spacing-base);
`;

const SchemaSampleWrapper = styled.div`
  flex: 1;
  position: sticky;
  top: calc(var(--navbar-height) + var(--banner-height) + var(--spacing-md));
  align-self: flex-start;
  padding-top: var(--spacing-sm);
`;
