import React, { useState, useEffect, useCallback, useMemo } from 'react';
import styled from 'styled-components';
import { useLocation } from 'react-router-dom';

import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
import { useThemeHooks } from '@redocly/theme/core/hooks';
import { MenuContainer } from '@redocly/theme/components/Menu/MenuContainer';
import { transformRevisionsToVersionHistory } from '@redocly/theme/core/utils';
import { DEFAULT_LOCALE_PLACEHOLDER } from '@redocly/theme/core/constants';
import { CatalogEntityVersionItem } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem';
import { RecentlyViewedIcon } from '@redocly/theme/icons/RecentlyViewedIcon/RecentlyViewedIcon';

export type CatalogHistorySidebarProps = {
  entityKey: string;
  revision?: string;
  version?: string | null;
  className?: string;
};

export function CatalogEntityHistorySidebar({
  entityKey,
  revision,
  version,
  className,
}: CatalogHistorySidebarProps): React.ReactElement | null {
  const [isOpen, setIsOpen] = useState(false);
  const location = useLocation();
  const basePath = location.pathname;
  const { useTranslate, useFetchCatalogEntityRevisions, useL10nConfig } = useThemeHooks();
  const { translate } = useTranslate();
  const { currentLocale } = useL10nConfig();

  const { items: revisions } = useFetchCatalogEntityRevisions({ entityKey });

  const normalizedLocale =
    currentLocale && currentLocale !== DEFAULT_LOCALE_PLACEHOLDER ? currentLocale : 'en-US';

  const versionHistoryItems = useMemo(
    () =>
      transformRevisionsToVersionHistory({
        revisions,
        currentRevisionDate: revision,
        currentVersion: version,
        locale: normalizedLocale,
      }),
    [revisions, revision, version, normalizedLocale],
  );
  const activeRevisionLabel = useMemo(() => {
    const itemWithActiveRevision = versionHistoryItems.find((item) =>
      item.revisions?.some((revision) => revision.isActive),
    );
    const activeRevision = itemWithActiveRevision?.revisions?.find((revision) => revision.isActive);
    return activeRevision?.name;
  }, [versionHistoryItems]);

  const [expandedVersions, setExpandedVersions] = useState<Set<string>>(new Set());

  useEffect(() => {
    setExpandedVersions(
      new Set(versionHistoryItems.filter((item) => item.isExpanded).map((item) => item.version)),
    );
  }, [versionHistoryItems]);

  const handleOpenSidebar = useCallback(() => {
    setIsOpen(true);
  }, []);

  useEffect(() => {
    window.addEventListener('portal:sidebar:open-version-history', handleOpenSidebar);

    return () => {
      window.removeEventListener('portal:sidebar:open-version-history', handleOpenSidebar);
    };
  }, [handleOpenSidebar]);

  const handleClose = (): void => {
    window.dispatchEvent(
      new CustomEvent('portal:sidebar:close-version-history', {
        detail: { version, revision: activeRevisionLabel },
      }),
    );
    setIsOpen(false);
  };

  const toggleVersion = (version: string): void => {
    setExpandedVersions((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(version)) {
        newSet.delete(version);
      } else {
        newSet.add(version);
      }
      return newSet;
    });
  };

  if (!isOpen) {
    return null;
  }

  return (
    <SidebarOverlay className={className} data-component-name="Catalog/CatalogHistorySidebar">
      <SidebarHeader>
        <HeaderWrapper>
          <HistoryIcon />
          <HeaderTitle>{translate('catalog.history.sidebar.title', 'Version history')}</HeaderTitle>
        </HeaderWrapper>
        <CloseButton
          onClick={handleClose}
          aria-label={translate('catalog.history.sidebar.close', 'Close version history')}
        >
          <CloseIcon size="20px" color="--catalog-history-sidebar-close-icon-color" />
        </CloseButton>
      </SidebarHeader>

      <MenuContainer growContent>
        <VersionList>
          {versionHistoryItems.map((group) => (
            <CatalogEntityVersionItem
              key={group.version}
              group={group}
              basePath={basePath}
              isExpanded={expandedVersions.has(group.version)}
              onToggle={toggleVersion}
            />
          ))}
        </VersionList>
      </MenuContainer>
    </SidebarOverlay>
  );
}

const SidebarOverlay = styled.div`
  position: fixed;
  top: calc(var(--navbar-height) + var(--banner-height));
  left: 0;
  width: var(--sidebar-width);
  height: calc(100vh - var(--navbar-height) - var(--banner-height));
  background-color: var(--catalog-history-sidebar-bg-color);
  border-right: 1px solid var(--catalog-history-sidebar-border-color);
  display: flex;
  flex-direction: column;
  z-index: calc(var(--z-index-raised) - 1);
  overflow: hidden;
`;

const SidebarHeader = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--catalog-history-sidebar-header-padding);
  border-bottom: 1px solid var(--catalog-history-sidebar-border-color);
  flex-shrink: 0;
`;

const HeaderTitle = styled.h2`
  margin: 0;
  font-family: var(--catalog-history-sidebar-header-font-family);
  font-size: var(--catalog-history-sidebar-header-font-size);
  font-weight: var(--catalog-history-sidebar-header-font-weight);
  line-height: var(--catalog-history-sidebar-header-line-height);
  letter-spacing: var(--catalog-history-sidebar-header-letter-spacing);
  color: var(--catalog-history-sidebar-header-color);
`;

const CloseButton = styled.button`
  all: unset;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--catalog-history-sidebar-close-button-size);
  height: var(--catalog-history-sidebar-close-button-size);
  cursor: pointer;
  border-radius: var(--catalog-history-sidebar-close-button-border-radius);
  transition: background-color 0.2s ease;

  &:hover {
    background-color: var(--catalog-history-sidebar-close-button-bg-color-hover);
  }
`;

const VersionList = styled.ul`
  list-style: none;
  margin: 0;
  padding: var(--catalog-history-sidebar-content-padding);
  margin-top: var(--catalog-history-sidebar-content-margin-top);
`;

const HistoryIcon = styled(RecentlyViewedIcon)`
  width: var(--catalog-history-icon-size);
  height: var(--catalog-history-icon-size);
  flex-shrink: 0;
`;

const HeaderWrapper = styled.div`
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
`;
