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

import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks';
import { Button } from '@redocly/theme/components/Button/Button';
import { SearchAiConversationInput } from '@redocly/theme/components/Search/SearchAiConversationInput';
import {
  AiSearchError,
  AI_SEARCH_ERROR_CONFIG as ERROR_CONFIG,
  AiSearchConversationRole,
} from '@redocly/theme/core/constants';
import { AiSearchConversationItem } from '@redocly/theme/core/types';
import { SearchAiMessage } from '@redocly/theme/components/Search/SearchAiMessage';
import { Admonition } from '@redocly/theme/components/Admonition/Admonition';
import { AiStarsIcon } from '@redocly/theme/icons/AiStarsIcon/AiStarsIcon';

export type SearchAiDialogProps = {
  response: string | undefined;
  isGeneratingResponse: boolean;
  error: AiSearchError | null;
  resources: {
    url: string;
    title: string;
  }[];
  initialMessage?: string;
  className?: string;
  conversation: AiSearchConversationItem[];
  setConversation: React.Dispatch<React.SetStateAction<AiSearchConversationItem[]>>;
  onMessageSent: (message: string, history?: AiSearchConversationItem[]) => void;
};

export function SearchAiDialog({
  isGeneratingResponse,
  response,
  initialMessage,
  error,
  resources,
  onMessageSent,
  className,
  conversation,
  setConversation,
}: SearchAiDialogProps): JSX.Element {
  const { useTranslate } = useThemeHooks();
  const { search } = useThemeConfig();
  const { translate } = useTranslate();

  const conversationEndRef = React.useRef<HTMLDivElement>(null);

  const suggestions = search?.ai?.suggestions;

  const placeholder = isGeneratingResponse
    ? translate('search.ai.generatingResponse', 'Generating response...')
    : conversation.length > 0
      ? translate('search.ai.followUpQuestion', 'Ask a follow up question?')
      : translate('search.ai.placeholder', 'Ask a question...');

  const scrollToBottom = () => {
    conversationEndRef.current?.scrollIntoView({ block: 'end' });
  };

  const handleOnMessageSent = (message: string) => {
    if (!message.trim()) {
      return;
    }
    const mappedHistory = conversation.map(({ role, content }) => ({
      role,
      content,
    }));
    onMessageSent(message, mappedHistory);
    setConversation((prev) => [...prev, { role: AiSearchConversationRole.USER, content: message }]);
  };

  useEffect(() => {
    if (!initialMessage?.trim().length) {
      return;
    }
    setConversation((prev) => [
      ...prev,
      { role: AiSearchConversationRole.USER, content: initialMessage },
    ]);
  }, [initialMessage, setConversation]);

  useEffect(() => {
    if (response === undefined || conversation.length === 0 || error) {
      return;
    }

    setConversation((prev) => {
      const lastMessage = prev[prev.length - 1];
      const content: string = response || '';

      if (lastMessage && lastMessage.role === AiSearchConversationRole.ASSISTANT) {
        return [
          ...prev.slice(0, -1),
          { role: AiSearchConversationRole.ASSISTANT, content, resources },
        ];
      }

      return [...prev, { role: AiSearchConversationRole.ASSISTANT, content }];
    });
  }, [response, conversation.length, error, resources, setConversation]);

  useEffect(() => {
    if (error) {
      setConversation((prev) => prev.slice(0, -1));
    }
  }, [error, setConversation]);

  useEffect(() => {
    scrollToBottom();
  }, [conversation, isGeneratingResponse]);

  return (
    <SearchAiDialogWrapper data-component-name="Search/SearchAiDialog" className={className}>
      {!conversation.length && (
        <WelcomeWrapper>
          <AiStarsIcon
            color="var(--search-ai-icon-color)"
            size="32px"
            background="var(--search-ai-icon-bg-color)"
            borderRadius="var(--border-radius-lg)"
            margin="0 var(--spacing-xs) 0 0"
          />
          {translate(
            'search.ai.welcomeText',
            'Welcome to AI search! Feel free to ask me anything. How can I help you? ',
          )}
        </WelcomeWrapper>
      )}

      <ConversationWrapper>
        {conversation.map((item, index) => (
          <SearchAiMessage
            key={`search-ai-message-${index}`}
            role={item.role}
            content={item.content}
            isThinking={
              item.role === AiSearchConversationRole.ASSISTANT &&
              isGeneratingResponse &&
              index === conversation.length - 1
            }
            resources={item.resources}
          />
        ))}

        {error && (
          <Admonition
            type="danger"
            name={translate(ERROR_CONFIG[error].headerKey, ERROR_CONFIG[error].headerDefault)}
          >
            {translate(ERROR_CONFIG[error].messageKey, ERROR_CONFIG[error].messageDefault)}
          </Admonition>
        )}

        {!conversation.length && !error && (
          <SuggestionsWrapper>
            {suggestions?.map((suggestion) => (
              <Button
                key={suggestion}
                variant="outlined"
                onClick={() => handleOnMessageSent(suggestion)}
              >
                {suggestion}
              </Button>
            ))}
          </SuggestionsWrapper>
        )}

        <div ref={conversationEndRef} />
      </ConversationWrapper>

      <ConversationInputWrapper>
        <SearchAiConversationInput
          onMessageSent={handleOnMessageSent}
          isGeneratingResponse={isGeneratingResponse}
          placeholder={placeholder}
        />
      </ConversationInputWrapper>
    </SearchAiDialogWrapper>
  );
}

const SearchAiDialogWrapper = styled.div`
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  min-height: 0;
  position: relative;
  background: var(--search-ai-dialog-bg-color);
  overflow: hidden;
`;

const ConversationWrapper = styled.div`
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--search-ai-dialog-body-padding);
  padding-bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--search-ai-dialog-body-gap);
  min-height: 0;

  > :first-child {
    margin-top: auto;
  }
  > :last-child {
    margin-bottom: 0;
    gap: 0;
  }
`;

const SuggestionsWrapper = styled.div`
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--search-ai-suggestions-gap);
  align-items: center;
  justify-content: center;
`;

const ConversationInputWrapper = styled.div`
  padding: var(--search-ai-dialog-input-padding);
  border-top: var(--search-ai-dialog-input-border);
  background: var(--search-ai-dialog-input-bg-color);
`;

const WelcomeWrapper = styled.div`
  display: flex;
  flex-direction: row;
  align-items: center;
  width: auto;
  margin: var(--search-ai-welcome-margin);
  position: relative;
`;
