import React, { JSX, useMemo } from 'react';
import { Background, ColorMode, Controls, ReactFlow } from '@xyflow/react';
import styled from 'styled-components';

import { BffCatalogEntity } from '@redocly/theme/core/types';
import { useColorSwitcher, useThemeHooks } from '@redocly/theme/core/hooks';
import { useGraph } from '@redocly/theme/core/hooks';
import { CatalogEntityRelationsNode } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsNode';
import { CatalogEntityRelationsEdge } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsEdge';
import { xyflow } from '@redocly/theme/core/styles';
import { CatalogPageDescription } from '@redocly/theme/components/Catalog/CatalogPageDescription';
import { GraphCustomEdgeType, GraphCustomNodeType } from '@redocly/theme/core/constants/catalog';

export type CatalogEntityRelationsGraphProps = {
  entity: BffCatalogEntity;
};

const commonReactFlowConfig = {
  fitView: true,
  proOptions: {
    hideAttribution: true,
  },
  style: {
    border:
      'var(--catalog-card-border-width) var(--catalog-card-border-style) var(--catalog-card-border-color)',
    borderRadius: 'var(--catalog-card-border-radius, 8px)',
  },
};

export function CatalogEntityRelationsGraph({
  entity,
}: CatalogEntityRelationsGraphProps): JSX.Element {
  const { useFetchCatalogEntitiesRelations } = useThemeHooks();
  const { activeColorMode } = useColorSwitcher();

  const combinedFilter = useMemo(() => {
    if (entity.version && entity.revision) {
      const versionFilter = `version:"${entity.version}"`;
      const revisionFilter = `revision:"${entity.revision}"`;
      return `${versionFilter} AND ${revisionFilter}`;
    }

    return undefined;
  }, [entity.version, entity.revision]);

  const { items: allRelations } = useFetchCatalogEntitiesRelations({
    entityKey: entity.key,
    filter: combinedFilter,
  });

  const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useGraph({
    entity,
    relations: allRelations ?? [],
  });

  const nodeTypes = useMemo(
    () => ({ [GraphCustomNodeType.CatalogEntity]: CatalogEntityRelationsNode }),
    [],
  );
  const edgeTypes = useMemo(
    () => ({ [GraphCustomEdgeType.CatalogEdge]: CatalogEntityRelationsEdge }),
    [],
  );

  const reactFlowConfig = allRelations.length
    ? {
        key: entity.id,
        nodes,
        edges,
        nodeTypes,
        edgeTypes,
        onNodesChange,
        onEdgesChange,
        onConnect,
        colorMode: activeColorMode as ColorMode,
        ...commonReactFlowConfig,
      }
    : {
        ...commonReactFlowConfig,
      };

  return (
    <>
      <CatalogPageDescription
        title={entity.title}
        description={entity.summary ?? ''}
        tag={entity.key}
      />
      <GraphWrapper>
        <ReactFlow {...reactFlowConfig}>
          <Background bgColor="var(--catalog-card-bg-color)" />
          <Controls />
        </ReactFlow>
      </GraphWrapper>
    </>
  );
}

const GraphWrapper = styled.div`
  height: 700px;
  width: 100%;
  ${xyflow}
`;
