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

import type { CatalogEntityConfig } from '@redocly/config';
import type { ResolvedFilter } from '@redocly/theme/core/types';

import {
  BffCatalogEntityList,
  CatalogSwitcherItem,
  CatalogViewMode,
} from '@redocly/theme/core/types';
import {
  breakpoints,
  customCatalogOptionsCasing,
  isFromToSelectedOptions,
} from '@redocly/theme/core/utils';
import { useThemeHooks } from '@redocly/theme/core/hooks';
import { H3 } from '@redocly/theme/components/Typography/H3';
import { CatalogFilterContent } from '@redocly/theme/components/Catalog/CatalogFilter/CatalogFilterContent';
import { Sidebar, SidebarHeader } from '@redocly/theme/components/Sidebar/Sidebar';
import { CatalogSelector } from '@redocly/theme/components/Catalog/CatalogSelector';
import { SidebarActions } from '@redocly/theme/components/SidebarActions/SidebarActions';
import { CounterTag } from '@redocly/theme/components/Tags/CounterTag';
import { FilterInput } from '@redocly/theme/components/Filter/FilterInput';
import { CatalogEntities } from '@redocly/theme/components/Catalog/CatalogEntities';
import { CatalogMobileTopBar } from '@redocly/theme/components/Catalog/CatalogMobileTopBar/CatalogMobileTopBar';
import { CatalogMobileFiltersPanelOverlay } from '@redocly/theme/components/Catalog/CatalogMobileFiltersPanel/CatalogMobileFiltersPanelOverlay';
import { CatalogActionsRow } from '@redocly/theme/components/Catalog/CatalogActionsRow';

type CatalogFiltersWithCounts = Record<string, { value: string; count: number }[]>;

function getActiveFiltersCount(filters: ResolvedFilter[], filterTerm: string): number {
  const filterOptionsCount = filters.reduce((sum, filter) => {
    if (filter.selectedOptions instanceof Set) return sum + filter.selectedOptions.size;
    if (
      isFromToSelectedOptions(filter.selectedOptions) &&
      filter.selectedOptions.from &&
      filter.selectedOptions.to
    ) {
      return sum + 1;
    }
    return sum;
  }, 0);
  const searchTermCount = filterTerm.trim() ? 1 : 0;
  return searchTermCount + filterOptionsCount;
}

export type CatalogProps = {
  catalogConfig: CatalogEntityConfig;
  filters?: CatalogFiltersWithCounts;
  entitiesTypes: string[];
  initialEntitiesList?: BffCatalogEntityList;
  catalogSwitcherItems: CatalogSwitcherItem[];
  initialViewMode?: CatalogViewMode;
};

export function Catalog(props: CatalogProps): JSX.Element {
  const {
    catalogConfig,
    filters: serverFilters,
    entitiesTypes,
    initialEntitiesList,
    catalogSwitcherItems,
    initialViewMode,
  } = props;

  const { useTranslate, useCatalog } = useThemeHooks();

  const { translate } = useTranslate();

  const {
    filters,
    searchQuery,
    setSearchQuery,
    filterQuery,
    sortOption,
    setSortOption,
    handleSortClick,
    isColumnSorted,
    viewMode,
    setViewMode,
    entitiesCounter,
    setEntitiesCounter,
    onChangeViewClick,
    onChangeCollapseSidebarClick,
    layout,
    collapsedSidebar,
  } = useCatalog({
    config: catalogConfig,
    entitiesCounterInitial: initialEntitiesList?.page.total || 0,
    serverFilters,
    initialViewMode,
  });

  const [mobileFiltersPanelOpen, setMobileFiltersPanelOpen] = useState(false);
  const activeFiltersCount = useMemo(
    () => getActiveFiltersCount(filters, searchQuery),
    [filters, searchQuery],
  );

  const filterContent = (
    <CatalogFilterContent
      catalogSelector={
        <CatalogSelector
          catalogSwitcherItems={catalogSwitcherItems}
          onChange={() => {
            setSearchQuery('');
            setSortOption(null);
          }}
        />
      }
      filters={filters}
      filterTerm={searchQuery}
      filterValuesCasing={customCatalogOptionsCasing}
      onClear={() => {
        setSearchQuery('');
      }}
      searchInput={
        <FilterInput
          value={searchQuery}
          onChange={(updatedTerm) => setSearchQuery(updatedTerm)}
          dataTestId="catalog-filter-search-input"
        />
      }
    />
  );

  return (
    <>
      <CatalogPageWrapper data-component-name="Catalog/Catalog">
        <FiltersSidebar
          collapsed={collapsedSidebar}
          menu={filterContent}
          footer={
            <SidebarActions
              layout={layout}
              collapsedSidebar={collapsedSidebar}
              isApiDocs={false}
              onChangeViewClick={onChangeViewClick}
              onChangeCollapseSidebarClick={onChangeCollapseSidebarClick}
            />
          }
        />
        <CatalogContentWrapper>
          <CatalogMobileTopBar
            setMobileFiltersPanelOpen={setMobileFiltersPanelOpen}
            activeFiltersCount={activeFiltersCount}
            setSortOption={setSortOption}
            sortOption={sortOption}
            viewMode={viewMode}
            setViewMode={setViewMode}
          />

          {mobileFiltersPanelOpen ? (
            <CatalogMobileFiltersPanelOverlay
              setMobileFiltersPanelOpen={setMobileFiltersPanelOpen}
              filterContent={filterContent}
            />
          ) : null}

          <CatalogContentScrollWrapper>
            <CatalogPageContentWrapper>
              <CatalogTitleWrapper>
                <CatalogTitle data-translation-key={catalogConfig?.titleTranslationKey}>
                  {catalogConfig?.titleTranslationKey
                    ? translate(catalogConfig?.titleTranslationKey)
                    : catalogConfig?.slug}{' '}
                </CatalogTitle>
                <CounterTag borderless>{entitiesCounter}</CounterTag>
              </CatalogTitleWrapper>
              <CatalogDescription data-translation-key={catalogConfig?.descriptionTranslationKey}>
                {translate(catalogConfig?.descriptionTranslationKey)}
              </CatalogDescription>

              <CatalogActionsRow
                searchQuery={searchQuery}
                setSearchQuery={setSearchQuery}
                sortOption={sortOption}
                setSortOption={setSortOption}
                viewMode={viewMode}
                onViewModeChange={setViewMode}
              />

              <CatalogEntities
                catalogConfig={catalogConfig}
                excludedEntities={catalogConfig?.excludes}
                filterQuery={filterQuery}
                entitiesTypes={entitiesTypes}
                sortOption={sortOption}
                searchQuery={searchQuery}
                viewMode={viewMode}
                setEntitiesCounter={setEntitiesCounter}
                initialEntitiesList={initialEntitiesList}
                handleSortClick={handleSortClick}
                isColumnSorted={isColumnSorted}
              />
            </CatalogPageContentWrapper>
          </CatalogContentScrollWrapper>
        </CatalogContentWrapper>
      </CatalogPageWrapper>
    </>
  );
}

const CatalogContentWrapper = styled.div`
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
`;

const CatalogContentScrollWrapper = styled.div`
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
`;

const CatalogPageContentWrapper = styled.main`
  width: var(--catalog-page-content-width);
  margin: var(--catalog-page-content-margin);
  padding: var(--catalog-page-padding);
  max-width: 1072px;

  @media screen and (max-width: ${breakpoints.small}) {
    padding: var(--catalog-page-padding-mobile);
  }
`;

const CatalogTitleWrapper = styled.div`
  display: flex;
  align-items: center;
  color: var(--catalog-title-text-color);
  font-weight: var(--catalog-title-font-weight) !important;
  font-size: var(--catalog-title-font-size);
`;

const CatalogTitle = styled(H3)`
  color: var(--catalog-title-text-color);
  font-weight: var(--catalog-title-font-weight) !important;
  font-size: var(--catalog-title-font-size);
  margin: var(--catalog-title-margin);
  margin-right: var(--catalog-title-spacing-right);
`;

const CatalogDescription = styled.p`
  color: var(--catalog-description-text-color);
  font-weight: var(--catalog-description-font-weight);
  font-size: var(--catalog-description-font-size);
  margin: var(--catalog-description-margin);
  line-height: var(--catalog-description-line-height);
`;

const CatalogPageWrapper = styled.div`
  --sidebar-width: var(--catalog-sidebar-width);

  height: calc(100vh - var(--navbar-height) - var(--banner-height));
  display: flex;
  flex-direction: column;
  overflow: hidden;

  font-weight: var(--catalog-page-wrapper-font-weight);
  color: var(--catalog-page-wrapper-text-color);
  font-size: var(--catalog-page-wrapper-font-size);
  font-family: var(--catalog-page-wrapper-font-family);
  line-height: var(--catalog-page-wrapper-line-height);

  hr {
    border: 0;
    width: var(--catalog-hr-width);
    margin: var(--catalog-hr-margin);
    border-top: var(--catalog-hr-border-width) solid var(--catalog-hr-border-color);
  }
  a:not([role='button']) {
    text-decoration: var(--catalog-link-text-decoration);
    color: var(--catalog-link-color);
    font-weight: var(--catalog-link-font-weight);
  }

  @media screen and (min-width: ${breakpoints.medium}) {
    flex-direction: row;
    padding: 0;
  }
`;

const FiltersSidebar = styled(Sidebar)`
  display: var(--catalog-sidebar-display-mobile);

  @media screen and (max-width: ${breakpoints.medium}) {
    display: none;
  }

  @media screen and (min-width: ${breakpoints.medium}) {
    display: var(--catalog-sidebar-display-desktop);
  }
  --menu-container-padding-top: var(--catalog-sidebar-menu-container-padding-top);

  ${SidebarHeader} {
    border: none;
  }
`;
