'use client';

import {
  WebOnboardingApiName,
  WebOnboardingIdentifier,
} from '@lobechat/builtin-tool-web-onboarding';
import { Flexbox } from '@lobehub/ui';
import { memo, useEffect, useMemo, useRef, useState } from 'react';
import { flushSync } from 'react-dom';

import type { ActionKeys, ChatInputFeature } from '@/features/ChatInput';
import {
  ChatInput,
  ChatList,
  conversationSelectors,
  MessageItem,
  useConversationStore,
} from '@/features/Conversation';
import { dataSelectors } from '@/features/Conversation/store';
import WideScreenContainer from '@/features/WideScreenContainer';
import { useIsMobile } from '@/hooks/useIsMobile';
import type { OnboardingPhase } from '@/types/user';
import { isDev } from '@/utils/env';

import CompletionPanel from './CompletionPanel';
import NameSuggestions from './NameSuggestions';
import Welcome from './Welcome';
import WelcomeMobile from './Welcome.mobile';
import WelcomeMessage from './WelcomeMessage';
import WrapUpHint from './WrapUpHint';

interface AgentOnboardingConversationProps {
  discoveryUserMessageCount?: number;
  feedbackSubmitted?: boolean;
  finishTargetUrl?: string;
  // When true, server reports the active topic already has at least one message.
  // The welcome shell is suppressed and ChatList renders its built-in skeleton
  // while messages fetch, avoiding the misleading "fresh Welcome flash" on
  // returning users.
  hasMessages?: boolean;
  // While false, the underlying backend (bootstrap state or builtin agent
  // config) is still hydrating: ChatInput shows its skeleton-style placeholder
  // for the action/send area so the user cannot submit until the orchestration
  // is ready to handle the first send.
  isInputReady?: boolean;
  onAfterWrapUp?: () => Promise<unknown> | void;
  onboardingFinished?: boolean;
  phase?: OnboardingPhase;
  readOnly?: boolean;
  showFeedback?: boolean;
  topicId?: string;
}

const chatInputLeftActions: ActionKeys[] = isDev ? ['model'] : [];
const chatInputRightActions: ActionKeys[] = [];
const chatInputFeature = {
  inputCompletion: false,
  mention: false,
  slash: false,
} satisfies ChatInputFeature;

const AgentOnboardingConversation = memo<AgentOnboardingConversationProps>(
  ({
    discoveryUserMessageCount,
    feedbackSubmitted,
    finishTargetUrl,
    hasMessages,
    isInputReady = true,
    onAfterWrapUp,
    onboardingFinished,
    phase,
    readOnly,
    showFeedback,
    topicId,
  }) => {
    const isMobile = useIsMobile();
    const displayMessages = useConversationStore(conversationSelectors.displayMessages);
    // The agent-marketplace intervention renders as an absolute overlay anchored
    // to the chat input area, which would otherwise occlude the last message.
    // Reserve matching scroll headroom inside ChatList so the latest message can
    // still be scrolled into view above the marketplace panel.
    const hasAgentMarketplaceIntervention = useConversationStore((s) =>
      dataSelectors
        .pendingInterventions(s)
        .some(
          (i) =>
            i.identifier === WebOnboardingIdentifier &&
            i.apiName === WebOnboardingApiName.showAgentMarketplace,
        ),
    );

    // The welcome is UI-only. It must not be persisted or inserted into LLM
    // history; otherwise the setup copy can compete with the user's first
    // actual naming instruction. `hasMessages` prevents the brief messages-fetch
    // window for returning users from flashing Welcome.
    const isGreetingState = useMemo(
      () => !hasMessages && displayMessages.length === 0,
      [hasMessages, displayMessages],
    );

    const [showGreeting, setShowGreeting] = useState(isGreetingState);
    const prevGreetingRef = useRef(isGreetingState);

    useEffect(() => {
      if (prevGreetingRef.current && !isGreetingState) {
        if (document.startViewTransition) {
          document.startViewTransition(() => {
            // eslint-disable-next-line @eslint-react/dom/no-flush-sync
            flushSync(() => setShowGreeting(false));
          });
        } else {
          setShowGreeting(false);
        }
      }
      if (!prevGreetingRef.current && isGreetingState) {
        setShowGreeting(true);
      }
      prevGreetingRef.current = isGreetingState;
    }, [isGreetingState]);

    const hasPersistedAssistantOpener = displayMessages.at(0)?.role === 'assistant';
    const shouldShowSyntheticWelcome =
      !onboardingFinished && !hasPersistedAssistantOpener && displayMessages.length > 0;
    const shouldShowGreetingWelcome = showGreeting && !onboardingFinished;
    const shouldShowGreetingActions = showGreeting && !onboardingFinished;

    const syntheticWelcome = useMemo(() => {
      if (!shouldShowSyntheticWelcome) return undefined;
      return <WelcomeMessage />;
    }, [shouldShowSyntheticWelcome]);

    const greetingWelcome = useMemo(() => {
      if (!shouldShowGreetingWelcome) return undefined;
      return isMobile ? <WelcomeMobile /> : <Welcome />;
    }, [shouldShowGreetingWelcome, isMobile]);

    const agentMarketplaceSpacer = useMemo(() => {
      if (!hasAgentMarketplaceIntervention) return undefined;
      return (
        <div
          aria-hidden
          style={{
            height: 'min(640px, 72vh)',
            minHeight: 480,
            pointerEvents: 'none',
          }}
        />
      );
    }, [hasAgentMarketplaceIntervention]);

    if (onboardingFinished)
      return (
        <CompletionPanel
          feedbackSubmitted={feedbackSubmitted}
          finishTargetUrl={finishTargetUrl}
          showFeedback={showFeedback}
          topicId={topicId}
        />
      );

    const itemContent = (index: number, id: string) => {
      const isLatestItem = displayMessages.length === index + 1;

      return (
        <MessageItem
          defaultWorkflowExpandLevel="collapsed"
          id={id}
          index={index}
          isLatestItem={isLatestItem}
        />
      );
    };

    return (
      <Flexbox flex={1} height={'100%'}>
        <Flexbox flex={1} style={{ overflow: 'hidden' }}>
          <ChatList
            footerSlot={agentMarketplaceSpacer}
            headerSlot={syntheticWelcome}
            itemContent={itemContent}
            showWelcome={shouldShowGreetingWelcome}
            welcome={greetingWelcome}
          />
        </Flexbox>
        {!readOnly && !onboardingFinished && (
          <Flexbox gap={8}>
            <WrapUpHint
              discoveryUserMessageCount={discoveryUserMessageCount}
              phase={phase}
              onAfterFinish={onAfterWrapUp}
            />
            {shouldShowGreetingActions &&
              (isMobile ? (
                <NameSuggestions variant={'chips'} />
              ) : (
                <WideScreenContainer>
                  <NameSuggestions />
                </WideScreenContainer>
              ))}
            <ChatInput
              disableFollowUpVariant
              disableQueue
              allowExpand={false}
              feature={chatInputFeature}
              isConfigLoading={!isInputReady}
              leftActions={chatInputLeftActions}
              rightActions={chatInputRightActions}
              showControlBar={false}
            />
          </Flexbox>
        )}
      </Flexbox>
    );
  },
);

AgentOnboardingConversation.displayName = 'AgentOnboardingConversation';

export default AgentOnboardingConversation;
