'use client';

import { useAuth } from '@clerk/nextjs';
import { ThemeProvider } from '@emotion/react';
import { useQueryClient } from '@tanstack/react-query';
import * as Ably from 'ably';
import { useAbly } from 'ably/react';
import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import React, {
  useCallback,
  useEffect,
  useLayoutEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { ClipBrowserContext } from '@/components/clipBrowser/useClipBrowser';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { ThemeMode, useThemeContext } from '@/context/ThemeContext';
import { useBreakpointMd } from '@/hooks/useBreakpoint';
import { useClipById } from '@/hooks/useClipById';
import { useContextSelector } from '@/hooks/useContextSelector';
import { getUnexpiredPrompt } from '@/hooks/useHasUnexpiredPrompt';
import { CaretDownIcon } from '@/icons';
import { Clip } from '@/state/clipStore';

import { standardTheme } from '../create/createV2/componentsQ3/themes';
import CreateFormContext from '../create/v2/CreateFormContext';
import { CreateModes } from '../create/v2/types';
import { FocusedObjectContext } from '../create/v2/useFocusedObject';
import { ChatArtifact } from './ChatArtifact';
import { ChatInput, ChatInputModeType } from './ChatInput';
import { ChatSessionAlert } from './ChatSessionAlert';
import { MessageList } from './MessageList';
import { NewUserPresets } from './NewUserPresets';
import { OutOfCreditsBanner } from './OutOfCreditsBanner';
import ShareChatModal, { ChatPermission } from './ShareChatModal';
import GradientBackground from './components/GradientBackground';
import {
  ClipReference,
  LyricsReference,
  ReferenceType,
} from './components/input/ReferenceTypes';
import {
  type GradientStateName,
  useGradientController,
} from './hooks/useGradientController';
import {
  useChatInputStore,
  useChatMessagesStore,
  useChatStore,
} from './stores';
import { ChatSession } from './types';
import { useChatContext } from './useChat';
import { useChatMessageActions } from './useChatMessageActions';
import {
  WORKSPACES_QUERY_KEY,
  workspaceListQueryClient,
} from './useWorkspaces';

export type ActiveUser = {
  clientId: string;
  data: {
    userHandle?: string;
    userAvatar?: string;
  };
};

export type SessionError = {
  session_id: string;
  error: string;
};

const MESSAGES_CONTAINER_SCROLL_THRESHOLD = 50;
const CONTENT_STABILIZATION_DEBOUNCE_MS = 100;

export const ChatClient = observer(
  ({
    className = '',
    readOnly = false,
    sessionId,
    sessionMetadata,
    setActiveUsers,
    offsetHeight,
    model,
  }: {
    className?: string;
    readOnly?: boolean;
    sessionId?: string;
    sessionMetadata?: ChatSession;
    setActiveUsers?: React.Dispatch<React.SetStateAction<ActiveUser[]>>;
    offsetHeight?: number;
    model: string;
  }) => {
    const { session, playbar, project } = useStores();
    const gradientController = useGradientController();
    const { setState: setGradientState } = gradientController;
    const isFirstGradientUpdate = useRef(true);
    const initialScrollRef = useRef(false);
    const contentStableTimeoutRef = useRef<NodeJS.Timeout | null>(null);
    const lastFetchedSessionIdRef = useRef<string | null>(null);
    const fetchingSessionsRef = useRef(false);
    const mainContainerRef = useRef<HTMLDivElement>(null);
    const messagesContentRef = useRef<HTMLDivElement>(null);
    const chatInputRef = useRef<any>(null);
    const allowChildScrollRef = useRef(false);
    const sendMessageRef = useRef<typeof sendMessage>(null);
    const setInputRef = useRef<typeof setInput>(null);
    const handleAllowChildScroll = useCallback(() => {
      allowChildScrollRef.current = true;
    }, []);
    const { getToken } = useAuth();
    const { effectiveTheme } = useThemeContext();
    const {
      handleSend: sendMessage,
      processDataChunk,
      processToolCallDataChunk,
    } = useChatMessageActions();
    const sessionMap = useChatStore((state) => state.sessionMap);
    const {
      currentSession,
      references,
      chatUUID,
      setChatUUID,
      isShareModalOpen,
      setAbly,
      setIsShareModalOpen,
      addSessionId,
      prependSessionId,
      setSessionMapValue,
      setIsChatOwner,
      setLastPlayedClipId,
      isSessionsDataLoaded,
      setIsSessionsDataLoaded,
      registerModelChange,
      registerClipStatusChange,
      isMaximumSessionLength,
      setIsMaximumSessionLength,
      createChatSession,
      isCreatingNewSession,
      isLoadingChatHistory,
      setIsLoadingChatHistory,
      clearReferences,
    } = useChatContext();
    const { msgIds, loadedMessages, isLoading, setIsLoading, forcedScrollAt } =
      useChatMessagesStore();

    const isVoiceMode = useChatInputStore((state) => state.isVoiceMode);
    const [_model, setModel] = useContextSelector(
      CreateFormContext,
      (context) => context.selectState<string>(['global', 'model'])
    );
    const [mode, setMode] = useContextSelector(CreateFormContext, (context) =>
      context.selectState<CreateModes>(['global', 'mode'])
    );
    const setFocusedObject = useContextSelector(
      FocusedObjectContext,
      (context) => context.setFocusedObject
    );
    const [chatInputMode, setChatInputMode] = useState<ChatInputModeType>(
      ChatInputModeType.ACTION
    );
    const [chatInputHeight, setChatInputHeight] = useState<number | null>(null);

    useEffect(() => {
      if (isCreatingNewSession) {
        lastFetchedSessionIdRef.current = null;
      }
    }, [isCreatingNewSession]);

    useEffect(() => {
      if (sessionId) {
        setChatUUID(sessionId);
      }
    }, [sessionId]);

    useEffect(() => {
      if (model) {
        setModel(model);
        registerModelChange(model);
      }
    }, [model, chatUUID]);

    useEffect(() => {
      if (mode === CreateModes.SIMPLE) {
        setMode(CreateModes.CUSTOM);
      }
    }, [mode, setMode]);

    useEffect(() => {
      registerModelChange(_model);
    }, [_model]);

    const { setInput } = useChatInputStore();
    const isHandlingLandingPageRef = useRef(false);
    const pendingPromptRef = useRef<string>(null);

    useEffect(() => {
      const handlePendingPrompt = async () => {
        // Check if already handled FIRST to prevent re-runs
        if (isHandlingLandingPageRef.current) {
          return;
        }

        // Use the centralized utility function to check if prompt is unexpired and get the prompt value
        const { hasUnexpiredPrompt, prompt } = getUnexpiredPrompt();

        if (hasUnexpiredPrompt) {
          // TypeScript knows prompt is a string here due to discriminated union type
          try {
            // Mark as handled immediately to prevent re-runs
            isHandlingLandingPageRef.current = true;
            if (prompt.trim().length > 0) {
              pendingPromptRef.current = prompt;
              await createChatSession();
              setIsLoadingChatHistory(false);
              // Store the prompt to send once subscriptions are ready
              localStorage.removeItem('prompt');
              localStorage.removeItem('prompt_saved_at');
              localStorage.removeItem('prompt_source');
            }
          } finally {
            isHandlingLandingPageRef.current = false;
          }
        }
      };
      if (isSessionsDataLoaded) {
        handlePendingPrompt();
      }
    }, [
      isSessionsDataLoaded,
      sendMessage,
      createChatSession,
      setInput,
      setIsLoadingChatHistory,
    ]);

    useEffect(() => {
      // when the session ID changes, reset local scroll indicator state
      setIsScrolled(false);
      setHasNewMessages(false);
      setIsLoading(false);
      setFocusedObject(undefined);
      clearReferences();
    }, [chatUUID]);

    // Derive clip reference from new references system
    const clipReference = references.find(
      (ref) => ref.type === ReferenceType.CLIP
    );
    const referencedClipId = clipReference
      ? (clipReference as ClipReference).clipId
      : null;
    const { data: referencedClip } = useClipById(referencedClipId);
    const referencedClipDuration = referencedClip?.metadata?.duration;
    const lyricsReference: LyricsReference | undefined = references.find(
      (ref) => ref.type === ReferenceType.LYRICS
    ) as LyricsReference;
    const ablyClient = useAbly();
    const queryClient = useQueryClient();
    const isSessionError = (
      sessionData: Partial<ChatSession> | SessionError
    ): sessionData is SessionError => {
      return (sessionData as SessionError).error !== undefined;
    };
    const [hasNewMessages, setHasNewMessages] = useState(false);
    const [isScrolled, setIsScrolled] = useState(false);

    const updateSessionMetadata = useCallback(
      async (sessionData: Partial<ChatSession> | SessionError) => {
        if (isSessionError(sessionData)) {
          if (
            sessionData.error === 'session_length' &&
            chatUUID === sessionData.session_id
          ) {
            setIsMaximumSessionLength(true);
            setIsLoading(false);
          }
          return;
        }

        const existingSession = sessionMap.get(sessionData?.session_id ?? '');
        if (sessionData.session_id && !existingSession) {
          prependSessionId(sessionData.session_id);
        }
        if (sessionData.session_id) {
          setSessionMapValue(sessionData.session_id, {
            ...(existingSession ?? {}),
            ...sessionData,
          });
          if (sessionData.name && sessionData.workspace_id) {
            await workspaceListQueryClient.invalidateQueries({
              queryKey: [WORKSPACES_QUERY_KEY, '', false],
            });
            await queryClient.invalidateQueries({
              queryKey: ['workspace', sessionData.workspace_id],
            });
          }
        }
      },
      [sessionMap, queryClient, workspaceListQueryClient, chatUUID]
    );

    useEffect(() => {
      if (ablyClient) {
        setAbly(ablyClient);
      }
    }, [ablyClient, setAbly]);

    useEffect(() => {
      if (sessionMetadata) {
        setIsChatOwner(sessionMetadata.user_id === session.userId);
      } else if (!sessionId) {
        // Not on a specific session page, so assume the user is chat owner
        setIsChatOwner(true);
      }
    }, [sessionMetadata, session.userId, sessionId]);

    useEffect(() => {
      if (playbar.isPlaying && playbar.clip?.id) {
        setLastPlayedClipId(playbar.clip?.id);
      }
    }, [playbar.clip, playbar.isPlaying]);

    useEffect(() => {
      sendMessageRef.current = sendMessage;
    }, [sendMessage]);

    useEffect(() => {
      setInputRef.current = setInput;
    }, [setInput]);

    const messageHandler = useCallback(
      (message: Ably.Message) => {
        if (message.name === 'orpheus-message') {
          if (message.data?.data?.userId === session.userId) {
            return;
          }
          if (isScrolled) {
            setHasNewMessages(true);
          }
          processDataChunk(message.data.data, isVoiceMode);
        }
      },
      [
        isScrolled,
        isVoiceMode,
        session.userId,
        setHasNewMessages,
        processDataChunk,
      ]
    );

    const toolCallHandler = useCallback(
      (message: Ably.Message) => {
        if (message.name === 'orpheus-tool-call') {
          processToolCallDataChunk(
            message.data.data,
            message.data.tool_call_id,
            message.data.tool_call_name
          );
        }
      },
      [processToolCallDataChunk]
    );

    const sessionUpdateHandler = useCallback(
      (message: Ably.Message) => {
        if (message.name === 'orpheus-session-update') {
          updateSessionMetadata(message.data);
        }
      },
      [updateSessionMetadata]
    );

    useEffect(() => {
      if (ablyClient && chatUUID) {
        const channel = ablyClient.channels.get(`orpheus-chat:${chatUUID}`);

        channel.subscribe('orpheus-message', messageHandler);
        channel.subscribe('orpheus-tool-call', toolCallHandler);
        channel.subscribe('orpheus-session-update', sessionUpdateHandler);

        // If there's a pending prompt for this session, send it now
        const pending = pendingPromptRef.current;
        if (pending) {
          pendingPromptRef.current = null;
          sendMessageRef
            .current?.({
              input: pending,
              setInput: setInputRef.current ?? undefined,
              isVoiceMode: false,
              needsResponse: true,
            })
            .catch(() => {
              pendingPromptRef.current = pending;
            });
        }

        return () => {
          channel.unsubscribe('orpheus-message', messageHandler);
          channel.unsubscribe('orpheus-tool-call', toolCallHandler);
          channel.unsubscribe('orpheus-session-update', sessionUpdateHandler);
        };
      }
    }, [
      chatUUID,
      ablyClient,
      setAbly,
      updateSessionMetadata,
      messageHandler,
      toolCallHandler,
      sessionUpdateHandler,
    ]);

    useEffect(() => {
      if (ablyClient && chatUUID && session.user?.handle) {
        const channel = ablyClient.channels.get(`orpheus-chat:${chatUUID}`);

        // Handle presence events
        const userEnterHandler = (message: Ably.PresenceMessage) => {
          // Handle user entering the channel
          if (setActiveUsers) {
            setActiveUsers((prev) => {
              // Don't add the current user to the list
              if (message.clientId === ablyClient.auth.clientId) {
                return prev;
              }

              // Check if user already exists
              if (prev.find((user) => user.clientId === message.clientId)) {
                return prev;
              }

              // Transform Ably.PresenceMessage to ActiveUser format
              const activeUser: ActiveUser = {
                clientId: message.clientId,
                data: {
                  userHandle: message.data?.userHandle,
                  userAvatar: message.data?.userAvatar,
                },
              };

              return [...prev, activeUser];
            });
          }
        };

        const userLeaveHandler = (message: Ably.PresenceMessage) => {
          // Handle user leaving the channel
          if (setActiveUsers) {
            setActiveUsers((prev) =>
              prev.filter((user) => user.clientId !== message.clientId)
            );
          }
        };

        // Subscribe to presence events
        channel.presence.subscribe('enter', userEnterHandler);
        channel.presence.subscribe('leave', userLeaveHandler);

        const enterPresence = async () => {
          try {
            await channel.presence.enter({
              userHandle: session.user?.handle,
              userAvatar: session.user?.avatar_image_url,
            });
          } catch (error) {
            console.error('Error entering presence:', error);
          }
        };

        enterPresence();

        // Get initial presence members
        const getInitialMembers = async () => {
          try {
            const members = await channel.presence.get();
            // Filter out the current user and transform the data structure
            const otherUsers = members
              .filter((member) => member.clientId !== ablyClient.auth.clientId)
              .map((member) => ({
                clientId: member.clientId,
                data: {
                  userHandle: member.data?.userHandle,
                  userAvatar: member.data?.userAvatar,
                },
              }));
            if (setActiveUsers) {
              setActiveUsers(otherUsers);
            }
          } catch (error) {
            console.error('Error getting presence members:', error);
          }
        };

        getInitialMembers();

        // Cleanup: leave presence and unsubscribe from events when component unmounts or chatUUID changes
        return () => {
          channel.presence.unsubscribe();
          channel.presence.leave();
        };
      }
    }, [
      chatUUID,
      ablyClient,
      session.user?.handle,
      session.user?.avatar_image_url,
    ]);

    useEffect(() => {
      const fetchSessionHistory = async () => {
        if (fetchingSessionsRef.current) return;

        fetchingSessionsRef.current = true;
        try {
          const token = await getToken();
          const env =
            process.env.NEXT_PUBLIC_ORPHEUS_ENV ??
            (process.env.NEXT_PUBLIC_NODE_ENV === 'production'
              ? 'prod'
              : 'dev');
          const MODAL_SRV = `https://suno-ai--orpheus-${env}-web.modal.run`;
          const response = await fetch(`${MODAL_SRV}/session-history`, {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
              Authorization: `Bearer ${token}`,
            },
          });
          const sessionHistory = await response.json();
          sessionHistory?.sessions?.forEach((sessionItem: any) => {
            sessionItem.name = sessionItem.name || `Untitled Chat`;
            sessionItem.session_id = sessionItem.item_id;
            addSessionId(sessionItem.session_id);
            setSessionMapValue(sessionItem.session_id, sessionItem);
          });
          setIsSessionsDataLoaded(true);
        } finally {
          fetchingSessionsRef.current = false;
        }
      };
      if (!isSessionsDataLoaded && !fetchingSessionsRef.current) {
        fetchSessionHistory();
      }
    }, [isSessionsDataLoaded]);

    const scrollToBottom = useCallback(
      (container: HTMLDivElement | null, forceScroll = false) => {
        if ((!isScrolled || forceScroll) && container) {
          if (forceScroll) {
            container.scrollTop =
              container.scrollHeight - container.clientHeight;
          } else {
            container.scrollBy({
              top: container.scrollHeight,
              behavior: 'smooth',
            });
          }

          allowChildScrollRef.current = false;
        }
      },
      [isScrolled]
    );

    const scrollToChildBottom = useCallback(
      (child: Element, container: HTMLDivElement | null) => {
        if (container && (!isScrolled || allowChildScrollRef.current)) {
          child.scrollIntoView({ block: 'end' });
          container.scrollTop += 200; // Offset for input box
          allowChildScrollRef.current = false;
        }
      },
      [isScrolled]
    );

    useEffect(() => {
      if (isLoadingChatHistory) {
        initialScrollRef.current = false;
      }
    }, [isLoadingChatHistory]);

    useLayoutEffect(() => {
      const container = mainContainerRef.current;
      const wrapper = messagesContentRef.current;
      if (!container || !wrapper) {
        return;
      }

      const childResizeObserver = new ResizeObserver((entries) => {
        // if (entries.length > 1 && initialChildScrollRef.current) return;

        if (contentStableTimeoutRef.current) {
          clearTimeout(contentStableTimeoutRef.current);
        }

        // Wait for content to stabilize (no resizes for 100ms)
        contentStableTimeoutRef.current = setTimeout(() => {
          if (!initialScrollRef.current && !isLoadingChatHistory) {
            scrollToBottom(container, true);
            initialScrollRef.current = true;
          }
          contentStableTimeoutRef.current = null;
        }, CONTENT_STABILIZATION_DEBOUNCE_MS);
        if (!allowChildScrollRef.current) {
          scrollToBottom(container);
        } else {
          scrollToChildBottom(entries[entries.length - 1].target, container);
        }
      });

      Array.from(wrapper.children).forEach((child) => {
        childResizeObserver.observe(child);
      });

      const mutationObserver = new MutationObserver((mutations) => {
        let shouldForceScroll = false;
        mutations.forEach((mutation) => {
          mutation.addedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) {
              childResizeObserver.observe(node as any);
            }
            if (
              node instanceof Element &&
              node.classList.contains('flex-row-reverse') // implies a user message was added
            ) {
              shouldForceScroll = true;
            }
          });
          mutation.removedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) {
              childResizeObserver.unobserve(node as any);
            }
          });
        });
        scrollToBottom(container, shouldForceScroll);
      });

      mutationObserver.observe(wrapper, {
        childList: true,
      });

      return () => {
        if (contentStableTimeoutRef.current) {
          clearTimeout(contentStableTimeoutRef.current);
          contentStableTimeoutRef.current = null;
        }
        childResizeObserver.disconnect();
        mutationObserver.disconnect();
      };
    }, [
      scrollToBottom,
      scrollToChildBottom,
      loadedMessages,
      isLoadingChatHistory,
    ]);

    useEffect(() => {
      setIsScrolled(false);
      setHasNewMessages(false);
      scrollToBottom(mainContainerRef.current, true);
    }, [forcedScrollAt]);

    const setFilters = useContextSelector(
      ClipBrowserContext,
      (context) => context.setFilters
    );

    useEffect(() => {
      setFilters((prev) => ({
        ...prev,
        workspace: {
          workspaceId: project.currentProjectId,
          presence: prev.workspace.presence as any,
        },
      }));
    }, [project.currentProjectId, setFilters]);

    const hasMessages = msgIds.length > 0 || (loadedMessages?.length ?? 0) > 0;
    const targetGradientState = useMemo<GradientStateName>(() => {
      if (isLoading) {
        return 'Thinking';
      }

      if (!isLoadingChatHistory && !readOnly && !hasMessages) {
        return 'EmptyChat';
      }

      return 'Static';
    }, [hasMessages, isLoading, isLoadingChatHistory, readOnly]);

    useEffect(() => {
      setGradientState(targetGradientState, {
        immediate: isFirstGradientUpdate.current,
      });
      isFirstGradientUpdate.current = false;
    }, [setGradientState, targetGradientState]);

    useEffect(() => {
      const updateChatInputHeight = () => {
        if (chatInputRef.current) {
          setChatInputHeight(chatInputRef.current.offsetHeight || 0);
        }
      };
      updateChatInputHeight();
      const resizeObserver = new ResizeObserver(updateChatInputHeight);
      if (chatInputRef.current) {
        resizeObserver.observe(chatInputRef.current);
      }
      return () => {
        resizeObserver.disconnect();
      };
    }, [chatInputMode, references]);

    const offsetHeightPx = offsetHeight ?? 64;
    const isMobile = !useBreakpointMd();

    return (
      <ThemeProvider theme={standardTheme}>
        <div className='relative flex h-full w-full flex-row'>
          {effectiveTheme === ThemeMode.Dark ? (
            <GradientBackground
              controller={gradientController}
              className='pointer-events-none absolute inset-0 z-0'
            />
          ) : null}

          <div
            className={twMerge(
              clsx(
                'relative z-10 flex h-full w-full flex-1 flex-col items-center'
              ),
              className
            )}
          >
            <OutOfCreditsBanner />
            <div
              className={clsx(`relative flex w-full flex-1`, {
                'pb-[85px]': hasMessages && !isMobile,
              })}
              style={{
                minHeight: hasMessages
                  ? `calc(100vh - ${offsetHeightPx}px)`
                  : undefined,
                maxHeight: `calc(100vh - ${offsetHeightPx}px)`,
              }}
            >
              <div className='flex h-full flex-1 justify-center overflow-hidden'>
                <div className='relative flex h-full w-full min-w-0 flex-1'>
                  {hasNewMessages && !readOnly && chatInputHeight ? (
                    <Button
                      icon={CaretDownIcon}
                      className={clsx(
                        'glass-highlight absolute left-1/2 z-[5000] -translate-x-1/2 bg-background-fog-thick backdrop-blur-lg'
                      )}
                      style={{
                        bottom: `${chatInputHeight + 16}px`,
                      }}
                      shape={ButtonShape.Pill}
                      size={ButtonSize.Mini}
                      variant={ButtonVariant.Secondary}
                      onClick={() => {
                        if (mainContainerRef.current) {
                          mainContainerRef.current.scrollTop =
                            mainContainerRef.current.scrollHeight;
                          setHasNewMessages(false);
                          setIsScrolled(false);
                        }
                      }}
                      aria-label='Jump to new messages'
                    >
                      Jump to new messages
                    </Button>
                  ) : null}
                  {isLoadingChatHistory ? (
                    <div className='flex h-full w-full flex-col items-center justify-center'>
                      <SpinnerSVG />
                    </div>
                  ) : (
                    <>
                      {!hasMessages && !readOnly && (
                        <div
                          className={clsx(
                            '@container/chat absolute bottom-[120px] left-1/2 z-[499] flex w-full max-w-[768px] -translate-x-1/2 justify-center px-8 transition-all duration-500 ease-in-out',
                            {
                              '-translate-y-[calc(50vh-120px)]':
                                references.length === 0,
                              '-translate-y-[calc(50vh-100px)]':
                                references.length > 0,
                            }
                          )}
                        >
                          <NewUserPresets
                            onClickPreset={(message: string) => {
                              sendMessage({ message });
                            }}
                            onUpload={() => {
                              setChatInputMode(ChatInputModeType.UPLOAD_FILE);
                            }}
                            onRecord={() => {
                              setChatInputMode(ChatInputModeType.RECORD);
                            }}
                          />
                        </div>
                      )}
                      {!readOnly ? (
                        <ChatInput
                          ref={chatInputRef}
                          chatInputMode={chatInputMode}
                          setChatInputMode={setChatInputMode}
                          referencedClip={referencedClip}
                          referencedClipDuration={
                            referencedClipDuration || undefined
                          }
                          referencedLyrics={lyricsReference}
                          isNewUserState={!hasMessages}
                          onUploadComplete={(
                            clipId: string,
                            title: string,
                            imageUrl: string,
                            uploadId: string,
                            audioBuffer?: AudioBuffer
                          ) => {
                            sendMessage({
                              message: JSON.stringify({ clipIds: [clipId] }),
                              clipIds: [clipId],
                            }).then(() => {
                              if (audioBuffer) {
                                useChatStore.getState().addReference({
                                  type: ReferenceType.CLIP,
                                  clipId: clipId,
                                });
                                registerClipStatusChange({
                                  clipId,
                                  status: 'complete',
                                  duration: audioBuffer.duration,
                                  title: title,
                                });
                              }
                            });
                          }}
                        />
                      ) : null}
                      {/* {!hasMessages && !readOnly ? (
                        <div className='absolute bottom-0 z-[5000] flex w-full translate-y-[120px] justify-center'>
                          <div className='w-full max-w-[1024px] -translate-y-[calc(50vh-100%+70px)] p-8'>
                            <Presets
                              onClickPreset={(message: string) => {
                                sendMessage({ message });
                              }}
                            />
                          </div>
                        </div>
                      ) : null} */}
                    </>
                  )}
                  <div
                    ref={mainContainerRef}
                    className={clsx(
                      'scrollbar-thin scrollbar-thumb-white/20 custom-scrollbar-transparent @container/chat relative z-[10] flex max-h-full w-full flex-1 flex-col items-center overflow-y-scroll'
                    )}
                    style={{ scrollbarGutter: 'stable !important' }}
                    onScroll={() => {
                      if (
                        (mainContainerRef.current?.scrollHeight ?? 0) -
                          (mainContainerRef.current?.scrollTop ?? 0) -
                          (mainContainerRef.current?.clientHeight ?? 0) >
                        MESSAGES_CONTAINER_SCROLL_THRESHOLD
                      ) {
                        setIsScrolled(true);
                      } else {
                        setIsScrolled(false);
                        setHasNewMessages(false);
                      }
                    }}
                  >
                    <div
                      className={clsx(
                        'flex h-auto w-full max-w-[1024px] flex-col gap-8 pt-8 pr-8 pl-10',
                        {
                          'h-full min-h-full items-center justify-center':
                            !hasMessages && !readOnly,
                          'mb-[200px]': hasMessages && !readOnly,
                          'mb-[248px]':
                            hasMessages && !readOnly && references.length > 0,
                          'mb-[120px]': readOnly,
                        }
                      )}
                      ref={messagesContentRef}
                    >
                      <MessageList
                        onAllowChildScroll={handleAllowChildScroll}
                      />
                      {isMaximumSessionLength && (
                        <ChatSessionAlert
                          title={'Conversation Length Limit Reached'}
                          subtitle={
                            'Start a new conversation to keep chatting.'
                          }
                          buttonText={'New Chat'}
                          onClick={async () => {
                            await createChatSession();
                          }}
                        />
                      )}
                    </div>
                  </div>
                </div>
              </div>
              {!isMobile ? (
                <ChatArtifact
                  onAfterCreate={(clips: Clip[]) => {
                    sendMessage({
                      forcedRole: 'assistant',
                      message: JSON.stringify({
                        clipIds: clips.map((clip: Clip) => clip.id),
                      }),
                      clipIds: clips.map((clip: Clip) => clip.id),
                    });
                  }}
                />
              ) : null}
            </div>
          </div>
        </div>
        <ShareChatModal
          chatUUID={chatUUID}
          isOpen={isShareModalOpen}
          onClose={() => setIsShareModalOpen(false)}
          currentVisibility={currentSession?.visibility as ChatPermission}
        />
        {/*session.isStaff ? (
          <>
            <EditingModal
              isOpen={isEditingModalOpen}
              onClose={() => setIsEditingModalOpen(false)}
            />
            <ChatLibrarySelectModal
              isOpen={isLibraryModalOpen}
              onClose={() => setIsLibraryModalOpen(false)}
            />
          </>
        ) : null*/}
      </ThemeProvider>
    );
  }
);
