import React from 'react';
import styled from 'styled-components';

import type { JSX } from 'react';

import { Spinner } from '@redocly/theme/icons/Spinner/Spinner';
import { CheckmarkFilledIcon } from '@redocly/theme/icons/CheckmarkFilledIcon/CheckmarkFilledIcon';
import { DocumentIcon } from '@redocly/theme/icons/DocumentIcon/DocumentIcon';
import { Tag } from '@redocly/theme/components/Tag/Tag';
import { Link } from '@redocly/theme/components/Link/Link';
import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks';
import { Markdown } from '@redocly/theme/components/Markdown/Markdown';
import { Typography } from '@redocly/theme/components/Typography/Typography';
import { Admonition } from '@redocly/theme/components/Admonition/Admonition';
import { ErrorFilledIcon } from '@redocly/theme/icons/ErrorFilledIcon/ErrorFilledIcon';
import {
  AiSearchError,
  AI_SEARCH_ERROR_CONFIG as ERROR_CONFIG,
} from '@redocly/theme/core/constants';
import { ChatIcon } from '@redocly/theme/icons/ChatIcon/ChatIcon';

export type SearchAiResponseProps = {
  question: string;
  isGeneratingResponse: boolean;
  response?: string;
  error: AiSearchError | null;
  resources: {
    url: string;
    title: string;
  }[];
  onSuggestionClick: (suggestion: string) => void;
};
export function SearchAiResponse(props: SearchAiResponseProps): JSX.Element {
  const { useMarkdownText } = useThemeHooks();
  const { question, response, isGeneratingResponse, resources, error, onSuggestionClick } = props;

  const { aiAssistant } = useThemeConfig();
  const { useTranslate } = useThemeHooks();

  const { translate } = useTranslate();
  const markdownResponse = useMarkdownText(response || '');

  let responseContainer = null;

  const suggestions = aiAssistant?.suggestions;

  const hasPendingOrReceivedResponse = response || isGeneratingResponse || error;
  if (hasPendingOrReceivedResponse) {
    let icon;
    switch (true) {
      case error !== null:
        icon = <ErrorFilledIcon size="20px" color="--error-bubble-content-color" />;
        break;
      case isGeneratingResponse:
        icon = <Spinner size="20px" color="--search-ai-spinner-icon-color" />;
        break;
      case Boolean(response):
        icon = <CheckmarkFilledIcon size="20px" color="--search-ai-checkmark-icon-color" />;
        break;
    }
    responseContainer = (
      <>
        <ResponseHeader>
          {icon}
          <Question>{question}</Question>
        </ResponseHeader>
        <ResponseBody>
          {response && <ResponseText children={markdownResponse} as="div" {...props} />}
          {!response && isGeneratingResponse && (
            <ThinkingResponseText data-translation-key="search.ai.thinkingText">
              {translate('search.ai.thinkingText', 'Thinking...')}
            </ThinkingResponseText>
          )}
          {error && (
            <Admonition
              type="danger"
              name={translate(ERROR_CONFIG[error].headerKey, ERROR_CONFIG[error].headerDefault)}
            >
              {translate(ERROR_CONFIG[error].messageKey, ERROR_CONFIG[error].messageDefault)}
            </Admonition>
          )}
          {resources.length && !isGeneratingResponse ? (
            <Resources>
              <ResourcesTitle data-translation-key="search.ai.resourcesFound">
                {resources.length} {translate('search.ai.resourcesFound', 'resources found')}
              </ResourcesTitle>
              <ResourceTags>
                {resources.map((resource, idx) => (
                  <Link key={idx} to={resource.url} target="_blank">
                    <ResourceTag
                      borderless
                      icon={<DocumentIcon color="--search-ai-resource-tag-icon-color" />}
                    >
                      {resource.title}
                    </ResourceTag>
                  </Link>
                ))}
              </ResourceTags>
            </Resources>
          ) : null}
        </ResponseBody>
      </>
    );
  }

  return (
    <ResponseWrapper data-component-name="Search/SearchAiResponse">
      {!question && (
        <>
          {suggestions?.length && (
            <SuggestionsWrapper>
              <SuggestionsTitle>
                {translate('search.ai.suggestionsTitle', 'Suggestions')}
              </SuggestionsTitle>
              {suggestions.map((suggestion, idx) => (
                <SuggestionItem
                  key={idx.toString()}
                  onClick={() => {
                    onSuggestionClick(suggestion);
                  }}
                >
                  <ChatIcon color="--color-blueberry-6" />
                  <Typography color="--search-ai-suggestions-text-color">{suggestion}</Typography>
                </SuggestionItem>
              ))}
            </SuggestionsWrapper>
          )}
        </>
      )}
      {responseContainer}
    </ResponseWrapper>
  );
}

const ResponseWrapper = styled.div`
  display: flex;
  flex-direction: column;
  flex: 2;
  flex-grow: 2;
  overflow-y: scroll;
  overscroll-behavior: contain;
  padding: var(--search-ai-response-padding);
  gap: var(--search-ai-response-gap);
`;

const ResponseHeader = styled.div`
  display: flex;
  flex-direction: row;
  gap: var(--search-ai-response-header-gap);
  align-items: center;
`;

const Question = styled.div`
  font-size: var(--search-ai-question-font-size);
  font-weight: var(--search-ai-question-font-weight);
  line-height: var(--search-ai-question-line-height);
  color: var(--search-ai-question-text-color);
`;

const ResponseBody = styled.div`
  display: flex;
  flex-direction: column;
  gap: var(--search-ai-response-body-gap);
  padding: var(--search-ai-response-body-padding);
`;

const ResponseText = styled(Markdown)`
  color: var(--search-ai-response-text-color);
  font-size: var(--search-ai-response-text-font-size);
  line-height: var(--search-ai-response-text-line-height);
  font-family: inherit;
  white-space: break-spaces;
`;

const ThinkingResponseText = styled.pre`
  color: var(--search-ai-response-text-color);
  font-size: var(--search-ai-response-text-font-size);
  line-height: var(--search-ai-response-text-line-height);
  font-family: inherit;
  white-space: break-spaces;
  margin: var(--md-pre-margin) 0;
  animation: fadeIn 2s ease-in-out infinite;

  @keyframes fadeIn {
    0% {
      opacity: 1;
    }
    50% {
      opacity: 0.3;
    }
    100% {
      opacity: 1;
    }
  }
`;

const Resources = styled.div`
  gap: var(--search-ai-resources-gap);
  display: flex;
  flex-direction: column;
`;

const ResourcesTitle = styled.div`
  font-weight: var(--search-ai-resources-title-font-weight);
  font-size: var(--search-ai-resources-title-font-size);
  line-height: var(--search-ai-resources-title-line-height);
`;

const ResourceTags = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: var(--search-ai-resource-tags-gap);
`;

const ResourceTag = styled(Tag).attrs({
  className: 'tag-resource',
})`
  .tag-default {
    --tag-color: --search-ai-resource-tag-text-color;
  }
`;

const SuggestionsWrapper = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: flex-start;

  gap: var(--spacing-sm);
  margin-left: var(--spacing-xs);
`;

const SuggestionsTitle = styled(Typography)`
  font-size: var(--search-ai-suggestions-title-font-size);
  line-height: var(--search-ai-suggestions-title-line-height);
  font-weight: var(--search-ai-suggestions-title-font-weight);

  color: var(--search-ai-suggestions-title-text-color);
`;

const SuggestionItem = styled.div`
  cursor: pointer;

  display: flex;
  align-items: center;
  justify-content: flex-start;

  gap: var(--spacing-xs);
`;
