import { createContext, useContext } from "react";
import { ConverationAPI } from "types";
import { AuthContext } from "./AuthContext";

type MessageProviderProps ={
    children? : ReactNode;
}

type IMessageContext = {
    stateMessage: string;
    setStateMessage: (message: string) => void;
    conversationDetails: ConverationAPI [];
    setConversationDetails: (conversationPrompts: ConverationAPI[]) => void;
    isGeneratingMessage: boolean;
}

const initialValues = {
    stateMessage: '',
    setStateMessage: () => {},
    conversationDetails: [],
    setConversationDetails: () => {},
    isGeneratingMessage: false
}

const MessageContext = createContext<IMessageContext>(initialValues);

const MessageProvider = ( {children}: MessageProviderProps) => {
    const { authenticated, loading } = useContext(AuthContext);
    const [subscribe, unsubscribe, socket, sendMessage]= useContext(WebSocketContext)
    const { account } = useContext(AccountContext)
    const {conversations, selectedConversation, setSelectedConversation} = useContext(ConversationContext);

    const [stateMessage, setStateMessage] = useState<string>('')
    const [conversationDetails, setConversationDetails] = useState<ConversationPrompt[]>([])
    const [isGeneratingMessage, setIsGeneratingMessage] = useState<boolean>(false)

    const messageRef = useRef('')
    const messageResponsePart = useRef(0);
    const conversationRef = useRef(conversationDetails)
    const selectedConversationRef = useRef<undefined | number>(undefined)

    async function GetConversationDetails(){
        if(selectedConversation){
            
            try{
                //setPromptProcessing(true)
                selectedConversationRef.current = selectedConversation;
                const {data, }: AxiosResponse<ConversationPromptType[]> = await axiosInstance.get(`conversation_details?conversation_id=${selectedConversation}`)
                
                const tempConversations: ConversationPrompt[] = data.map((item) => new ConversationPrompt({
                    message: item.message,
                    user_created: item.user_created,
                    created_timestamp: item.created_timestamp
                }))
                if(tempConversations.length === 1){
                    // we need to add another card because this is the first message
                    tempConversations.push(new ConversationPrompt({message: '', user_created:false}))
                }
                conversationRef.current = tempConversations
                setConversationDetails(tempConversations)
  
            }finally{
                //setPromptProcessing(false)
  
            }
            
        }else{
            setConversationDetails([])

        }
    }
  
    useEffect(() => {
        GetConversationDetails();

    }, [selectedConversation])

    useEffect(() => {
        /* register a consistent channel name for identifing this chat messages */
        const channelName = `ACCOUNT_ID_${account?.email}`
  
        /* subscribe to channel and register callback */        
        subscribe(channelName, (message: string) => {
            /* when a message is received just add it to the UI */
            
            if (message === 'END_OF_THE_STREAM_ENDER_GAME_42'){
                messageResponsePart.current = 0
            
                conversationRef.current.pop()
            
                //handleAssistantPrompt({prompt: messageRef.current})
                setConversationDetails([...conversationRef.current, new ConversationPrompt({message: `${messageRef.current}`, user_created:false})])
                console.log([...conversationRef.current, new ConversationPrompt({message: `${messageRef.current}`, user_created:false})])
                messageRef.current = ''
                setStateMessage('')
                setIsGeneratingMessage(false)
            }
            else if (message === 'START_OF_THE_STREAM_ENDER_GAME_42'){
                conversationRef.current = conversationDetails
                setIsGeneratingMessage(true)
                messageResponsePart.current = 2
  
            }else if (message === 'CONVERSATION_ID'){
                setIsGeneratingMessage(true)
                messageResponsePart.current = 1
            }else{
                setIsGeneratingMessage(true)
                if (messageResponsePart.current === 1){
                    // this has to do with the conversation id
                    if(!selectedConversation){
                        setSelectedConversation(Number(message))
                    }   
                }
                else if (messageResponsePart.current === 2){
                    messageRef.current += message
                    setStateMessage(messageRef.current)
  
                }
            }
            
        })
  
        return () => {
            /* unsubscribe from channel during cleanup */
            unsubscribe(channelName)
        }
    }, [account, subscribe, unsubscribe, conversationDetails])


    return(
        <MessageContext.Provider value={{stateMessage, setStateMessage, conversationDetails, setConversationDetails, isGeneratingMessage}}>
            {children}
        </MessageContext.Provider>
    )

}

export { MessageContext, MessageProvider}