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

import type { JSX } from 'react';
import type { SearchItemData } from '@redocly/theme/core/types';

import { HttpTag } from '@redocly/theme/components/Tags/HttpTag';
import { Link } from '@redocly/theme/components/Link/Link';
import { Image } from '@redocly/theme/components/Image/Image';
import { searchHighlight } from '@redocly/theme/components/Search/SearchHighlight';
import { Badge } from '@redocly/theme/components/Badge/Badge';
import { trimText, getOperationColor } from '@redocly/theme/core/utils';
import { ReturnKeyIcon } from '@redocly/theme/icons/ReturnKeyIcon/ReturnKeyIcon';
import { useThemeHooks } from '@redocly/theme/core/hooks';

type ActiveItem<T> = T & { active?: boolean };
export type SearchItemProps = {
  item: ActiveItem<SearchItemData>;
  onClick?: VoidFunction;
  product?: {
    name: string;
    icon?: string;
  };
  className?: string;
  innerRef?: React.ForwardedRef<HTMLAnchorElement>;
};

export function SearchItem({
  onClick,
  item,
  className,
  product,
  innerRef,
}: SearchItemProps): JSX.Element {
  const ref = useRef<HTMLAnchorElement>(null);
  const { useTranslate } = useThemeHooks();
  const { translate } = useTranslate();

  useEffect(() => {
    if (item.active) {
      ref.current?.focus();
    }
  }, [item.active]);

  const { document, highlight } = item;

  const parameter =
    highlight.parameters && highlight.parameters.length ? highlight.parameters[0] : null;
  const shouldShowPath = document.path && document.path?.length > 1;

  const httpColor = getOperationColor({
    isAdditionalOperation: document.isAdditionalOperation,
    httpVerb: document.httpMethod || '',
  });

  return (
    <SearchItemWrapper
      className={className}
      to={document.url}
      onClick={onClick}
      tabIndex={0}
      innerRef={(el: HTMLAnchorElement) => {
        ref.current = el;

        if (!innerRef) return;

        if (typeof innerRef === 'function') {
          innerRef(el);
        } else {
          innerRef.current = el;
        }
      }}
      data-component-name="Search/SearchItem"
    >
      <SearchItemContent>
        <SearchItemHeader>
          {product && (
            <SearchItemProductTag data-testid="search-item-product-tag">
              <Image src={product.icon} />
              {product.name}
            </SearchItemProductTag>
          )}
          {document.httpMethod ? (
            <SearchItemOperation>
              <SearchItemOperationTag color={httpColor}>
                {document.httpMethod.toUpperCase()}
              </SearchItemOperationTag>
              {highlight.httpPath ? searchHighlight(highlight.httpPath) : document.httpPath}
            </SearchItemOperation>
          ) : null}
          <SearchItemTitleWrapper>
            <SearchItemTitle>
              {highlight.title ? searchHighlight(highlight.title) : document.title}
            </SearchItemTitle>
            {document.deprecated ? (
              <SearchItemBadge deprecated>
                {translate('search.searchItem.deprecated', 'Deprecated')}
              </SearchItemBadge>
            ) : null}
            {document.badges
              ? document.badges.map(({ name, color }) => (
                  <SearchItemBadge color={color || 'var(--color-info-base)'} key={name}>
                    {name}
                  </SearchItemBadge>
                ))
              : null}
          </SearchItemTitleWrapper>
          <SearchItemDescription>
            {highlight.text ? searchHighlight(highlight.text) : trimText(document.text)}
          </SearchItemDescription>
        </SearchItemHeader>
        {parameter ? (
          <SearchItemPlace>
            <div>
              {searchHighlight(parameter.place)}
              {` → `}
              {parameter.path?.length ? searchHighlight(parameter.path?.join(' → ')) + ' → ' : ''}
              {searchHighlight(parameter.name)}
            </div>
            <div>{searchHighlight(parameter.description)}</div>
          </SearchItemPlace>
        ) : (
          shouldShowPath && (
            <SearchItemPath>
              {highlight.path && highlight.path.length
                ? searchHighlight(highlight.path.join(' → '))
                : document.path?.join(' → ')}
            </SearchItemPath>
          )
        )}
      </SearchItemContent>
      <ReturnKeyIcon color="var(--search-item-text-color)" />
    </SearchItemWrapper>
  );
}

const SearchItemWrapper = styled(Link)`
  display: flex;
  padding: var(--search-item-padding);
  color: var(--search-item-text-color);
  background-color: var(--search-item-bg-color);
  transition: background-color 0.3s ease;
  text-decoration: none;
  white-space: normal;
  outline: none;
  border-top: 1px solid var(--search-item-border-color);
  border-bottom: 1px solid var(--search-item-border-color);

  ${ReturnKeyIcon} {
    align-self: center;
    opacity: 0;
  }

  &:hover,
  &:focus {
    color: var(--search-item-text-color-hover);
    background-color: var(--search-item-bg-color-hover);

    ${ReturnKeyIcon} {
      opacity: 1;
    }
  }

  &:focus {
    border-top: 1px solid var(--search-item-border-color-focused);
    border-bottom: 1px solid var(--search-item-border-color-focused);
  }
`;

const SearchItemContent = styled.section`
  flex: 1 1 auto;
`;

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

const SearchItemTitleWrapper = styled.div`
  display: flex;
  align-items: center;
`;

const SearchItemTitle = styled.div`
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--search-item-title-text-color);
  padding: var(--search-item-title-padding);
  font-size: var(--search-item-title-font-size);
  font-weight: var(--search-item-title-font-weight);
  line-height: var(--search-item-title-line-height);
`;

const SearchItemBadge = styled(Badge)`
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-regular);
`;

const SearchItemOperation = styled.div`
  display: inline-flex;
  align-items: baseline;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-regular);
  color: var(--search-item-path-text-color);
  gap: var(--search-item-gap);
`;

const SearchItemDescription = styled.div`
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  font-weight: var(--font-weight-regular);
`;

const SearchItemPath = styled.div`
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-regular);
  margin-top: var(--spacing-sm);
`;

const SearchItemPlace = styled.div`
  display: flex;
  flex-direction: column;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-sm);
  font-weight: var(--font-weight-regular);
  margin-top: var(--spacing-sm);

  &:first-child {
    padding-top: 0;
  }
`;

const SearchItemProductTag = styled.div`
  position: absolute;
  display: flex;
  align-items: center;
  right: 0;
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  font-weight: var(--font-weight-regular);
  padding: var(--search-item-title-padding);
  gap: var(--spacing-xs);

  img {
    width: var(--search-item-product-icon-size);
    height: var(--search-item-product-icon-size);
  }
`;

const SearchItemOperationTag = styled(HttpTag)`
  --http-tag-width: auto;
  --http-tag-font-weight: var(--font-weight-semibold);
`;
