import React, { Dispatch, PropsWithChildren, SetStateAction, useContext, useEffect, useState } from 'react';
import { MOCK_ACCOUNTS, MOCK_ANNOUNCEMENTS, MOCK_CONVERSATION } from '../../mockData';
import Footer from '../../components/Footer/Footer';
import Header from '../../components/Header/Header';
import { Account, Announcement, AnnouncementType, Conversation, ConversationPrompt, ConversationPromptType, ConversationType } from '../../data';
import { AccountContext } from '../../contexts/AccountContext';
import { axiosInstance } from '../../../axiosApi';
import { AxiosResponse } from 'axios';
import { Form, Formik } from 'formik';
import { object, ref, string } from 'yup';
import { Button, ButtonBase, Card, CardContent, CardHeader } from '@mui/material';
import CustomTextField from '../../components/CustomTextField/CustomTextField';
import ConversationLog from '../../components/ConversationLog/ConversationLog';
import ConversationDetailCard from '../../components/ConversationDetailCard/ConversationDetailCard';

export type PromptValues = {
    prompt: string;
};
const validationSchema = object().shape({

})

interface ConfirmEntryProps {
    status: string;
    message: string;
}

const AnnouncementBadge = ({status, message}: PropsWithChildren<ConfirmEntryProps>): JSX.Element => {
    console.log(message)
    return(
        <div className={`alert alert-${status}`}>
            { message }
        </div>
    )
}





type ConversationDetailProps = {
    selectedConversation: number | undefined
    conversationTitle: string | undefined
    conversations: Conversation[]
    setConversations: React.Dispatch<React.SetStateAction<Conversation[]>>
    setSelectedConversation: React.Dispatch<React.SetStateAction<number | undefined>>
};

interface IResponseObject {
    role: string;
    content: string;
}

const ConversationDetail = ({selectedConversation, conversationTitle,conversations, setConversations, setSelectedConversation}: ConversationDetailProps): JSX.Element => {
    const [conversationDetails, setConversationDetails] = useState<ConversationPrompt[]>([])
    const [promptProcessing, setPromptProcessing] = useState<boolean>(false);
    
    useEffect(() => {
        // now we want to stream the new response
        const eventSource = new EventSource("http://127.0.0.1:8011/api/streamed_response")
        try{
            
            eventSource.onmessage = (event) => {
                const responseObject = JSON.parse(event.data)
                console.log(responseObject)
                setResponse((prev: IResponseObject)=>{
                    const responseRole  = responseObject["role"] || "";
                    const responseContent  = responseObject["content"] || "";
                    const combinedObject = {
                        role: prev.role + responseRole,
                        content: prev.content + responseContent
                    }
                    return combinedObject
                })
            }
            eventSource.onerror = (error) =>  {
                console.log(error)
            }

        }finally{
            eventSource.close()
        }
    }, [])
    
    async function GetConversationDetails(){
        if(selectedConversation){
            
            try{
                setPromptProcessing(true)
                const {data, }: AxiosResponse<ConversationPromptType[]> = await axiosInstance.get(`conversation_details?conversation_id=${selectedConversation}`)
                console.log(data)
                setConversationDetails(data.map((item) => new ConversationPrompt({
                    message: item.message,
                    user_created: item.user_created,
                    created_timestamp: item.created_timestamp
                })))

            }finally{
                setPromptProcessing(false)

            }
            
        }
    }

    useEffect(() => {
        GetConversationDetails();
    }, [selectedConversation])

    const [response, setResponse] = useState<IResponseObject>({role: '', content: ''})

    const handlePromptSubmit = async ({prompt}: PromptValues): Promise<void> => {
        setConversationDetails([...conversationDetails, new ConversationPrompt({message: prompt, user_created:true})])
        try{
            setPromptProcessing(true)
            if(!selectedConversation){
                const {data, }: AxiosResponse<ConversationType> = await axiosInstance.post('/conversations', {
                    prompt: prompt
                })
                // add the conversation to the list
                setConversations([...conversations, new Conversation({title: data.title, id: data.id})])
                // set the conversation as the selected one
                // TODO
                setSelectedConversation(data.id)
                
                
            }
            console.log(selectedConversation)
            const {data }: AxiosResponse<ConversationPromptType> = await axiosInstance.post('/conversation_details', {
                prompt: prompt,
                conversation_id: selectedConversation
            })
            console.log(data)
            
                setConversationDetails([...conversationDetails, new ConversationPrompt({
                    message: data.message,
                    user_created: data.user_created,
                    created_timestamp: data.created_timestamp
                })] )

            
            

            
        }finally{
            setPromptProcessing(false)
        }
        // try{
            
        //     setConversationDetails([...conversationDetails, new ConversationPrompt({
        //         message: prompt,
        //         user_created: true,
        //     })])
        //     const {data,  }: AxiosResponse<ConversationPromptType[]> = await axiosInstance.post('/conversation_details', {
        //         prompt: prompt,
        //         conversation_id: selectedConversation ? selectedConversation : -1
        //     })
        //     setConversationDetails(data.map((item) => new ConversationPrompt({
        //         message: item.message,
        //         user_created: item.user_created,
        //         created_timestamp: item.created_timestamp
        //     })))

        // }catch(error){
        //     console.log(error)
        // }
    }

    

    // we have conversation details here
    
    
    return (
        <div className='col-lg-8 col-md-6 col-sm-12 right-column'>
            <div className="card" style= {{height: 'auto'}}>
                <div className='card-header'>
                        <div className='bg-gradient-dark shadow-dark border-radius-lg py-3 pe-1'>
                            <h5 className='text-white'>
                                {selectedConversation ? conversationTitle : 'Conversation Detail'}
                                </h5>
                        </div>
                    </div>
                <div className="card-body">
                    {selectedConversation ?
                    conversationDetails.map((convo_detail) => <ConversationDetailCard message={convo_detail.message} user_created={convo_detail.user_created}/>)
                    :
                    <p>Either select a previous conversation on start a new one.</p>
                    }
                </div>
                <div className='card-footer'>
                    
                    <Formik
                    initialValues={{
                        prompt: '',
                    }}
                    onSubmit={handlePromptSubmit}
                    validationSchema={validationSchema}
                    >
                        {(formik) => 
                                <Form>
                            <div className='row' style={{
                                position: 'sticky',
                                bottom: 0
                            }}>
                                <div className='col-10'>
                                    <CustomTextField label='Prompt' name='prompt' changeHandler={(e) => formik.setFieldValue('prompt',e.target.value)} isMultline={true}/>
                                    

                                </div>
                                <div className='col-2'>
                                    <Button
                                    type={'submit'}
                                    disabled={promptProcessing}
                                    >Send

                                    </Button>
                                </div>
                            </div>
                        </Form>
                        }

                    </Formik>
                        
                    
                </div>
            </div>
        </div>
    );
}

// assume that we are using the first account at this point

const Dashboard = ({}): JSX.Element => {
    const [announcements, setAnnouncement] = useState<Announcement[]>([]);
    const { account, setAccount} = useContext(AccountContext);
    const [conversations, setConversations] = useState<Conversation[]>([]);
    const [selectedConversation, setSelectedConversation] = useState<number | undefined>(undefined);
    
    

    async function GetAnnouncements(){
        const response: AxiosResponse<AnnouncementType[]> = await axiosInstance.get('announcment/get/')
        setAnnouncement(response.data.map((status, message) => new Announcement({
            status: status,
            message: message
        })))

    }

    async function GetConversations(){
        const {data, }: AxiosResponse<ConversationType[]> = await axiosInstance.get(`conversations`)
        setConversations(data.map((item) => new Conversation({
            id: item.id,
            title: item.title
        })))        
    }

    useEffect(() => {
        GetAnnouncements();
        GetConversations();
    }, [selectedConversation])

    
    const conversationTitle = selectedConversation ? conversations.find(item => item.id === selectedConversation)?.title : 'New Conversation';
    
  return (
    <div className='main-content' style={{'height': '100%', minHeight: '100vh', display: 'flex', flexDirection: 'column'}}>
        <div className='container-fluid'>
            <div className='row'>
                <div className='col-12' style={{
                    position: 'sticky',
                    top: 0,
                }}>
                    <Header />

                </div>
            </div>
        </div>
        { announcements.map((x) => <AnnouncementBadge status={x.status} message={x.message} />)}
        <div className='row flex-fill'>
            {/* <ConversationLog conversations={conversations} setSelectConversation={setSelectedConversation}/> */}
            <ConversationDetail selectedConversation={selectedConversation} conversationTitle={conversationTitle} setConversations={setConversations} conversations={conversations} setSelectedConversation={setSelectedConversation}/>
                
        </div>
    
    
    
  
    
        <Footer />
    </div>
  );
};

export default Dashboard;