/**
 * Gravity Web — App 초기화 및 WebSocket 관리
 */

(function () {
    // ─── 컴포넌트 초기화 ──────────────────────────────────
    const sessionPanel = new SessionPanel();
    const chatPanel = new ChatPanel();
    const mirrorPanel = new MirrorPanel();

    let ws = null;
    let reconnectTimer = null;
    let currentView = 'chat'; // 'chat' | 'mirror'
    const WS_URL = `ws://${location.host}/ws`;

    // ─── DOM 레퍼런스 ─────────────────────────────────────
    const connectionStatus = document.getElementById('connectionStatus');
    const statusDot = connectionStatus.querySelector('.status-dot');
    const statusText = connectionStatus.querySelector('.status-text');

    const addSessionBtn = document.getElementById('addSessionBtn');
    const addSessionModal = document.getElementById('addSessionModal');
    const closeModal = document.getElementById('closeModal');
    const cancelModal = document.getElementById('cancelModal');
    const confirmAddSession = document.getElementById('confirmAddSession');
    const sessionNameInput = document.getElementById('sessionName');
    const sessionHostInput = document.getElementById('sessionHost');
    const sessionPortInput = document.getElementById('sessionPort');

    const screenshotBtn = document.getElementById('screenshotBtn');
    const reconnectBtn = document.getElementById('reconnectBtn');
    const screenshotOverlay = document.getElementById('screenshotOverlay');
    const screenshotImage = document.getElementById('screenshotImage');
    const closeScreenshot = document.getElementById('closeScreenshot');

    const tabChat = document.getElementById('tabChat');
    const tabMirror = document.getElementById('tabMirror');
    const chatMessagesWrap = document.getElementById('chatMessages');
    const chatInputArea = document.querySelector('.chat-input-area');
    const mirrorHint = document.getElementById('mirrorHint');

    // ─── WebSocket 연결 ───────────────────────────────────
    function connectWebSocket() {
        ws = new WebSocket(WS_URL);

        ws.onopen = () => {
            setConnectionStatus('connected', '서버 연결됨');
            if (reconnectTimer) {
                clearTimeout(reconnectTimer);
                reconnectTimer = null;
            }
            // Bridge 세션 자동 로드
            loadBridgeSessions();
        };

        ws.onclose = () => {
            setConnectionStatus('error', '연결 끊김');
            scheduleReconnect();
        };

        ws.onerror = () => {
            setConnectionStatus('error', '연결 오류');
        };

        ws.onmessage = (event) => {
            try {
                const msg = JSON.parse(event.data);
                handleMessage(msg);
            } catch (e) {
                console.error('WS 메시지 파싱 오류:', e);
            }
        };
    }

    function scheduleReconnect() {
        if (reconnectTimer) return;
        reconnectTimer = setTimeout(() => {
            reconnectTimer = null;
            connectWebSocket();
        }, 3000);
    }

    function sendWs(msg) {
        if (ws && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify(msg));
        }
    }

    // ─── Bridge 세션 관리 ──────────────────────────────────
    let bridgeSessions = [];  // Bridge에서 가져온 대화 목록
    let activeBridgeSession = null;

    async function loadBridgeSessions() {
        try {
            const res = await fetch('/api/bridge/sessions');
            if (!res.ok) return;
            const data = await res.json();
            bridgeSessions = (data.sessions || []).map(s => ({
                id: s.id,
                name: s.title || s.id.substring(0, 8),
                host: 'bridge',
                cdpPort: 0,
                status: 'connected',
                title: s.title,
                stepCount: s.stepCount,
                isBridge: true,
            }));
            sessionPanel.update(bridgeSessions);
            // 활성 세션 없으면 가장 최근 대화 자동 선택
            if (!sessionPanel.activeSessionId && bridgeSessions.length > 0) {
                selectBridgeSession(bridgeSessions[0].id);
            }
        } catch (e) {
            console.warn('[Bridge] 세션 로드 실패:', e);
        }
    }

    async function selectBridgeSession(sessionId) {
        activeBridgeSession = sessionId;
        sessionPanel.setActive(sessionId);
        const session = bridgeSessions.find(s => s.id === sessionId);
        if (session) {
            chatPanel.showSession({ name: session.name, status: 'connected' });
        }
        // cascades에서 대화 내용 가져오기
        try {
            const res = await fetch('/api/bridge/cascades');
            if (!res.ok) return;
            const data = await res.json();
            const cascadeData = data.cascades || data;
            // 선택된 세션의 데이터 찾기
            const cascade = cascadeData[sessionId];
            if (cascade) {
                const messages = parseCascadeToMessages(cascade);
                chatPanel.updateChat(messages);
            }
        } catch (e) {
            console.warn('[Bridge] cascade 로드 실패:', e);
        }
    }

    /**
     * Cascade 데이터를 ChatPanel이 이해하는 message[] 형식으로 변환
     */
    function parseCascadeToMessages(cascade) {
        const msgs = [];
        // latestNotifyUserStep — 마지막 AI 응답
        if (cascade.latestNotifyUserStep?.step?.notifyUser?.notificationContent) {
            msgs.push({
                type: 'text',
                html: cascade.latestNotifyUserStep.step.notifyUser.notificationContent
                    .replace(/\n/g, '<br>')
                    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
                    .replace(/`([^`]+)`/g, '<code>$1</code>'),
            });
        }
        // latestTaskBoundaryStep — 현재 작업 상태
        if (cascade.latestTaskBoundaryStep?.step?.taskBoundary) {
            const tb = cascade.latestTaskBoundaryStep.step.taskBoundary;
            msgs.push({
                type: 'task',
                title: tb.taskName || '',
                summary: tb.taskSummary || '',
                status: tb.taskStatus || '',
                mode: tb.mode || '',
            });
        }
        // summary
        if (cascade.summary && msgs.length === 0) {
            msgs.push({ type: 'text', html: `<p>${cascade.summary}</p>` });
        }
        return msgs;
    }

    // ─── 서버 메시지 핸들러 ───────────────────────────────
    function handleMessage(msg) {
        switch (msg.type) {
            case 'sessions_list':
                // CDP 세션 (레거시) — Bridge 세션과 병합하지 않음
                break;

            case 'session_switched':
                sessionPanel.setActive(msg.sessionId);
                chatPanel.showSession(msg.session);
                break;

            case 'chat_update':
                if (msg.sessionId === sessionPanel.activeSessionId) {
                    chatPanel.updateChat(msg.messages);
                }
                break;

            case 'message_sent':
                if (!msg.success) {
                    showToast(`전송 실패: ${msg.error}`, 'error');
                }
                break;

            case 'bridge_event':
                handleBridgeEvent(msg);
                break;

            case 'screenshot':
                screenshotImage.src = `data:image/jpeg;base64,${msg.data}`;
                screenshotOverlay.style.display = 'flex';
                break;

            case 'screencast_frame':
                if (msg.sessionId === sessionPanel.activeSessionId) {
                    mirrorPanel.updateFrame(msg.data, msg.metadata);
                    if (mirrorHint) mirrorHint.style.display = 'none';
                }
                break;

            case 'error':
                showToast(msg.message, 'error');
                break;
        }
    }

    function handleBridgeEvent(msg) {
        switch (msg.type) {
            case 'bridge_event':
                // step_changed → 활성 대화 갱신
                if (msg.step_changed || msg.sessions) {
                    loadBridgeSessions();
                }
                if (msg.new_conversation) {
                    loadBridgeSessions();
                }
                break;
        }
    }

    // ─── 세션 패널 이벤트 ─────────────────────────────────
    sessionPanel.onSessionSelect = (sessionId) => {
        // Bridge 세션인지 확인
        const isBridge = bridgeSessions.some(s => s.id === sessionId);
        if (isBridge) {
            selectBridgeSession(sessionId);
        } else {
            sendWs({ type: 'switch_session', sessionId });
        }
    };

    sessionPanel.onSessionRemove = async (sessionId) => {
        try {
            const res = await fetch(`/api/sessions/${sessionId}`, { method: 'DELETE' });
            if (res.ok) {
                if (sessionPanel.activeSessionId === sessionId) {
                    chatPanel.showEmpty();
                    sessionPanel.setActive(null);
                }
                showToast('세션이 제거되었습니다', 'success');
            }
        } catch (e) {
            showToast('세션 제거 실패', 'error');
        }
    };

    // ─── 채팅 패널 이벤트 ─────────────────────────────────
    chatPanel.onSendMessage = async (text) => {
        if (!sessionPanel.activeSessionId) return;
        // Bridge 세션이면 Bridge API로 전송
        const isBridge = bridgeSessions.some(s => s.id === sessionPanel.activeSessionId);
        if (isBridge) {
            try {
                const res = await fetch('/api/bridge/send', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ message: text, sessionId: sessionPanel.activeSessionId }),
                });
                if (!res.ok) showToast('전송 실패', 'error');
            } catch { showToast('전송 실패', 'error'); }
            return;
        }
        sendWs({
            type: 'send_message',
            sessionId: sessionPanel.activeSessionId,
            text,
        });
    };

    chatPanel.onActionClick = (button) => {
        sendWs({
            type: 'click_action',
            sessionId: sessionPanel.activeSessionId,
            label: button.label,
            x: button.x,
            y: button.y,
        });
        showToast(`"${button.label}" 클릭`, 'success');
    };

    // ─── 미러 패널 이벤트 ─────────────────────────────
    mirrorPanel.onStartScreencast = (sessionId) => {
        sendWs({ type: 'start_screencast', sessionId });
    };

    mirrorPanel.onStopScreencast = (sessionId) => {
        sendWs({ type: 'stop_screencast', sessionId });
    };

    mirrorPanel.onInputEvent = (sessionId, event) => {
        sendWs({ type: 'input_event', sessionId, event });
    };

    // ─── 탭 전환 (Chat ↔ Mirror) ────────────────────────
    function switchView(view) {
        currentView = view;

        // 탭 UI
        tabChat.classList.toggle('active', view === 'chat');
        tabMirror.classList.toggle('active', view === 'mirror');

        // 채팅 영역 표시/숨기기
        chatMessagesWrap.style.display = view === 'chat' ? '' : 'none';
        if (chatInputArea) chatInputArea.style.display = view === 'chat' ? '' : 'none';

        if (view === 'mirror') {
            if (mirrorHint) mirrorHint.style.display = '';
            mirrorPanel.start(sessionPanel.activeSessionId);
        } else {
            mirrorPanel.stop();
        }
    }

    tabChat?.addEventListener('click', () => switchView('chat'));
    tabMirror?.addEventListener('click', () => switchView('mirror'));

    // ─── 모달 ─────────────────────────────────────────────
    function showModal() {
        addSessionModal.style.display = 'flex';
        sessionNameInput.value = '';
        sessionHostInput.value = 'localhost';
        sessionPortInput.value = '9000';
        setTimeout(() => sessionNameInput.focus(), 100);
    }

    function hideModal() {
        addSessionModal.style.display = 'none';
    }

    async function addSession() {
        const name = sessionNameInput.value.trim();
        const host = sessionHostInput.value.trim();
        const port = parseInt(sessionPortInput.value, 10);

        if (!name) {
            sessionNameInput.focus();
            return;
        }

        hideModal();

        try {
            const res = await fetch('/api/sessions', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ name, host, cdpPort: port }),
            });

            const session = await res.json();

            if (session.status === 'connected') {
                showToast(`${name} 연결 성공`, 'success');
            } else {
                showToast(`${name} 연결 실패: ${session.error || '알 수 없는 오류'}`, 'error');
            }
        } catch (e) {
            showToast('세션 추가 실패', 'error');
        }
    }

    addSessionBtn.addEventListener('click', showModal);
    closeModal.addEventListener('click', hideModal);
    cancelModal.addEventListener('click', hideModal);
    confirmAddSession.addEventListener('click', addSession);

    // Enter로 모달 확인
    addSessionModal.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') addSession();
        if (e.key === 'Escape') hideModal();
    });

    // 배경 클릭으로 모달 닫기
    addSessionModal.addEventListener('click', (e) => {
        if (e.target === addSessionModal) hideModal();
    });

    // ─── 스크린샷 ─────────────────────────────────────────
    screenshotBtn.addEventListener('click', () => {
        sendWs({ type: 'get_screenshot', sessionId: sessionPanel.activeSessionId });
    });

    closeScreenshot.addEventListener('click', () => {
        screenshotOverlay.style.display = 'none';
    });

    screenshotOverlay.addEventListener('click', (e) => {
        if (e.target === screenshotOverlay) {
            screenshotOverlay.style.display = 'none';
        }
    });

    // ─── 재연결 ───────────────────────────────────────────
    reconnectBtn.addEventListener('click', async () => {
        const id = sessionPanel.activeSessionId;
        if (!id) return;

        try {
            const res = await fetch(`/api/sessions/${id}/reconnect`, { method: 'POST' });
            const result = await res.json();
            if (result.success) {
                showToast('재연결 성공', 'success');
            } else {
                showToast(`재연결 실패: ${result.error}`, 'error');
            }
        } catch {
            showToast('재연결 실패', 'error');
        }
    });

    // ─── 유틸리티 ─────────────────────────────────────────
    function setConnectionStatus(status, text) {
        statusDot.className = `status-dot ${status}`;
        statusText.textContent = text;
    }

    function showToast(message, type = '') {
        const toast = document.createElement('div');
        toast.className = `toast ${type}`;
        toast.textContent = message;
        document.body.appendChild(toast);
        setTimeout(() => toast.remove(), 3000);
    }

    // ─── 시작 ─────────────────────────────────────────────
    connectWebSocket();
})();
