// main.js – index.html 전체 SPA 로직(jQuery 기반)
// 핵심 기능: 도구 목록 로드, 채팅 페이지 렌더, 파일 사이드바, 세션/메시지 관리 등.
// 코드가 600+ 라인으로 길기 때문에 함수별 세부 주석은 추후 리팩터링 시 모듈 분할과 함께 추가 권장.
// 여기서는 상단 설명만 삽입한다.
// -----------------------------------------------------------------------------
$(function() {
    // 도구 데이터 (서버에서 동적으로 가져옴)
    let tools = [];
    let favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
    
    // 현재 선택된 도구와 세션
    let currentTool = null;
    let currentSessionId = null;
    
    // 도구별 채팅 메시지 저장소 { sessionId: messages[] }
    let toolChatMessages = {};
    // 도구별 마지막 세션 ID를 기억해 도구를 다시 선택했을 때 복원
    let lastSessionPerTool = {};
    // 업로드 progress interval 저장소 {placeholderId: intervalId}
    let uploadIntervals = {};

    // IME 조합 상태 플래그
    let isComposing = false;
    let enterPressedWhileComposing = false;

    // IME 조합 시작/종료 이벤트 등록
    $('.chat-input').on('compositionstart', function() {
        isComposing = true;
    });
    $('.chat-input').on('compositionend', function(e) {
        isComposing = false;
        // 조합 중 Enter가 눌렸다면, 조합 끝난 후 전송
        if (enterPressedWhileComposing) {
            enterPressedWhileComposing = false;
            sendChat();
        }
    });

    // 도구 목록 가져오기
    async function loadTools() {
        try {
            const response = await fetch('http://localhost:8010/tools');
            if (response.ok) {
                const toolsData = await response.json();
                tools = toolsData.map(tool => {
                    // 도구 유형(오픈AI / 내부AI)에 따라 카테고리 지정
                    const category = ['전체'];
                    if (tool.id === 'dev_chatbot' || tool.id === 'chatgpt' || tool.id === 'doc_translation') {
                        category.push('오픈AI');
                    } else if ([
                        'chatbot_gxp',
                        'lims_text2sql',
                        'research_qa'
                    ].includes(tool.id)) {
                        category.push('내부AI');
                    }
                    return {
                        ...tool,
                        category,
                        id: tool.id
                    };
                });
                renderTools('all');
                // 도구 자동 선택 (최초 진입 시)
                if (tools.length > 0 && !currentTool) {
                    selectTool(tools[0].id);
                }
            } else {
                console.error('도구 목록을 가져오는데 실패했습니다.');
            }
        } catch (error) {
            console.error('도구 목록 로드 오류:', error);
        }
    }

    async function loadFileList() {
        try {
            const res = await fetch('http://localhost:8010/files');
            const data = await res.json();
            const $list = $('.file-list');
            $list.empty();
            data.files.forEach(f => {
                let display = f;
                const parts = f.split("_");
                if(parts.length>1 && /^\d{17,}$/.test(parts[0])){
                    display = parts.slice(1).join("_");
                }
                $list.append(`<li data-fname="${f}" title="${display}"><span>${display}</span><button class="file-del-btn" data-fname="${f}">✕</button></li>`);
            });
        } catch(e) { console.error('파일 목록 로드 오류', e); }
    }

    // 문서번역 파일 리스트 로드
    async function loadDocTranslationFileList() {
        try {
            const res = await fetch('http://localhost:8010/doc_translation/files');
            const data = await res.json();
            const $list = $('.file-list');
            $list.empty();
            
            // 파일 추가 버튼의 기능을 Word 파일 업로드로 변경
            $('.file-add-btn').off('click').on('click', function() {
                const input = $('<input type="file" accept=".doc,.docx" multiple style="display:none;">');
                $('body').append(input);
                input.on('change', function() {
                    uploadDocTranslationFiles(this.files);
                    $(this).remove();
                });
                input.click();
            });

            data.forEach(file => {
                // 실제 파일명 추출 함수
                function extractRealFilename(filename) {
                    // 패턴: [doc_translation]_admin_YYYYMMDDHHMMSS[fff]_실제파일명
                    const regex = /^\[doc_translation\]_admin_\d{14,17}_(.+)$/;
                    const match = filename.match(regex);
                    return match ? match[1] : filename;
                }

                let displayName = extractRealFilename(file.filename);

                let listItem = '';
                if (file.has_result) {
                    // 결과 파일명도 정리
                    let resultDisplayName = extractRealFilename(file.result_filename);

                    // 번역 완료된 파일 - 원본 파일명과 결과 파일명을 세로로 표시
                    listItem = `
                        <li class="translation-result-item" data-fname="${file.filename}" title="${displayName}">
                            <div class="file-item-content">
                                <div class="original-file">${displayName}</div>
                                <div class="result-file">   → ${resultDisplayName}</div>
                                <div class="file-actions">
                                    <a href="#" class="download-original-link" data-original-fname="${file.filename}">[원본다운]</a>
                                    <a href="#" class="download-result-link" data-result-fname="${file.result_filename}">[결과다운]</a>
                                    <button class="file-del-btn" data-fname="${file.filename}">✕</button>
                                </div>
                            </div>
                        </li>
                    `;
                } else {
                    // 번역 중인 파일 - 파일명 숨김
                    listItem = `
                        <li data-fname="${file.filename}" title="번역중...">
                            <span class="translating">번역중...</span>
                            <button class="file-del-btn" data-fname="${file.filename}">✕</button>
                        </li>
                    `;
                }
                $list.append(listItem);
            });
        } catch(e) { 
            console.error('문서번역 파일 목록 로드 오류', e); 
        }
    }

    // Word 파일 업로드 함수
    async function uploadDocTranslationFiles(files) {
        if (!files || files.length === 0) return;

        // MS Word 파일 검증
        for (let file of files) {
            if (!file.name.toLowerCase().endsWith('.doc') && !file.name.toLowerCase().endsWith('.docx')) {
                alert('MS Word 파일(.doc, .docx)만 업로드 가능합니다.');
                return;
            }
        }

        const formData = new FormData();
        for (let file of files) {
            formData.append('files', file);
        }

        try {
            // 업로드 시작 시 로딩 상태 표시
            const $fileList = $('.file-list');
            const loadingItem = $('<li class="uploading-item"><span class="translating">업로드 및 번역 중...</span></li>');
            $fileList.prepend(loadingItem);

            const response = await fetch('http://localhost:8010/doc_translation/upload_doc', {
                method: 'POST',
                body: formData
            });

            const result = await response.json();
            
            // 로딩 아이템 제거
            loadingItem.remove();
            
            if (result.status === 'success') {
                // 업로드와 번역이 동기적으로 완료됨 - 즉시 완료 상태로 표시
                loadDocTranslationFileList(); 
            } else {
                alert('파일 업로드에 실패했습니다: ' + (result.detail || '알 수 없는 오류'));
            }
        } catch (error) {
            // 로딩 아이템 제거
            $('.uploading-item').remove();
            console.error('파일 업로드 오류:', error);
            alert('파일 업로드 중 오류가 발생했습니다.');
        }
    }

    // --- PDF 뷰어 로딩 오버레이 표시/숨김 유틸 ---
    function showPdfLoading() {
        const $slide = $('.file-slide');
        let $overlay = $slide.find('.file-loading-overlay');
        if ($overlay.length === 0) {
            $overlay = $('<div class="file-loading-overlay">로딩중…</div>');
            $slide.append($overlay);
        }
        $overlay.show();
        $('.file-viewer').hide();
    }
    function hidePdfLoading() {
        $('.file-loading-overlay').hide();
        $('.file-viewer').show();
    }

    // 삭제 버튼 클릭 (동적으로 처리 - 도구에 따라 다른 엔드포인트 사용)
    $('.file-list').on('click', '.file-del-btn', async function(e) {
        e.stopPropagation();
        const fname = $(this).data('fname');
        
        // 문서번역의 경우 실제 파일명만 표시
        let displayName = fname;
        if (currentTool && currentTool.id === 'doc_translation') {
            // 실제 파일명 추출 함수
            function extractRealFilename(filename) {
                const regex = /^\[doc_translation\]_admin_\d{14,17}_(.+)$/;
                const match = filename.match(regex);
                return match ? match[1] : filename;
            }
            displayName = extractRealFilename(fname);
        }
        
        if(!confirm(displayName + ' 파일을 삭제하시겠습니까?')) return;
        try {
            let deleteUrl;
            if (currentTool && currentTool.id === 'doc_translation') {
                deleteUrl = `http://localhost:8010/doc_translation/files/${encodeURIComponent(fname)}`;
            } else {
                deleteUrl = `http://localhost:8010/file?filename=${encodeURIComponent(fname)}`;
            }
            
            const res = await fetch(deleteUrl, { method: 'DELETE' });
            const data = await res.json();
            if(data.status==='success') {
                if (currentTool && currentTool.id === 'doc_translation') {
                    loadDocTranslationFileList();
                } else {
                    loadFileList();
                }
                // 슬라이드가 해당 파일이라면 닫기
                if($('.file-slide.show').length && $('.file-slide-content').text().includes(fname)) {
                    $('.file-slide').removeClass('show');
                }
            } else {
                alert('삭제 실패: '+data.message);
            }
        } catch(err){ alert('삭제 오류: '+err); }
    });

    // 문서번역 원본 파일 다운로드 링크 클릭
    $('.file-list').on('click', '.download-original-link', async function(e) {
        e.preventDefault();
        e.stopPropagation();
        const originalFilename = $(this).data('original-fname');
        
        // 실제 파일명 추출 함수
        function extractRealFilename(filename) {
            const regex = /^\[doc_translation\]_admin_\d{14,17}_(.+)$/;
            const match = filename.match(regex);
            return match ? match[1] : filename;
        }
        
        try {
            const response = await fetch(`http://localhost:8010/doc_translation/download/${encodeURIComponent(originalFilename)}`);
            if (response.ok) {
                const blob = await response.blob();
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = extractRealFilename(originalFilename); // 실제 파일명으로 다운로드
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            } else {
                alert('원본 파일 다운로드에 실패했습니다.');
            }
        } catch (error) {
            console.error('원본 파일 다운로드 오류:', error);
            alert('원본 파일 다운로드 중 오류가 발생했습니다.');
        }
    });

    // 문서번역 결과 다운로드 링크 클릭
    $('.file-list').on('click', '.download-result-link', async function(e) {
        e.preventDefault();
        e.stopPropagation();
        const resultFilename = $(this).data('result-fname');
        
        // 실제 파일명 추출 함수
        function extractRealFilename(filename) {
            const regex = /^\[doc_translation\]_admin_\d{14,17}_(.+)$/;
            const match = filename.match(regex);
            return match ? match[1] : filename;
        }
        
        try {
            const response = await fetch(`http://localhost:8010/doc_translation/download/${encodeURIComponent(resultFilename)}`);
            if (response.ok) {
                const blob = await response.blob();
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = extractRealFilename(resultFilename); // 실제 파일명으로 다운로드
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            } else {
                alert('결과 파일 다운로드에 실패했습니다.');
            }
        } catch (error) {
            console.error('결과 파일 다운로드 오류:', error);
            alert('결과 파일 다운로드 중 오류가 발생했습니다.');
        }
    });

    // 파일 클릭 -> 슬라이드 열기 (파일 내용 확인 요청은 실패해도 뷰어 열기)
    $('.file-list').off('click', 'li').on('click', 'li', async function() {
        const fname = $(this).data('fname');
        const url = `http://localhost:8010/pdf?filename=${encodeURIComponent(fname)}`;

        const $viewer = $('.file-viewer');

        // 로딩 오버레이 표시
        showPdfLoading();

        // 로드 완료 시 오버레이 숨김
        $viewer.off('load').on('load', function() {
            hidePdfLoading();
        });

        // PDF 로드 시작
        $viewer.attr('src', url);
        $('.file-slide').css('display','block').addClass('show');

        // 백그라운드로 파일 존재 여부를 확인하여 오류시 알림
        try {
            const res = await fetch(`http://localhost:8010/file_content?filename=${encodeURIComponent(fname)}`);
            const data = await res.json();
            if (data.status !== 'success') {
                console.warn('파일 내용 조회 실패:', data.message);
            }
        } catch(err) {
            console.error('파일 내용 조회 오류:', err);
        }
    });

    // 닫기 버튼
    $('.file-slide').on('click', '.file-slide-close', function() {
        $('.file-slide').removeClass('show').css('display','none');
    });

    // 슬라이드 종료(배경 클릭)
    $('.file-slide').click(function(e) {
        if (e.target === this) {
            $(this).removeClass('show').css('display','none');
        }
    });

    // 출처 링크 클릭 시: 기존 뷰어가 열려 있으면 닫았다가 새로 열어 원하는 페이지로 이동
    $('.chat-center').off('click', '.ref-link').on('click', '.ref-link', function(e){
        e.preventDefault();

        const fname = $(this).data('fname');
        const page = $(this).data('page');
        const url = `http://localhost:8010/pdf?filename=${encodeURIComponent(fname)}#page=${page}`;

        const $slide = $('.file-slide');
        const $viewer = $('.file-viewer');

        // 슬라이드가 이미 열려 있으면 우선 닫기 (애니메이션 제거 목적)
        if ($slide.hasClass('show')) {
            $slide.removeClass('show').css('display', 'none');
        }

        // 로딩 오버레이 표시
        showPdfLoading();

        // 먼저 blank 로드로 강제 새로고침
        $viewer.off('load');
        $viewer.attr('src', 'about:blank');

        // PDF 로드 시작 (약간의 딜레이 후 실행)
        setTimeout(() => {
            $viewer.off('load').on('load', function() {
                hidePdfLoading();
            });
            $viewer.attr('src', url);
            $slide.css('display', 'block').addClass('show');
        }, 50);
    });

    // 채팅 메시지 렌더링 함수 (loading 타입 처리)
    function renderChatMessages(autoScroll=false) {
        const $chatCenter = $('.chat-center');
        $chatCenter.empty();
        
        if (!currentTool) {
            $chatCenter.append(`
                <div class="chat-logo"></div>
                <div class="chat-title">엔큐톡</div>
                <div class="chat-subtitle">도구를 선택하여 채팅을 시작하세요</div>
            `);
            return;
        }

        // iframe을 사용하는 도구 매핑
        const iframeTools = {
            'research_qa': 'http://yongin-qa-chatbot.daewoongai.com/',
            'lims_text2sql': 'http://3.38.184.255:8080/'
        };

        if (iframeTools[currentTool.id]) {
            $('.chat-input-wrapper').hide();
            $chatCenter.addClass('iframe-mode');
            $chatCenter.append(`<iframe src="${iframeTools[currentTool.id]}" class="external-iframe"></iframe>`);
            return;
        } else {
            $('.chat-input-wrapper').show();
            $chatCenter.removeClass('iframe-mode');
        }

        $chatCenter.append(`
            <div class="tool-chat-header">
                <div class="tool-chat-title">${currentTool.name}</div>
                <div class="tool-chat-desc">${currentTool.description}</div>
            </div>
        `);
        
        // 현재 세션 메시지 출력
        const sessionKeyToShow = getMsgKey(currentTool.id, currentSessionId);
        if (toolChatMessages[currentTool.id] && toolChatMessages[currentTool.id][sessionKeyToShow]) {
            let messages = toolChatMessages[currentTool.id][sessionKeyToShow];
            messages.forEach(msg => {
                let messageClass = msg.type === 'user' ? 'user-message' : (msg.type === 'bot' ? 'bot-message' : (msg.type === 'progress' ? 'bot-message progress' : 'bot-message loading'));
                let contentHtml = msg.content
                    // 구백엔드 형식: 파일.pdf (p1)
                    .replace(/([^\s]+\.pdf) \(p(\d+)\)/g, '<a href="#" class="ref-link" data-fname="$1" data-page="$2">$1 (p$2)</a>')
                    // 신백엔드 형식: [p1](/pdf?filename=파일.pdf#page=1)
                    .replace(/\[p(\d+)\]\(\/pdf\?filename=([^#]+)#page=(\d+)\)/g, function(_, pageNum, fnameEnc, pageNum2){
                        const fname = decodeURIComponent(fnameEnc);
                        return `<a href="#" class="ref-link" data-fname="${fname}" data-page="${pageNum}">p${pageNum}</a>`;
                    })
                    // gxp-chat 경로 링크
                    .replace(/\[p(\d+)\]\(\/gxp-chat\/pdf\?filename=([^#]+)#page=(\d+)\)/g, function(_, pg, fnameEnc){
                         const fname = decodeURIComponent(fnameEnc);
                         return `<a href="#" class="ref-link" data-fname="${fname}" data-page="${pg}">p${pg}</a>`;
                    })
                contentHtml = contentHtml.replace(/\n/g, "<br>");
                if (msg.type === 'progress') {
                    const label = msg.content || '생각중';
                    contentHtml = `<span style="color:#aaa;font-style:italic;">${label}</span><div class="progress-bar"><div class="progress-bar-inner"></div></div>`;
                } else if (msg.type === 'loading') {
                    contentHtml = `<span style="color:#aaa;font-style:italic;">${msg.content}</span>`;
                }
                let timeDisplay = msg.time;
                if (msg.type === 'loading') {
                    const elapsed = Math.floor((Date.now() - (msg.start||Date.now()))/1000);
                    timeDisplay = elapsed + 's';
                }
                $chatCenter.append(`<div class="chat-message ${messageClass}"><div class="message-content">${contentHtml}</div><div class="message-time">${timeDisplay}</div></div>`);
            });
        } else if (toolChatMessages[currentTool.id] && toolChatMessages[currentTool.id][getMsgKey(currentTool.id,null)]) {
            let messages = toolChatMessages[currentTool.id][getMsgKey(currentTool.id,null)];
            messages.forEach(msg => {
                let messageClass = msg.type === 'user' ? 'user-message' : (msg.type === 'bot' ? 'bot-message' : (msg.type === 'progress' ? 'bot-message progress' : 'bot-message loading'));
                let contentHtml = msg.content
                    // 구백엔드 형식: 파일.pdf (p1)
                    .replace(/([^\s]+\.pdf) \(p(\d+)\)/g, '<a href="#" class="ref-link" data-fname="$1" data-page="$2">$1 (p$2)</a>')
                    // 신백엔드 형식: [p1](/pdf?filename=파일.pdf#page=1)
                    .replace(/\[p(\d+)\]\(\/pdf\?filename=([^#]+)#page=(\d+)\)/g, function(_, pageNum, fnameEnc, pageNum2){
                        const fname = decodeURIComponent(fnameEnc);
                        return `<a href="#" class="ref-link" data-fname="${fname}" data-page="${pageNum}">p${pageNum}</a>`;
                    })
                    // gxp-chat 경로 링크
                    .replace(/\[p(\d+)\]\(\/gxp-chat\/pdf\?filename=([^#]+)#page=(\d+)\)/g, function(_, pg, fnameEnc){
                         const fname = decodeURIComponent(fnameEnc);
                         return `<a href="#" class="ref-link" data-fname="${fname}" data-page="${pg}">p${pg}</a>`;
                    })
                contentHtml = contentHtml.replace(/\n/g, "<br>");
                if (msg.type === 'progress') {
                    const label = msg.content || '생각중';
                    contentHtml = `<span style="color:#aaa;font-style:italic;">${label}</span><div class="progress-bar"><div class="progress-bar-inner"></div></div>`;
                } else if (msg.type === 'loading') {
                    contentHtml = `<span style="color:#aaa;font-style:italic;">${msg.content}</span>`;
                }
                let timeDisplay = msg.time;
                if (msg.type === 'loading') {
                    const elapsed = Math.floor((Date.now() - (msg.start||Date.now()))/1000);
                    timeDisplay = elapsed + 's';
                }
                $chatCenter.append(`<div class="chat-message ${messageClass}"><div class="message-content">${contentHtml}</div><div class="message-time">${timeDisplay}</div></div>`);
            });
        }
        // after messages appended
        if(autoScroll){
            $chatCenter.scrollTop($chatCenter[0].scrollHeight);
        }
    }

    // Helper: send message to backend and get response
    async function sendMessageToAI(toolId, sessionId, message, model, knowledgeMode){
        const url = toolId === 'chatgpt' ? 'http://localhost:8010/chatgpt/chat' : 'http://localhost:8010/chat';
        const formData = new FormData();
        formData.append('message', message);
        formData.append('tool_id', toolId);
        if(sessionId) formData.append('session_id', sessionId);
        formData.append('model', model);
        if(toolId === 'dev_chatbot'){
            formData.append('knowledge_mode', knowledgeMode);
        }
        const res = await fetch(url,{method:'POST',body:formData});
        if(!res.ok) throw new Error('HTTP '+res.status);
        return await res.json();
    }

    // Modify sendChat implementation
    function sendChat(){
        const message = $('.chat-input').text().trim();
        if(!message) return;
        const now = new Date().toISOString();
        const sessionId = currentSessionId || 'temp-session';
        const toolId = currentTool.id;
        const msgKey = getMsgKey(toolId, sessionId);

        if(!toolChatMessages[toolId]) toolChatMessages[toolId] = {};
        if(!toolChatMessages[toolId][msgKey]) toolChatMessages[toolId][msgKey]=[];
        toolChatMessages[toolId][msgKey].push({type:'user',content:message,time:now});
        const loadingMsg = {type:'loading',content:'생각중',start:Date.now()};
        toolChatMessages[toolId][msgKey].push(loadingMsg);
        // 주기적으로 경과 시간 업데이트
        const loadingInterval = setInterval(()=>{
            // 종료 조건: 로딩 메시지가 더 이상 마지막이 아닐 때
            const msgs = toolChatMessages[toolId][msgKey];
            if(!msgs || msgs[msgs.length-1] !== loadingMsg){
                clearInterval(loadingInterval);
                return;
            }
            renderChatMessages(true);
        },1000);
        $('.chat-input').text('');
        renderChatMessages(true);

        // Determine model & knowledgeMode
        let model='gpt-oss:latest';
        if(currentTool.id==='chatgpt'){
            model = $('.model-select').val()||'auto';
        } else if(currentTool.id==='dev_chatbot'){
            model = $('.gc-model-select').val()||'woong';
        } else if(currentTool.id==='doc_translation'){
            model = $('.dt-model-select').val()||'external';
        }
        const kMode = $('.knowledge-mode').val()||'hybrid';

        sendMessageToAI(currentTool.id, currentSessionId, message, model, kMode)
            .then(resp=>{
                // replace last loading message
                const msgs = toolChatMessages[toolId][msgKey];
                msgs[msgs.length-1] = {type:'bot',content:resp.response,time:new Date().toISOString()};
                // update session id
                if(!currentSessionId && resp.session_id){
                    currentSessionId = resp.session_id;
                    lastSessionPerTool[currentTool.id]=resp.session_id;
                    const newKey = getMsgKey(toolId, resp.session_id);
                    toolChatMessages[toolId][newKey]=msgs;
                    delete toolChatMessages['temp']; // Remove temp session from toolChatMessages
                    delete toolChatMessages['temp-session']; // Remove temp session from toolChatMessages
                }
                renderChatMessages(true);
            })
            .catch(err=>{
                const msgs=toolChatMessages[toolId][msgKey];
                msgs[msgs.length-1]={type:'bot',content:'서버 오류: '+err.message,time:new Date().toISOString()};
                renderChatMessages(true);
            });
    }

    // 채팅 입력 핸들러 (Enter 전송, Shift+Enter 줄바꿈)
    $('.chat-input').on('keydown', function(e) {
        if (e.key === 'Enter' && !e.shiftKey && !isComposing) {
            e.preventDefault();
            sendChat();
        }
    });

    // 채팅 전송 버튼 클릭 핸들러
    $('.send-chat').on('click', function() {
        sendChat();
    });

    // 세션 변경 핸들러
    $('.session-selector').on('change', function() {
        const selectedSessionId = $(this).val();
        if (selectedSessionId !== currentSessionId) {
            currentSessionId = selectedSessionId;
            renderChatMessages();
        }
    });

    // 도구 선택 핸들러
    function selectTool(toolId) {
        currentTool = tools.find(tool => tool.id === toolId);
        if (!currentTool) return;

        // 페이지 전환: 채팅 페이지 활성화
        $('.menu-item').removeClass('active');
        $('.menu-item[data-page="chat"]').addClass('active');
        $('.page').removeClass('active');
        $('.page-chat').addClass('active');
        $('.page-title').text('채팅');

        // 세션 리셋 또는 기존 세션 복원
        currentSessionId = lastSessionPerTool[toolId] || null;

        // 모델/지식모드 드롭다운 표시 제어
        if (toolId === 'chatgpt') {
            $('.model-select').show();
            $('.knowledge-mode').hide();
            $('.gc-model-select').hide();
            $('.dt-model-select').hide();
            // 파일 사이드바 숨김 (개발챗봇 전용)
            $('.file-sidebar').hide();
            $('.page-chat').removeClass('has-file-sidebar');
        } else if (toolId === 'dev_chatbot') {
            $('.model-select').hide();
            $('.knowledge-mode').show();
            $('.gc-model-select').show();
            $('.dt-model-select').hide();

            // 개발챗봇에서만 PDF 파일 사이드바 표시
            $('.file-sidebar').show();
            $('.page-chat').addClass('has-file-sidebar');
            loadFileList();
        } else if (toolId === 'doc_translation') {
            $('.model-select').hide();
            $('.knowledge-mode').hide();
            $('.gc-model-select').hide();
            $('.dt-model-select').show();

            // 문서번역에서도 파일 사이드바 표시 (Word 파일용)
            $('.file-sidebar').show();
            $('.page-chat').addClass('has-file-sidebar');
            loadDocTranslationFileList();
        } else {
            $('.model-select').hide();
            $('.knowledge-mode').hide();
            $('.gc-model-select').hide();
            $('.dt-model-select').hide();

            // 다른 도구 선택 시 파일 사이드바 숨김
            $('.file-sidebar').hide();
            $('.page-chat').removeClass('has-file-sidebar');
        }

        renderChatMessages();
    }

    // ---------- 도구 목록 렌더링 및 이벤트 ----------
    function renderTools(filter) {
        let list = tools;
        if (filter && filter !== 'all') {
            if (filter === 'favorite') {
                list = tools.filter(t => favorites.includes(t.id));
            } else {
                list = tools.filter(t => t.category && t.category.includes(filter));
            }
        }
        const $list = $('.tools-list');
        $list.empty();
        if (list.length === 0) {
            $list.append('<div style="padding:40px;color:#bbb;">도구가 없습니다.</div>');
            return;
        }
        list.forEach(tool => {
            const fav = favorites.includes(tool.id) ? 'active' : '';
            $list.append(`
                <div class="tool-card" data-tool-id="${tool.id}">
                    <div class="tool-title">${tool.name}</div>
                    <div class="tool-desc">${tool.description}</div>
                    <div class="tool-fav ${fav}" data-id="${tool.id}">&#9733;</div>
                </div>
            `);
        });
    }

    // 필터 버튼 클릭 -> 목록 갱신
    $(document).on('click', '.filter-btn', function() {
        $('.filter-btn').removeClass('active');
        $(this).addClass('active');
        const filter = $(this).data('filter');
        renderTools(filter);
    });

    // 도구 카드 클릭 이벤트 (즐겨찾기 별 클릭 제외)
    $(document).on('click', '.tool-card', function(e) {
        if (!$(e.target).hasClass('tool-fav')) {
            const toolId = $(this).data('tool-id');
            selectTool(toolId);
        }
    });

    // 즐겨찾기 별 토글
    $(document).on('click', '.tool-fav', function(e) {
        e.stopPropagation();
        const id = $(this).data('id');
        if (favorites.includes(id)) {
            favorites = favorites.filter(f => f !== id);
        } else {
            favorites.push(id);
        }
        localStorage.setItem('favorites', JSON.stringify(favorites));
        const filter = $('.filter-btn.active').data('filter') || 'all';
        renderTools(filter);
    });
    // ---------- 도구 목록 End ----------

    // ---------- 파일 업로드 UI ----------
    // 파일 리스트 헤더 '+' 버튼 클릭 → 파일 선택창 오픈
    $('.file-add-btn').on('click', function(){
        $('.chat-file-input').click();
    });

    // 파일 선택 후 업로드 요청
    $('.chat-file-input').on('change', async function(){
        const files = this.files;
        if(!files || files.length===0) return;

        const formData = new FormData();
        Array.from(files).forEach(f => formData.append('files', f));

        // ---- dev_chatbot: progress 메시지 표시 ----
        let placeholderIds = [];
        if(currentTool && currentTool.id === 'dev_chatbot'){
            const $list = $('.file-list');
            Array.from(files).forEach(f=>{
                const pid = 'upload-'+Date.now()+Math.random().toString(36).slice(2,8);
                placeholderIds.push(pid);
                $list.append(`<li class="uploading" data-temp="${pid}" style="font-style:italic; color:#aaa;"><span class="uploading-label">공부중<span class="uploading-dots">...</span></span></li>`);
                let dotCnt = 3; // start with visible dots
                uploadIntervals[pid] = setInterval(()=>{
                    dotCnt = (dotCnt + 1) % 4;
                    const dots = '.'.repeat(dotCnt);
                    $(`li.uploading[data-temp="${pid}"] .uploading-dots`).text(dots);
                }, 400);
            });
        }

        try {
            const res = await fetch('http://localhost:8010/upload_pdf', {
                method: 'POST',
                body: formData
            });
            const data = await res.json();

            // 업로드 결과 처리
            if(currentTool && currentTool.id === 'dev_chatbot'){
                if(data.status==='success'){
                    const uploaded = data.files || [];
                    // 성공한 파일 대체
                    uploaded.forEach((fname, idx)=>{
                        const pid = placeholderIds[idx];
                        const $li = $(`li.uploading[data-temp="${pid}"]`);
                        if($li.length){
                            clearInterval(uploadIntervals[pid]);
                            delete uploadIntervals[pid];
                            $li.removeClass('uploading');
                            $li.removeAttr('data-temp');
                            $li.html(`<span>${fname}</span><button class="file-del-btn" data-fname="${fname}">✕</button>`);
                        }
                    });
                    // 업로드되지 않은 placeholder 정리
                    if(uploaded.length < placeholderIds.length){
                        placeholderIds.slice(uploaded.length).forEach(pid=>{
                            clearInterval(uploadIntervals[pid]);
                            delete uploadIntervals[pid];
                            $(`li.uploading[data-temp="${pid}"]`).remove();
                        });
                        if(uploaded.length===0){
                            alert('업로드할 PDF가 없습니다.');
                        }
                    }
                    // 최종 파일 리스트 새로고침
                    loadFileList();
                } else {
                    // 실패 시 placeholder 제거
                    placeholderIds.forEach(pid=>{
                        clearInterval(uploadIntervals[pid]);
                        delete uploadIntervals[pid];
                        $(`li.uploading[data-temp="${pid}"]`).remove();
                    });
                    alert('업로드 실패: '+ (data.message||'알 수 없는 오류'));
                }
            } else {
                // dev_chatbot 아닐 때는 알림
                if(data.status==='success'){
                    alert('파일 업로드가 완료되었습니다.');
                } else {
                    alert('업로드 실패: '+ (data.message||'알 수 없는 오류'));
                }
            }

            if(data.status==='success'){
                loadFileList();
            }
        } catch(err){
            if(currentTool && currentTool.id === 'dev_chatbot'){
                // 오류 시 placeholder 제거 및 경고
                placeholderIds.forEach(pid=>{
                    clearInterval(uploadIntervals[pid]);
                    delete uploadIntervals[pid];
                    $(`li.uploading[data-temp="${pid}"]`).remove();
                });
                alert('업로드 오류: ' + err.message);
            } else {
                alert('업로드 오류: ' + err.message);
            }
        } finally {
            // 같은 파일을 다시 업로드할 수 있도록 값 초기화
            $(this).val('');
        }
    });
    // ---------- 파일 업로드 End ----------

    // ----- 강의 페이지 렌더링 -----
    function renderLecturePage(){
        const $page = $('.page-lecture');
        if($page.length===0) return;
        $page.empty();
        const videos=[
            "https://www.youtube.com/watch?v=GlvOHXJT_gI&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=14&t=26s",
            "https://www.youtube.com/watch?v=nl34M5bKkVM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=12",
            "https://www.youtube.com/watch?v=0sRlrW_UyLk&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=11",
            "https://www.youtube.com/watch?v=MtTAprzHOBg&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=10",
            "https://www.youtube.com/watch?v=CyWcZWVwCjQ&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=9",
            "https://www.youtube.com/watch?v=X7ycln4JREM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=8",
            "https://www.youtube.com/watch?v=rrCmsOFt2UU&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=7",
            "https://www.youtube.com/watch?v=7cyDMjzcdxM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=6",
            "https://www.youtube.com/watch?v=Sr4MEivnt4M&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=5",
            "https://www.youtube.com/watch?v=F4ExQ3P_A5w&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=4",
            "https://www.youtube.com/watch?v=tiC5k9P93cE&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=3",
            "https://www.youtube.com/watch?v=nfPXfsVz6jM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=2",
            "https://www.youtube.com/watch?v=9NH3FhBX2ng&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=1"
        ];
        const videoHtml1=videos.map(url=>{
            const id=url.match(/v=([\w-]{11})/);
            const vid=id? id[1]:'';
            const thumb=vid?`https://img.youtube.com/vi/${vid}/hqdefault.jpg`:'';
            return `<a href="${url}" target="_blank" class="lecture-video"><img src="${thumb}" alt="video thumbnail"></a>`;
        }).join('');

        // second list
        const videos2=[
            "https://www.youtube.com/watch?v=menXWx89QFg&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=14",
            "https://www.youtube.com/watch?v=6IsYJy3ussQ&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=13",
            "https://www.youtube.com/watch?v=Mpk4LNZ_P4c&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=12",
            "https://www.youtube.com/watch?v=r2UMvkwJTRc&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=11",
            "https://www.youtube.com/watch?v=4uc58O4poJE&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=10",
            "https://www.youtube.com/watch?v=njAu-W-JA6c&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=9",
            "https://www.youtube.com/watch?v=SaYxoKVYgsk&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=8",
            "https://www.youtube.com/watch?v=sDDW5w2jD2Q&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=7",
            "https://www.youtube.com/watch?v=Ext47QeBCbY&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=6",
            "https://www.youtube.com/watch?v=og0mGD29Hw8&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=5",
            "https://www.youtube.com/watch?v=GkZgTth3guQ&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=4",
            "https://www.youtube.com/watch?v=oSZBGZmaTTw&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=3",
            "https://www.youtube.com/watch?v=t6Xc1Ey5PMY&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=2",
            "https://www.youtube.com/watch?v=aFw4Z9F4Ens&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=1"
        ];
        const videoHtml2=videos2.map(url=>{
            const id=url.match(/v=([\w-]{11})/);
            const vid=id? id[1]:'';
            const thumb=vid?`https://img.youtube.com/vi/${vid}/hqdefault.jpg`:'';
            return `<a href="${url}" target="_blank" class="lecture-video"><img src="${thumb}" alt="video thumbnail"></a>`;
        }).join('');
 
        // third list
        const videos3=[
            "https://www.youtube.com/watch?v=kEAV-PqWD_4",
            "https://www.youtube.com/watch?v=ha9kn0qe4Mc",
            "https://www.youtube.com/watch?v=ISrYHGg2C2c",
            "https://www.youtube.com/watch?v=cxOoV2guNQQ",
            "https://www.youtube.com/watch?v=oAxunD8k0C8",
            "https://www.youtube.com/watch?v=oZ1O6Z9HwW0",
            "https://www.youtube.com/watch?v=nyZnrKVaIXU",
            "https://www.youtube.com/watch?v=BzwhskWZ-CQ"
        ];
        const videoHtml3=videos3.map(url=>{
            const id=url.match(/v=([\w-]{11})/);
            const vid=id? id[1]:'';
            const thumb=vid?`https://img.youtube.com/vi/${vid}/hqdefault.jpg`:'';
            return `<a href="${url}" target="_blank" class="lecture-video"><img src="${thumb}" alt="video thumbnail"></a>`;
        }).join('');
 
        $page.append(`
            <h3 class="lecture-topic">강수진박사의 프롬프트 엔지니어링의 세계</h3>
            <div class="lecture-video-list">${videoHtml1}</div>
            <h3 class="lecture-topic" style="margin-top:24px;">AI, 안해보면 모른다</h3>
            <div class="lecture-video-list">${videoHtml2}</div>
            <h3 class="lecture-topic" style="margin-top:24px;">MCP를 배워보자</h3>
            <div class="lecture-video-list">${videoHtml3}</div>
        `);
    }

    // ---------- 사이드바 메뉴 전환 ----------
    $(document).on('click', '.menu-item', function(){
        $('.menu-item').removeClass('active');
        $(this).addClass('active');
        const page = $(this).data('page');
        $('.page').removeClass('active');
        $('.page-' + page).addClass('active');
        $('.page-title').text($(this).text());

        // 채팅 페이지로 돌아올 때 현재 도구 상태 유지해서 메시지 다시 렌더링
        if(page === 'chat') {
            renderChatMessages();
        }
        if(page === 'community') {
            $('.community-menu-item').removeClass('active');
            $('.community-menu-item[data-content="newsletter"]').addClass('active');
            showCommunityContent('newsletter');
        }
        if(page === 'lecture') {
            renderLecturePage();
        }
    });
    // ---------- 메뉴 전환 End ----------

    // ---------- 커뮤니티 서브 메뉴 ----------
    function showCommunityContent(type){
        const $content = $('.community-content');
        if($content.length===0) return;
        $content.empty();
        if(type === 'newsletter'){
            $content.append(`
                <h2 class="newsletter-title">뉴스레터</h2>
                <div class="newsletter-content-area">
                    <ul class="newsletter-list">
                        <li><a href="#" class="newsletter-link" data-file="AI뉴스레터25년7월호_IT전략팀.pdf">25년 7월호</a></li>
                    </ul>
                </div>
            `);
        } else if(type === 'lecture'){
            // 재사용을 위해 내부 함수
            function toThumb(url){
                const id=url.match(/v=([\w-]{11})/);
                const vid=id? id[1]:'';
                return vid?`https://img.youtube.com/vi/${vid}/hqdefault.jpg`:'';
            }
            const sec1=[
                "https://www.youtube.com/watch?v=GlvOHXJT_gI&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=14&t=26s",
                "https://www.youtube.com/watch?v=nl34M5bKkVM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=12",
                "https://www.youtube.com/watch?v=0sRlrW_UyLk&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=11",
                "https://www.youtube.com/watch?v=MtTAprzHOBg&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=10",
                "https://www.youtube.com/watch?v=CyWcZWVwCjQ&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=9",
                "https://www.youtube.com/watch?v=X7ycln4JREM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=8",
                "https://www.youtube.com/watch?v=rrCmsOFt2UU&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=7",
                "https://www.youtube.com/watch?v=7cyDMjzcdxM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=6",
                "https://www.youtube.com/watch?v=Sr4MEivnt4M&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=5",
                "https://www.youtube.com/watch?v=F4ExQ3P_A5w&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=4",
                "https://www.youtube.com/watch?v=tiC5k9P93cE&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=3",
                "https://www.youtube.com/watch?v=nfPXfsVz6jM&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=2",
                "https://www.youtube.com/watch?v=9NH3FhBX2ng&list=PL7d4-rFjtYdK4-RGBJTXbgLI5a-H7lz7g&index=1"
            ];
            const sec2=[
                "https://www.youtube.com/watch?v=menXWx89QFg&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=14",
                "https://www.youtube.com/watch?v=6IsYJy3ussQ&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=13",
                "https://www.youtube.com/watch?v=Mpk4LNZ_P4c&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=12",
                "https://www.youtube.com/watch?v=r2UMvkwJTRc&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=11",
                "https://www.youtube.com/watch?v=4uc58O4poJE&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=10",
                "https://www.youtube.com/watch?v=njAu-W-JA6c&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=9",
                "https://www.youtube.com/watch?v=SaYxoKVYgsk&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=8",
                "https://www.youtube.com/watch?v=sDDW5w2jD2Q&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=7",
                "https://www.youtube.com/watch?v=Ext47QeBCbY&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=6",
                "https://www.youtube.com/watch?v=og0mGD29Hw8&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=5",
                "https://www.youtube.com/watch?v=GkZgTth3guQ&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=4",
                "https://www.youtube.com/watch?v=oSZBGZmaTTw&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=3",
                "https://www.youtube.com/watch?v=t6Xc1Ey5PMY&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=2",
                "https://www.youtube.com/watch?v=aFw4Z9F4Ens&list=PL7d4-rFjtYdK5d2KOXyyaBymJYtEDRmy3&index=1"
            ];
            const sec3=[
                "https://www.youtube.com/watch?v=kEAV-PqWD_4",
                "https://www.youtube.com/watch?v=ha9kn0qe4Mc",
                "https://www.youtube.com/watch?v=ISrYHGg2C2c",
                "https://www.youtube.com/watch?v=cxOoV2guNQQ",
                "https://www.youtube.com/watch?v=oAxunD8k0C8",
                "https://www.youtube.com/watch?v=oZ1O6Z9HwW0",
                "https://www.youtube.com/watch?v=nyZnrKVaIXU",
                "https://www.youtube.com/watch?v=BzwhskWZ-CQ"
            ];
            const makeHtml=list=>list.map(url=>{
                const thumb=toThumb(url);
                return `<a href="${url}" target="_blank" class="lecture-video"><img src="${thumb}" alt="video thumbnail"></a>`;
            }).join('');

            $content.append(`
                <h3 class="lecture-topic">강수진박사의 프롬프트 엔지니어링의 세계</h3>
                <div class="lecture-video-list">${makeHtml(sec1)}</div>
                <h3 class="lecture-topic" style="margin-top:24px;">AI, 안해보면 모른다</h3>
                <div class="lecture-video-list">${makeHtml(sec2)}</div>
                <h3 class="lecture-topic" style="margin-top:24px;">MCP를 배워보자</h3>
                <div class="lecture-video-list">${makeHtml(sec3)}</div>
            `);
        } else if(type === 'qna'){
            const rows=[
               {no:1,title:'AI 모델 선택은 어떻게?',date:'2025-07-21',views:8},
               {no:2,title:'PDF 뷰어 오류 해결',date:'2025-07-20',views:21},
               {no:3,title:'질의 응답 게시판이 생성되었습니다.',date:'2025-07-19',views:12}
            ];
            const rowHtml=rows.map(r=>`<tr><td>${r.no}</td><td class="qna-title">${r.title}</td><td>${r.date}</td><td>${r.views}</td></tr>`).join('');
            $content.append(`
               <h2 class="qna-title-head">질의응답</h2>
               <table class="qna-table">
                   <thead><tr><th style="width:60px;">번호</th><th>제목</th><th style="width:120px;">등록일</th><th style="width:80px;">조회수</th></tr></thead>
                   <tbody>${rowHtml}</tbody>
               </table>
            `);
         }
    }

    // PDF 뷰 닫기 (X 버튼)
    $(document).on('click', '.newsletter-close', function(){
        // 복원 리스트 영역
        const $area = $('.newsletter-content-area');
        if($area.length){
            $area.html(`
                <ul class="newsletter-list">
                    <li><a href="#" class="newsletter-link" data-file="AI뉴스레터25년7월호_IT전략팀.pdf">25년 7월호</a></li>
                </ul>`);
        }
    });

    // 뉴스레터 항목 클릭 → PDF 보기
    $(document).on('click', '.newsletter-link', function(e){
        e.preventDefault();
        const fname = $(this).data('file');
        const encoded = encodeURIComponent(fname);
        const url = `community/${encoded}`;
        const $area = $('.newsletter-content-area');
        if(!$area.length) return;
        $area.html(`
            <div class="newsletter-pdf-wrapper">
                <button class="newsletter-close">×</button>
                <iframe src="${url}" class="newsletter-iframe"></iframe>
            </div>
        `);
    });
    // 서브 메뉴 클릭 (뉴스레터/질의응답 등)
    $(document).on('click', '.community-menu-item', function(){
        $('.community-menu-item').removeClass('active');
        $(this).addClass('active');
        const type = $(this).data('content');
        showCommunityContent(type);
    });
    // ---------- 커뮤니티 서브 메뉴 End ----------

    // ===== Helper =====
    function getMsgKey(toolId, sessionId){
        return sessionId && sessionId!=='temp-session' ? `${toolId}__${sessionId}` : `temp__${toolId}`;
    }
    // ------------------

    // 초기 로딩
    loadTools();
    loadFileList();
    renderChatMessages();
});