<template>
    <div class="ai-content-wrap">
        <div class="window-list-wrap">
            <div class="window-title">
                <div class="title-wrap">
                    <p class="text-ellipsis" style="color: #333333;font-size: 20px;font-weight: 600;">{{companyName}}</p>
                    <span style="color: #666666;font-size: 16px;">{{$t('ToolBox.AIQuestion.title')}}</span>
                </div>
                <div class="icon"><img src="~@/assets/img/icons/ai_company.png"/></div>
            </div>
            <div class="add-btn" @click="handleAddNewWindow"><i class="el-icon-circle-plus-outline"></i>{{$t('ToolBox.AIQuestion.add_new_window')}}</div>
            <div class="list-wrap hidden-scrollbar">
                <Window-List-Item 
                    ref="windowListItem"
                    v-for="item in windowList" :key="item.AiChatTopicId"
                    :activeWindowId="activeWindowId"
                    :item="item"
                    @click.native="changeActiveWindow(item)"
                    @changeEdit="changeWindowTitle"
                    @delete="deleteWindowItem"
                />
                <div class="empty-list" v-if="windowList.length===0">
                    <img src="~@/assets/img/ai_m/empty_list.png" />
                </div>
            </div>
        </div>
        <div class="content-wrap">
            <div class="content-header">
                <div class="title-wrap">
                    <p>{{activeWindowId<=0?$t('ToolBox.AIQuestion.new_window'):activeWindow.TopicName||''}}</p>
                    <span>{{activeWindowId<=0?$t('ToolBox.AIQuestion.AI_use_intro'):`${historyList.length||0} messages`}}</span>
                </div>
            </div>
            <!-- 仅这一部分滚动 -->
            <div class="window-content-wrap hidden-scrollbar">
                <div class="content-item" v-for="item in historyList" :key="item.AiChatId" >
                    <!-- user 提问 -->
                    <Message-Item :messageInfo="formatMsg(item,'user')"
                        @startTyping="handleStartTyping"
                        @finishedTyping="handleFinishedTyping"
                    />
                    <!-- 模型回答 -->
                    <Message-Item :messageInfo="formatMsg(item,'model')"
                        @startTyping="handleStartTyping"
                        @finishedTyping="handleFinishedTyping"
                    />
                </div>
                <New-Window-Hint v-if="activeWindowId===0" />
            </div>
            <div class="input-box" id="input-box">
                <div class="upload-row">
                    <el-upload
                    style="display: inline-block; margin-right: 8px"
                    accept=".pptx,.pdf,.docx"
                    action=""
                    :http-request="handleUpload"
                    :before-upload="handleBeforeUpload"
                    :show-file-list="false"
                    :disabled="startUploadAudio">
                        <img src="~@/assets/img/icons/ai-upload.png" />
                    </el-upload>
                    <span>{{ $t('ToolBox.AIQuestion.support_formats') }}：PDF、PPTX、DOCX；{{ $t('ToolBox.AIQuestion.max_file_text') }}</span>
                </div>
                <textarea rows="6" v-model="inputText" :placeholder="$t('ToolBox.AIQuestion.input_placeholder')" @keydown.enter="handleSendMsg"></textarea>
                <div class="send-btn" @click="handleSendMsg"><img src="~@/assets/img/ai_m/send.png" />{{$t('ToolBox.AIQuestion.send_btn')}}</div>
            </div>
        </div>
    </div>
</template>

<script>
/* components */
import MessageItem from './components/messageItem.vue';
import NewWindowHint from './components/newWindowHint.vue';
import WindowListItem from './components/windowListItem';
/* api */
import {aiQAInterence} from '@/api/modules/aiApi.js'; 
import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
export default {
    components: { WindowListItem,NewWindowHint, MessageItem },
    data() {
        return {
            /* window */
            activeWindowId:0,//当前激活的窗口id
            activeWindow:null,//当前激活窗口
            windowList:[],//窗口列表
            listWrapLoading:null,
            /* window-content*/
            historyList:[],//当前窗口历史记录
            inputText:'',
            model:'Kimi',//当前选择的模型
            modelOldValue:'',
            showHint:false,//选择模型提示
            isTyping:false,//是否处于打字动画中
            windowContentLoading:null,
            answerLoading:false,//回答中
            companyName:'',
            aiFileIds:[],
            // 上传窗口的队列
            windowSet:new Set(),
            fileTypeRule:new RegExp(/\.pdf|\.pptx|\.docx$/,'i')
        };
    },
    watch:{
        model(newVal,oldVal){
            this.modelOldValue = oldVal
        }
    },
    computed:{
    },
    methods: {
        //改变活跃窗口
        changeActiveWindow(item){
            if(item.AiChatTopicId===0){
                this.handleAddNewWindow()
                return 
            }
            if(item.AiChatTopicId===this.activeWindowId) return

            if(this.windowContentLoading&&this.windowContentLoading.visible){
                this.$message.warning('上个窗口未加载完成,请稍等')
                return
            }

            this.activeWindowId=item.AiChatTopicId
            this.activeWindow = this.windowList.find(i=>i.AiChatTopicId===item.AiChatTopicId)||{}
            this.historyList = []
            this.isTyping = false
            this.getWindowDetail()
        },
        //获取对话窗口具体信息
        getWindowDetail(){
            this.windowContentLoading = this.$loading({
                target:document.querySelector('.window-content-wrap'),
            });
            aiQAInterence.getTopicDetail({
                AiChatTopicId:this.activeWindowId
            }).then(res=>{
                if(res.Ret!==200) return
                const {List} = res.Data
                this.historyList = List||[]

                this.aiFileIds=this.historyList.map(item => item.OpenaiFileId).filter(Boolean)

                this.windowContentLoading&&this.windowContentLoading.close()
                //使用模型
                this.model = this.historyList.length?this.historyList[this.historyList.length-1].Model:'Kimi'
                //如果有历史记录,则滚动到底部
                this.windowContentToBottom()
            })
        },
        // 滚动到聊天窗口底部
        windowContentToBottom(){
            this.$nextTick(()=>{
                const windowContentWrap = document.querySelector('.window-content-wrap')
                windowContentWrap.scrollTo({
                    top:windowContentWrap.scrollHeight,
                    behavior:'smooth'
                })
            })
        },
        //格式化对话信息
        formatMsg(msg,type){
            let msgObj = {
                messageId:msg.AiChatId,
                messageTime:'',
                messageText:'',
                messageType:'',
                modelName:''
            }
            const {Ask,Answer,CreateTime,ModifyTime,isPlay,Model,OpenaiFilePath} = msg
            if(type==='user'){
                msgObj.messageText = Ask||''
                msgObj.messageType = 'question'
                msgObj.messageTime = CreateTime||''
                msgObj.askFileUrl = OpenaiFilePath || ''
            }
            else{
                msgObj.messageText = Answer||''
                msgObj.messageType = 'answer'
                msgObj.messageTime = ModifyTime||''
                msgObj.modelName = Model||''
                msgObj.isPlay = Boolean(isPlay)
                msgObj.askFileUrl = OpenaiFilePath || ''
            }
            return msgObj
        },
        //新建对话窗口
        handleAddNewWindow(){
            //禁止重复新建
            if(this.activeWindowId===0){
                this.$message.warning(this.$t('ToolBox.AIQuestion.add_new_window_hint'))
                return
            }
            //将相关值置空
            this.activeWindowId=0
            this.activeWindow=null
            this.historyList=[]
            this.model='Kimi'
            this.aiFileIds=[]
            this.isTyping = false
        },
        //开始播放动画
        handleStartTyping(){
            this.isTyping = true
        },
        //结束播放动画
        handleFinishedTyping(item){
            this.isTyping = false
            const {messageId} = item
            const index = this.historyList.findIndex(i=>i.AiChatId===messageId)
            index!==-1&&(this.historyList[index].isPlay = false)
        },
        //编辑对话窗口名称
        changeWindowTitle(title){
            aiQAInterence.editTopicName({
                AiChatTopicId:this.activeWindowId,
                TopicName:title
            }).then(res=>{
                if(res.Ret!==200) return 
                this.$message.success(/* '保存成功' */this.$t('MsgPrompt.saved_msg'))
                this.getWindowList()
            })
        },
        //删除对话窗口
        deleteWindowItem(){
            const index = this.windowList.findIndex(i=>i.AiChatTopicId===this.activeWindowId)||0
            //更改activeWindowId 
            /**
             * 一般情况:指向下一个
             * 若当前为最后一个,指向上一个
             * 如果是唯一一个,则置为0
             */
            let AiChatTopicId = 0
            if(this.windowList.length===1){
                AiChatTopicId=0
            }else if(index===this.windowList.length-1){
                AiChatTopicId = this.windowList[index-1].AiChatTopicId
            }else {
                AiChatTopicId = this.windowList[index+1].AiChatTopicId
            }
            aiQAInterence.deleteTopic({
                AiChatTopicId:this.activeWindowId
            }).then(res=>{
                if(res.Ret!==200) return 
                this.getWindowList()
                this.changeActiveWindow({AiChatTopicId})
            })
        },
        //点击模型选择框
        //发送消息
        handleSendMsg(e){
            e.preventDefault()
            if(e.shiftKey===true) {
                this.inputText+='\n'
                return
            }
            if(this.isTyping||this.answerLoading){
                this.$message.warning('请等待回答完成')
                return
            }
            //新建窗口,未选择模型
            if(this.inputText.length===0){
                this.$message.warning(this.$t('ToolBox.AIQuestion.inter_check'))
                return
            }
            this.answerLoading=true
            this.activeWindowId===0&&(this.activeWindowId = -1)
            //mock 加入到historyList中
            const msgObj = {
                AiChatId:-1,
                AiChatTopicId:this.activeWindowId || 0,
                Ask:this.inputText,
                Answer:'回答生成中...',
                CreateTime:'',
                ModifyTime:'',
                Model:this.model
            }
            this.historyList.push(msgObj)
            
            //滚动到底部
            this.windowContentToBottom()

            const inputText = this.inputText
            this.inputText = ''
            let apiName = "sendChatMsg"
            let params={
                AiChatTopicId:this.activeWindowId<=0?0:this.activeWindowId,
                Ask:inputText,
                Model:this.model
            }
            if(this.aiFileIds && this.aiFileIds.length>0){
                // 文件检索功能
                apiName="fileRetrieve"
                params.OpenaiFileId=this.aiFileIds
            }
            aiQAInterence[apiName](params).then(res=>{
                this.answerLoading=false
                //在回答未获取前切换了新窗口
                if(this.historyList.length===0){
                    this.getWindowList()
                    return
                }

                const msg = this.historyList[this.historyList.length-1]
                if(res.Ret!==200){
                    //提问失败
                    msg.Answer = res.ErrMsg||res.Msg||''
                    msg.isPlay = true
                    this.historyList.splice(this.historyList.length-1,1,msg)
                    return
                } 
                //提问成功,替换对应数据
                const {AiChatTopicId,Answer,Ask,Model} = res.Data
                if(this.activeWindowId<=0){
                    const windowItem = {
                        AiChatTopicId:AiChatTopicId||0,
                        TopicName:Ask,
                    }
                    this.windowList.push(windowItem)
                    this.activeWindow = windowItem
                    this.getWindowList()
                }
                //在回答未获取前切换了已有窗口
                if(this.activeWindowId>0&&this.activeWindowId!==AiChatTopicId) return

                this.activeWindowId = AiChatTopicId||0
                msg.Answer = Answer||''
                msg.Model = Model
                msg.isPlay = true
                this.historyList.splice(this.historyList.length-1,1,msg)
            }).catch(()=>{
                this.answerLoading=false
                const msg = this.historyList[this.historyList.length-1]
                msg.Answer = '回答超时，请重试！'
                msg.isPlay = true
                this.historyList.splice(this.historyList.length-1,1,msg)
            })
        },
        //获取窗口列表
        /**
         * @param {*} topicId AiChatTopicId 定位到具体窗口
         */
        getWindowList(topicId){
            this.listWrapLoading = this.$loading({
                target:document.querySelector('.list-wrap'),
                background: 'rgba(244, 245, 249, 1)'
            });
            aiQAInterence.getTopicList().then(res=>{
                if(res.Ret!==200) return
                this.windowList = res.Data.List||[]
                if(topicId){
                    this.changeActiveWindow({AiChatTopicId:topicId})
                }
                this.listWrapLoading&&this.listWrapLoading.close()
            })
        },

        getBaseConfig(){
            etaBaseConfigInterence.getBaseConfig().then(res=>{
                if(res.Ret===200){
                    this.companyName=res.Data.CompanyName||''
                }
            })
        },
        inputBoxDragover(event){
            event.preventDefault(); //阻止默认行为，允许放置
        },
        inputBoxDrop(event){
            event.preventDefault(); //阻止浏览器默认行为
            // 获取文件的数据
            const DataTransferItemList = event.dataTransfer.files
            if(DataTransferItemList && DataTransferItemList.length){
                if(DataTransferItemList.length>1){
                    return this.$message.error("单次只能上传一个文件，请重试");
                }else{
                    let file = DataTransferItemList[0]
                    if(file.type && this.fileTypeRule.test(file.name)){
                        if(file.size/1024/1024 > 50.1){
                            this.$message.error("上传文件大小不超过50MB");
                            return false;
                        }
                        this.handleUpload({file})
                    }else{
                        return this.$message.error("上传文件格式只支持PDF、PPTX、DOCX");
                    }
                }
            }else{
                // 没有文件数据
                let txt = event.dataTransfer.getData("text/plain")
                this.inputText=txt
            }
        },
        handleBeforeUpload(e) {
            if(!this.fileTypeRule.test(e.name)){
                this.$message.error("上传文件格式只支持PDF、PPTX、DOCX");
                return false;
            }
            if(!(e.size/1024/1024 < 50.1)){
                this.$message.error("上传文件大小不超过50MB");
                return false;
            }
        },
        handleUpload(e){
            if(this.windowSet.has(this.activeWindowId)){
                return this.$message.warning("请等待文件上传完成")
            }

            let {file} = e
            let downloadHint = this.$message({
                type:"info",
                message:/* '上传中，请稍后······' */this.$t('ReportManage.CloudPage.upload_msg'),
                duration:0,
                iconClass:'el-icon-loading'
            })
            let formData = new FormData()
            formData.append('File',file)
            formData.append('AiChatTopicId',this.activeWindowId)
            formData.append('Model',this.model)
            this.windowSet.add(this.activeWindowId)
            aiQAInterence.fileUpload(formData).then(res=>{
                downloadHint.close()
                if(res.Ret == 200){
                    let Data = res.Data || {}
                    this.$message.success(`${Data.ResourceName}上传成功`)
                    if(this.windowList.find(item => item.AiChatTopicId == Data.AiChatTopicId)){
                        // 窗口存在
                        this.windowSet.delete(Data.AiChatTopicId)

                        if(Data.AiChatTopicId == this.activeWindowId){
                            this.aiFileIds.push(Data.OpenaiFileId)
                            const msgObj = {
                                AiChatId:Data.AiChatId || -1,
                                AiChatTopicId:Data.AiChatTopicId,
                                Ask:Data.ResourceName,
                                OpenaiFilePath:Data.ResourceUrl,
                                Answer:Data.Answer || '',
                                CreateTime:Data.CreateTime||'',
                                ModifyTime:Data.ModifyTime || '',
                                Model:this.model
                            }
                            this.historyList.push(msgObj)
                            this.windowContentToBottom()
                        }
                    }else{
                        //窗口不存在
                        this.windowSet.delete(0)
                        this.getWindowList(this.activeWindowId==0 ? Data.AiChatTopicId:0)
                    }
                }
            }).catch(()=>{
                downloadHint.close()
                // 失败，清空
                this.windowSet.clear()
            })
        }
    },
    mounted(){
        this.getWindowList()
        this.getBaseConfig()
        const dropDom = document.getElementById('input-box')
        dropDom.addEventListener('dragover',this.inputBoxDragover);

        dropDom.addEventListener('drop',this.inputBoxDrop);
    },
    beforeDestroy(){
        const dropDom = document.getElementById('input-box')
        dropDom.removeEventListener('dragover',this.inputBoxDragover);

        dropDom.removeEventListener('drop',this.inputBoxDrop);
    }
};
</script>

<style lang="scss">
.ai-content-wrap{
    .el-select.hint{
        .el-input.is-focus .el-input__inner{
            border-color: red;
        }
        .el-input__inner:focus{
            border-color: red;
        }
    }
}
</style>
<style scoped lang="scss">
$border-color:#3D52A1;
.ai-content-wrap{
    width:calc(100% - 64px);
    height:calc(100% - 64px);
    display: flex;
    position:relative;
    margin:30px;
    border:1px solid $border-color;
    border-radius: 32px;
    overflow: hidden;
    min-width: 960px;
    .window-list-wrap{
        width:380px;
        border-right: 1px solid #E2E2E2;
        padding:30px;
        box-sizing: border-box;
        background-color: #F4F5F9;
        display: flex;
        flex-direction: column;
        .window-title{
            display: flex;
            justify-content: space-between;
            align-items: center;
            .icon img{
                width:58px;
                height:58px;
            }
            .title-wrap{
                overflow: hidden;
            }
            .text-ellipsis{
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
            }
        }
        .add-btn{
            border:2px dashed $border-color;
            border-radius:16px;
            padding:14px;
            margin-top:40px;
            text-align: center;
            font-size: 16px;
            color:#333333;
            cursor: pointer;
            background-color: #F4F5F9;
            transition: background-color .5s, color .5s;
            &:hover{
                background-color: white;
                color: $border-color;
                border-style: solid;
                i{
                    color: $border-color;
                }
            }
            i{
                margin-right: 10px;
                font-weight: bold;
                font-size: 16px;
            }
        }
        .list-wrap{
            margin-top:30px;
            flex: 1;
            overflow-y: scroll;
            position:relative;
            .empty-list img{
                width:150px;
                height:150px;
                margin:0 auto;
                display: block;
            }
        }
    }
    .content-wrap{
        flex: 1;
        display: flex;
        flex-direction: column;
        min-width: 588px;
        .content-header{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding:20px 30px;
            box-sizing: border-box;
            border-bottom: 1px solid #E2E2E2;
            .title-wrap{
                p{
                    color: #333333;
                    font-size: 18px;
                    margin-bottom: 5px;
                }
                span{
                    color: #999999;
                    line-height: 18px;
                }
            }
        }
        .window-content-wrap{
            flex: 1;
            padding:30px;
            text-align: center;
            overflow-y: scroll;
            overflow-x:hidden;
            position:relative;
            .content-item{
                text-align: left;
                .item{
                    width: 100%;
                    display: flex;
                    padding:15px 0;
                    border-bottom: 1px solid black;
                    .content-item-avatar{
                        width: 50px;
                        margin-right: 20px;
                        img{
                            width:38px;
                            height:38px;
                        }
                    }
                    .text{
                        flex: 1;
                    }
                }
            }
        }
        .input-box{
            padding:12px 30px 30px;
            position: relative;
            .upload-row{
                display: flex;
                align-items: center;
                padding: 0 20px;
                margin-bottom: 12px;
                img{
                    height: 20px;
                    width: 20px;
                    vertical-align: bottom;
                    box-shadow: 3px 3px 8px 0px #182c421f;
                }
                span{
                    color: #A5A5A5;
                    font-size: 15px;
                    font-weight: 400;
                }
            }
            textarea{
                width:100%;
                border-radius: 16px;
                box-sizing: border-box;
                padding:20px 95px 20px 20px;
                font-size: 16px;
                resize: none;
                border-color: #E3E3E3;
                box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.08);
            }
            .send-btn{
                position:absolute;
                bottom:50px;
                right:50px;
                padding:8px 12px;
                background-color: $border-color;
                border-radius: 6px;
                font-size: 14px;
                color: white;
                line-height: 14px;
                cursor: pointer;
                opacity: .7;
                transition: opacity .5s;
                img{
                    width:14px;
                    height:14px;
                    margin-right: 8px;
                }
                &:hover,&.canClick{
                    opacity: 1;
                }
            }
        }
    }
    .hidden-scrollbar{
        &::-webkit-scrollbar-track{
            display: none;
        }
        div::-webkit-scrollbar-track{
            display: none;
        }
    }
}
</style>
