/**
 * ViewerCore - 문서 뷰어 Alpine.js 컴포넌트
 * 모든 모듈을 통합하고 Alpine.js 컴포넌트를 관리합니다.
 */
window.documentViewer = () => ({
    // ==================== 기본 상태 ====================
    loading: true,
    error: null,
    document: null,
    documentId: null,
    contentType: 'document', // 'document' 또는 'note'
    navigation: null,
    
    // ==================== PDF 뷰어 상태 ====================
    pdfSrc: '',
    pdfLoading: false,
    pdfError: false,
    pdfLoaded: false,
    
    // ==================== PDF 검색 상태 ====================
    showPdfSearchModal: false,
    pdfSearchQuery: '',
    pdfSearchResults: [],
    pdfSearchLoading: false,
    
    // ==================== PDF.js 뷰어 상태 ====================
    pdfDocument: null,
    currentPage: 1,
    totalPages: 0,
    pdfScale: 1.0,
    pdfCanvas: null,
    pdfContext: null,
    pdfTextContent: [],
    
    // ==================== 데이터 상태 ====================
    highlights: [],
    notes: [],
    bookmarks: [],
    documentLinks: [],
    linkableDocuments: [],
    backlinks: [],
    
    // ==================== 선택 상태 ====================
    selectedHighlightColor: '#FFFF00',
    selectedText: '',
    selectedRange: null,
    
    // ==================== 폼 데이터 ====================
    noteForm: {
        content: '',
        tags: ''
    },
    bookmarkForm: {
        title: '',
        description: ''
    },
    linkForm: {
        target_type: 'document', // 'document' 또는 'note'
        target_document_id: '',
        selected_text: '',
        start_offset: 0,
        end_offset: 0,
        link_text: '',
        description: '',
        link_type: 'text_fragment', // 무조건 텍스트 선택만 지원
        target_text: '',
        target_start_offset: 0,
        target_end_offset: 0,

        target_book_id: ''
    },
    
    // ==================== 언어 및 기타 ====================
    isKorean: false,
    
    // ==================== UI 상태 (Alpine.js 바인딩용) ====================
    searchQuery: '',
    activeFeatureMenu: null,
    showLinksModal: false,
    showLinkModal: false,
    showNotesModal: false,
    showBookmarksModal: false,
    showBacklinksModal: false,
    showNoteInputModal: false,
    availableBooks: [],
    filteredDocuments: [],
    
    // ==================== 모듈 인스턴스 ====================
    documentLoader: null,
    highlightManager: null,
    bookmarkManager: null,
    linkManager: null,
    uiManager: null,
    
    // ==================== 초기화 플래그 ====================
    _initialized: false,

    // ==================== 초기화 ====================
    async init() {
        // 중복 초기화 방지
        if (this._initialized) {
            console.log('⚠️ 이미 초기화됨, 중복 실행 방지');
            return;
        }
        this._initialized = true;
        
        console.log('🚀 DocumentViewer 초기화 시작');
        
        // 전역 인스턴스 설정 (말풍선에서 함수 호출용)
        window.documentViewerInstance = this;
        
        try {
            // 모듈 초기화
            await this.initializeModules();
            
            // URL 파라미터 처리
            this.parseUrlParameters();
            
            // 문서 로드
            await this.loadDocument();
            
            console.log('✅ DocumentViewer 초기화 완료');
        } catch (error) {
            console.error('❌ DocumentViewer 초기화 실패:', error);
            this.error = error.message;
            this.loading = false;
        }
    },

    // ==================== 모듈 초기화 (지연 로딩 + 폴백) ====================
    async initializeModules() {
        console.log('🔧 모듈 초기화 시작 (지연 로딩)');
        
        // API 및 캐시 초기화
        this.api = new DocumentServerAPI();
        
        // 토큰 설정 (인증 확인)
        const token = localStorage.getItem('access_token');
        if (token) {
            this.api.setToken(token);
            console.log('🔐 API 토큰 설정 완료');
        } else {
            console.error('❌ 인증 토큰이 없습니다!');
            throw new Error('인증이 필요합니다');
        }
        
        this.cache = new CacheManager();
        this.cachedApi = new CachedAPI(this.api, this.cache);
        
        // 직접 모듈 인스턴스 생성 (모든 모듈이 HTML에서 로드됨)
        if (window.DocumentLoader && window.UIManager && window.HighlightManager && 
            window.LinkManager && window.BookmarkManager) {
            
            this.documentLoader = new window.DocumentLoader(this.cachedApi);
            this.uiManager = new window.UIManager();
            this.highlightManager = new window.HighlightManager(this.cachedApi);
            this.linkManager = new window.LinkManager(this.cachedApi);
            this.bookmarkManager = new window.BookmarkManager(this.cachedApi);
            
            console.log('✅ 모든 모듈 직접 로드 성공');
        } else {
            console.error('❌ 필수 모듈이 로드되지 않음');
            console.log('사용 가능한 모듈:', {
                DocumentLoader: !!window.DocumentLoader,
                UIManager: !!window.UIManager,
                HighlightManager: !!window.HighlightManager,
                LinkManager: !!window.LinkManager,
                BookmarkManager: !!window.BookmarkManager
            });
            throw new Error('필수 모듈을 로드할 수 없습니다.');
        }
        
        // UI 상태를 UIManager와 동기화 (모달은 초기화 시 닫힌 상태로)
        this.syncUIState();
        
        // 초기화 시 모든 모달을 명시적으로 닫기
        this.closeAllModals();
        
        // 나머지 모듈들은 백그라운드에서 프리로딩 (지연 로딩 가능한 경우만)
        if (window.moduleLoader) {
            window.moduleLoader.preloadModules(['HighlightManager', 'BookmarkManager', 'LinkManager']);
        }
        
        console.log('✅ 모듈 초기화 완료');
    },

    // ==================== UI 상태 동기화 ====================
    syncUIState() {
        // UIManager의 상태를 Alpine.js 컴포넌트와 동기화 (getter/setter 방식)
        
        // 패널 상태 동기화
        Object.defineProperty(this, 'showNotesPanel', {
            get: () => this.uiManager.showNotesPanel,
            set: (value) => { this.uiManager.showNotesPanel = value; }
        });
        
        Object.defineProperty(this, 'showBookmarksPanel', {
            get: () => this.uiManager.showBookmarksPanel,
            set: (value) => { this.uiManager.showBookmarksPanel = value; }
        });
        
        Object.defineProperty(this, 'showBacklinks', {
            get: () => this.uiManager.showBacklinks,
            set: (value) => { this.uiManager.showBacklinks = value; }
        });
        
        Object.defineProperty(this, 'activePanel', {
            get: () => this.uiManager.activePanel,
            set: (value) => { this.uiManager.activePanel = value; }
        });
        
        // 모달 상태 동기화 (UIManager와 실시간 연동)
        this.updateModalStates();
        
        // 검색 상태 동기화
        Object.defineProperty(this, 'noteSearchQuery', {
            get: () => this.uiManager.noteSearchQuery,
            set: (value) => { this.uiManager.updateNoteSearchQuery(value); }
        });
        
        Object.defineProperty(this, 'filteredNotes', {
            get: () => this.uiManager.filteredNotes,
            set: (value) => { this.uiManager.filteredNotes = value; }
        });
        
        // 모드 및 핸들러 상태
        this.activeMode = null;
        this.textSelectionHandler = null;
        this.editingNote = null;
        this.editingBookmark = null;
        this.editingLink = null;
        this.noteLoading = false;
        this.bookmarkLoading = false;
        this.linkLoading = false;
    },

    // ==================== 모달 상태 업데이트 ====================
    updateModalStates() {
        // UIManager의 모달 상태를 ViewerCore의 속성에 반영
        if (this.uiManager) {
            this.showLinksModal = this.uiManager.showLinksModal;
            this.showLinkModal = this.uiManager.showLinkModal;
            this.showNotesModal = this.uiManager.showNotesModal;
            this.showBookmarksModal = this.uiManager.showBookmarksModal;
            this.showBacklinksModal = this.uiManager.showBacklinksModal;
            this.activeFeatureMenu = this.uiManager.activeFeatureMenu;
            this.searchQuery = this.uiManager.searchQuery;
        }
    },

    // ==================== 모든 모달 닫기 ====================
    closeAllModals() {
        console.log('🔒 초기화 시 모든 모달 닫기');
        this.showLinksModal = false;
        this.showLinkModal = false;
        this.showNotesModal = false;
        this.showBookmarksModal = false;
        this.showBacklinksModal = false;
        this.showNoteInputModal = false;
        
        // UIManager에도 반영
        if (this.uiManager) {
            this.uiManager.closeAllModals();
        }
    },

    // ==================== URL 파라미터 처리 ====================
    parseUrlParameters() {
        const urlParams = new URLSearchParams(window.location.search);
        const rawId = urlParams.get('id');
        
        // null 문자열이나 빈 값 처리
        if (!rawId || rawId === 'null' || rawId === 'undefined' || rawId.trim() === '') {
            console.error('❌ 유효하지 않은 문서 ID:', rawId);
            throw new Error('유효한 문서 ID가 필요합니다. URL을 확인해주세요.');
        }
        
        this.documentId = rawId;
        // contentType 파라미터를 올바르게 가져오기 (type과 contentType 둘 다 지원)
        this.contentType = urlParams.get('contentType') || urlParams.get('type') || 'document';
        
        console.log('🔍 URL 파싱 결과:', {
            rawId: rawId,
            documentId: this.documentId,
            contentType: this.contentType,
            fullURL: window.location.href
        });
    },

    // ==================== 문서 로드 ====================
    async loadDocument() {
        console.log('📄 문서 로드 시작');
        this.loading = true;
        
        try {
            // 문서 데이터 로드
            if (this.contentType === 'note') {
                this.document = await this.documentLoader.loadNote(this.documentId);
                this.navigation = null; // 노트는 네비게이션 없음
            } else {
                this.document = await this.documentLoader.loadDocument(this.documentId);
                // 네비게이션 별도 로드
                this.navigation = await this.documentLoader.loadNavigation(this.documentId);
                
                // PDF 문서인 경우 PDF 뷰어 준비
                if (this.document && this.document.pdf_path) {
                    await this.loadPdfViewer();
                }
            }
            
            // 관련 데이터 병렬 로드
            await this.loadDocumentData();
            
            // 데이터를 모듈에 전달
            this.distributeDataToModules();
            
            // 렌더링
            await this.renderAllFeatures();
            
            // URL 하이라이트 처리
            await this.handleUrlHighlight();
            
            this.loading = false;
            console.log('✅ 문서 로드 완료');
            
        } catch (error) {
            console.error('❌ 문서 로드 실패:', error);
            this.error = error.message;
            this.loading = false;
        }
    },

    // ==================== 문서 데이터 로드 (지연 로딩) ====================
    async loadDocumentData() {
        console.log('📊 문서 데이터 로드 시작');
        
        const [highlights, notes, bookmarks, documentLinks, backlinks] = await Promise.all([
            this.highlightManager.loadHighlights(this.documentId, this.contentType),
            this.highlightManager.loadNotes(this.documentId, this.contentType),
            this.bookmarkManager.loadBookmarks(this.documentId),
            this.linkManager.loadDocumentLinks(this.documentId, this.contentType),
            this.linkManager.loadBacklinks(this.documentId, this.contentType)
        ]);
        
        // 데이터 저장 및 모듈 동기화
        this.highlights = highlights;
        this.notes = notes;
        this.bookmarks = bookmarks;
        this.documentLinks = documentLinks;
        this.backlinks = backlinks;
        
        // 모듈에 데이터 동기화 (중요!)
        this.linkManager.documentLinks = documentLinks;
        this.linkManager.backlinks = backlinks;
        
        console.log('📊 로드된 데이터:', {
            highlights: highlights.length,
            notes: notes.length,
            bookmarks: bookmarks.length,
            documentLinks: documentLinks.length,
            backlinks: backlinks.length
        });
        
        console.log('🔄 모듈 데이터 동기화 완료:', {
            'linkManager.documentLinks': this.linkManager.documentLinks?.length || 0,
            'linkManager.backlinks': this.linkManager.backlinks?.length || 0
        });
    },

    // ==================== 모듈 지연 로딩 보장 (폴백 포함) ====================
    async ensureModulesLoaded(moduleNames) {
        const missingModules = [];
        
        for (const moduleName of moduleNames) {
            const propertyName = this.getModulePropertyName(moduleName);
            if (!this[propertyName]) {
                missingModules.push(moduleName);
            }
        }
        
        if (missingModules.length > 0) {
            console.log(`🔄 필요한 모듈 지연 로딩: ${missingModules.join(', ')}`);
            
            // 각 모듈을 개별적으로 로드
            for (const moduleName of missingModules) {
                const propertyName = this.getModulePropertyName(moduleName);
                
                try {
                    // 지연 로딩 시도
                    if (window.moduleLoader) {
                        const ModuleClass = await window.moduleLoader.loadModule(moduleName);
                        
                        if (moduleName === 'UIManager') {
                            this[propertyName] = new ModuleClass();
                        } else {
                            this[propertyName] = new ModuleClass(this.cachedApi);
                        }
                        
                        console.log(`✅ 지연 로딩 성공: ${moduleName}`);
                    } else {
                        throw new Error('ModuleLoader 없음');
                    }
                } catch (error) {
                    console.warn(`⚠️ 지연 로딩 실패, 폴백 시도: ${moduleName}`, error);
                    
                    // 폴백: 전역 클래스 직접 사용
                    if (window[moduleName]) {
                        if (moduleName === 'UIManager') {
                            this[propertyName] = new window[moduleName]();
                        } else {
                            this[propertyName] = new window[moduleName](this.cachedApi);
                        }
                        
                        console.log(`✅ 폴백 성공: ${moduleName}`);
                    } else {
                        console.error(`❌ 폴백도 실패: ${moduleName} - 전역 클래스 없음`);
                        throw new Error(`모듈을 로드할 수 없습니다: ${moduleName}`);
                    }
                }
            }
        }
    },

    // ==================== 모듈명 → 속성명 변환 ====================
    getModulePropertyName(moduleName) {
        const nameMap = {
            'DocumentLoader': 'documentLoader',
            'HighlightManager': 'highlightManager',
            'BookmarkManager': 'bookmarkManager',
            'LinkManager': 'linkManager',
            'UIManager': 'uiManager'
        };
        return nameMap[moduleName];
    },

    // ==================== 모듈에 데이터 분배 ====================
    distributeDataToModules() {
        // HighlightManager에 데이터 전달
        this.highlightManager.highlights = this.highlights;
        this.highlightManager.notes = this.notes;
        
        // BookmarkManager에 데이터 전달
        this.bookmarkManager.bookmarks = this.bookmarks;
        
        // LinkManager에 데이터 전달
        this.linkManager.documentLinks = this.documentLinks;
        this.linkManager.backlinks = this.backlinks;
    },

    // ==================== 모든 기능 렌더링 ====================
    async renderAllFeatures() {
        console.log('🎨 모든 기능 렌더링 시작');
        
        // 하이라이트 렌더링
        this.highlightManager.renderHighlights();
        
        // 백링크 먼저 렌더링 (링크보다 먼저)
        this.linkManager.renderBacklinks();
        
        // 문서 링크 렌더링 (백링크 후에 렌더링)
        this.linkManager.renderDocumentLinks();
        
        console.log('✅ 모든 기능 렌더링 완료');
    },

    // ==================== URL 하이라이트 처리 ====================
    async handleUrlHighlight() {
        const urlParams = new URLSearchParams(window.location.search);
        const highlightText = urlParams.get('highlight');
        const startOffset = parseInt(urlParams.get('start_offset'));
        const endOffset = parseInt(urlParams.get('end_offset'));
        
        if (highlightText || (startOffset && endOffset)) {
            console.log('🎯 URL에서 하이라이트 요청:', { highlightText, startOffset, endOffset });
            await this.documentLoader.highlightAndScrollToText({ 
                text: highlightText, 
                start_offset: startOffset, 
                end_offset: endOffset 
            });
        }
    },

    // ==================== 기능 모드 활성화 ====================
    activateLinkMode() {
        console.log('🔗 링크 모드 활성화');
        this.activeMode = 'link';
        
        // 선택된 텍스트 확인
        const selectedText = window.getSelection().toString().trim();
        const selection = window.getSelection();
        
        if (!selectedText || selection.rangeCount === 0) {
            alert('텍스트를 먼저 선택해주세요.');
            return;
        }
        
        const selectedRange = selection.getRangeAt(0);
        this.linkManager.createLinkFromSelection(this.documentId, selectedText, selectedRange);
    },



    activateNoteMode() {
        console.log('📝 메모 모드 활성화');
        this.activeMode = 'memo';
        this.highlightManager.activateNoteMode();
    },

    async loadBacklinks() {
        console.log('🔗 백링크 로드 시작');
        if (this.linkManager) {
            await this.linkManager.loadBacklinks(this.documentId, this.contentType);
            // UI 상태 동기화
            this.backlinks = this.linkManager.backlinks || [];
        }
    },

    // 링크 대상 타입 변경 시 호출
    async onTargetTypeChange() {
        console.log('🔄 링크 대상 타입 변경:', this.linkForm.target_type);
        
        // 기존 선택 초기화
        this.linkForm.target_book_id = '';
        this.linkForm.target_document_id = '';
        this.availableBooks = [];
        this.filteredDocuments = [];
        
        // 선택된 타입에 따라 데이터 로드
        if (this.linkForm.target_type === 'note') {
            await this.loadNotebooks();
        } else {
            await this.loadBooks();
        }
    },

    // 노트북 목록 로드
    async loadNotebooks() {
        try {
            console.log('📚 노트북 목록 로딩 시작...');
            
            const notebooks = await this.api.get('/notebooks/', { active_only: true });
            this.availableBooks = notebooks.map(notebook => ({
                id: notebook.id,
                title: notebook.title
            })) || [];
            
            console.log('📚 로드된 노트북 목록:', this.availableBooks.length, '개');
        } catch (error) {
            console.error('노트북 목록 로드 실패:', error);
            this.availableBooks = [];
        }
    },

    // 서적 목록 로드
    async loadBooks() {
        try {
            console.log('📚 서적 목록 로딩 시작...');
            
            let allDocuments;
            
            // contentType에 따라 다른 API 사용
            if (this.contentType === 'note') {
                // 노트의 경우 전체 문서 목록에서 서적 정보 추출
                console.log('📝 노트 모드: 전체 문서 목록에서 서적 정보 추출');
                allDocuments = await this.api.getDocuments();
                console.log('📄 전체 문서들 (총 개수):', allDocuments.length);
            } else {
                // 일반 문서의 경우 linkable-documents API 사용
                console.log('📄 문서 모드: linkable-documents API 사용');
                allDocuments = await this.api.getLinkableDocuments(this.documentId);
                console.log('📄 링크 가능한 문서들 (총 개수):', allDocuments.length);
            }
            
            // 서적별로 그룹화
            const bookMap = new Map();
            allDocuments.forEach(doc => {
                if (doc.book_id && doc.book_title) {
                    bookMap.set(doc.book_id, {
                        id: doc.book_id,
                        title: doc.book_title
                    });
                }
            });
            
            this.availableBooks = Array.from(bookMap.values());
            console.log('📚 로드된 서적 목록:', this.availableBooks.length, '개');
        } catch (error) {
            console.error('서적 목록 로드 실패:', error);
            this.availableBooks = [];
        }
    },

    async loadAvailableBooks() {
        try {
            // 기본값으로 문서 타입 설정 (기존 호환성)
            if (this.linkForm.target_type === 'note') {
                await this.loadNotebooks();
            } else {
                await this.loadBooks();
            }
        } catch (error) {
            console.error('목록 로드 실패:', error);
            this.availableBooks = [];
        }
    },

    getSourceBookInfo(allDocuments = null) {
        // 여러 소스에서 현재 문서의 서적 정보 찾기
        let sourceBookId = this.navigation?.book_info?.id || 
                          this.document?.book_id || 
                          this.document?.book_info?.id;
        
        let sourceBookTitle = this.navigation?.book_info?.title || 
                             this.document?.book_title || 
                             this.document?.book_info?.title;
        
        // allDocuments에서도 확인 (가장 확실한 방법)
        if (allDocuments) {
            const currentDoc = allDocuments.find(doc => doc.id === this.documentId);
            if (currentDoc) {
                sourceBookId = currentDoc.book_id;
                sourceBookTitle = currentDoc.book_title;
            }
        }
        
        return {
            id: sourceBookId,
            title: sourceBookTitle
        };
    },

    async loadSameBookDocuments() {
        try {
            if (this.contentType === 'note') {
                console.log('📚 같은 노트북의 노트들 로드 시작...');
                
                // 현재 노트의 노트북 정보 가져오기
                const currentNote = this.document;
                const notebookId = currentNote?.notebook_id;
                
                if (notebookId) {
                    // 같은 노트북의 노트들 로드 (현재 노트 제외)
                    const notes = await this.api.getNotesInNotebook(notebookId);
                    
                    this.filteredDocuments = notes.filter(note => note.id !== this.documentId);
                    console.log('📚 같은 노트북 노트들:', {
                        count: this.filteredDocuments.length,
                        notebookId: notebookId,
                        notes: this.filteredDocuments.map(note => ({ id: note.id, title: note.title }))
                    });
                } else {
                    console.warn('⚠️ 현재 노트의 노트북 정보를 찾을 수 없습니다');
                    this.filteredDocuments = [];
                }
                return;
            }
            
            const allDocuments = await this.api.getLinkableDocuments(this.documentId);
            
            // 소스 문서의 서적 정보 가져오기
            const sourceBookInfo = this.getSourceBookInfo(allDocuments);
            
            console.log('📚 같은 서적 문서 로드 시작:', {
                sourceBookId: sourceBookInfo.id,
                sourceBookTitle: sourceBookInfo.title,
                totalDocs: allDocuments.length
            });
            
            if (sourceBookInfo.id) {
                // 소스 문서와 같은 서적의 문서들만 필터링 (현재 문서 제외)
                this.filteredDocuments = allDocuments.filter(doc => 
                    doc.book_id === sourceBookInfo.id && doc.id !== this.documentId
                );
                console.log('📚 같은 서적 문서들:', {
                    count: this.filteredDocuments.length,
                    bookTitle: sourceBookInfo.title,
                    documents: this.filteredDocuments.map(doc => ({ id: doc.id, title: doc.title }))
                });
            } else {
                console.warn('⚠️ 소스 문서의 서적 정보를 찾을 수 없습니다!');
                this.filteredDocuments = [];
            }
        } catch (error) {
            console.error('같은 서적/노트북 문서 로드 실패:', error);
            this.filteredDocuments = [];
        }
    },

    async loadSameBookDocumentsForSelected() {
        try {
            console.log('📚 선택한 문서 기준으로 같은 서적 문서 로드 시작');
            
            const allDocuments = await this.api.getLinkableDocuments(this.documentId);
            
            // 선택한 대상 문서 찾기
            const selectedDoc = allDocuments.find(doc => doc.id === this.linkForm.target_document_id);
            
            if (!selectedDoc) {
                console.error('❌ 선택한 문서를 찾을 수 없습니다:', this.linkForm.target_document_id);
                return;
            }
            
            console.log('🎯 선택한 문서 정보:', {
                id: selectedDoc.id,
                title: selectedDoc.title,
                bookId: selectedDoc.book_id,
                bookTitle: selectedDoc.book_title
            });
            
            // 선택한 문서와 같은 서적의 모든 문서들 (소스 문서 제외)
            this.filteredDocuments = allDocuments.filter(doc => 
                doc.book_id === selectedDoc.book_id && doc.id !== this.documentId
            );
            
            console.log('📚 선택한 문서와 같은 서적 문서들:', {
                selectedBookTitle: selectedDoc.book_title,
                count: this.filteredDocuments.length,
                documents: this.filteredDocuments.map(doc => ({ id: doc.id, title: doc.title }))
            });
            
        } catch (error) {
            console.error('선택한 문서 기준 같은 서적 로드 실패:', error);
            this.filteredDocuments = [];
        }
    },

    async loadDocumentsFromBook() {
        try {
            if (this.linkForm.target_book_id) {
                if (this.linkForm.target_type === 'note') {
                    // 노트북 선택: 선택된 노트북의 노트들 가져오기
                    const notes = await this.api.getNotesInNotebook(this.linkForm.target_book_id);
                    this.filteredDocuments = notes.filter(note => note.id !== this.documentId);
                    console.log('📚 선택된 노트북 노트들:', this.filteredDocuments);
                } else {
                    // 서적 선택: 선택된 서적의 문서들만 가져오기
                    let allDocuments;
                    
                    if (this.contentType === 'note') {
                        // 노트에서 서적 문서를 선택하는 경우: 전체 문서 목록에서 HTML이 있는 문서만 필터링
                        console.log('📝 노트에서 서적 문서 선택: HTML 문서만 필터링');
                        const allDocs = await this.api.getDocuments();
                        allDocuments = allDocs.filter(doc => doc.html_path && doc.html_path !== null);
                        console.log('📝 HTML 문서 필터링 결과:', allDocuments.length, '개');
                    } else {
                        // 일반 문서에서 서적 문서를 선택하는 경우: linkable-documents API 사용
                        console.log('📄 문서에서 서적 문서 선택: linkable-documents API 사용');
                        allDocuments = await this.api.getLinkableDocuments(this.documentId);
                    }
                    
                    this.filteredDocuments = allDocuments.filter(doc => 
                        doc.book_id === this.linkForm.target_book_id
                    );
                    console.log('📚 선택된 서적 문서들:', this.filteredDocuments);
                }
            } else {
                this.filteredDocuments = [];
            }
            
            // 문서 선택 초기화
            this.linkForm.target_document_id = '';
        } catch (error) {
            console.error('서적/노트북별 문서 로드 실패:', error);
            this.filteredDocuments = [];
        }
    },

    resetTargetSelection() {
        console.log('🔄 대상 선택 초기화');
        this.linkForm.target_book_id = '';
        this.linkForm.target_document_id = '';
        this.filteredDocuments = [];
        
        // 초기화 후 아무것도 하지 않음 (서적 선택 후 문서 로드)
    },

    async onTargetDocumentChange() {
        console.log('📄 대상 문서 변경:', this.linkForm.target_document_id);
        
        // 대상 문서 변경 시 특별한 처리 없음
    },

    selectTextFromDocument() {
        console.log('🎯 대상 문서에서 텍스트 선택 시작');
        
        if (!this.linkForm.target_document_id) {
            alert('대상 문서를 먼저 선택해주세요.');
            return;
        }

        // 새 창에서 대상 문서 열기 (텍스트 선택 모드 전용 페이지)
        const targetContentType = this.linkForm.target_type === 'note' ? 'note' : 'document';
        const targetUrl = `/text-selector.html?id=${this.linkForm.target_document_id}&contentType=${targetContentType}`;
        console.log('🚀 텍스트 선택 창 열기:', targetUrl, 'contentType:', targetContentType);
        const popup = window.open(targetUrl, 'targetDocumentSelector', 'width=1200,height=800,scrollbars=yes,resizable=yes');
        
        if (!popup) {
            console.error('❌ 팝업 창이 차단되었습니다!');
            alert('팝업 창이 차단되었습니다. 브라우저 설정에서 팝업을 허용해주세요.');
        } else {
            console.log('✅ 팝업 창이 성공적으로 열렸습니다');
        }
        
        // 팝업에서 텍스트 선택 완료 시 메시지 수신
        window.addEventListener('message', (event) => {
            if (event.data.type === 'TEXT_SELECTED') {
                this.linkForm.target_text = event.data.selectedText;
                this.linkForm.target_start_offset = event.data.startOffset;
                this.linkForm.target_end_offset = event.data.endOffset;
                console.log('🎯 대상 텍스트 선택됨:', event.data);
                popup.close();
            }
        }, { once: true });
    },

    activateBookmarkMode() {
        console.log('🔖 북마크 모드 활성화');
        this.activeMode = 'bookmark';
        this.bookmarkManager.activateBookmarkMode();
    },

    // ==================== 하이라이트 기능 위임 ====================
    createHighlightWithColor(color) {
        console.log('🎨 하이라이트 생성 요청:', color);
        // ViewerCore의 selectedHighlightColor도 동기화
        this.selectedHighlightColor = color;
        console.log('🎨 ViewerCore 색상 동기화:', this.selectedHighlightColor);
        return this.highlightManager.createHighlightWithColor(color);
    },

    // ==================== 메모 입력 모달 관련 ====================
    openNoteInputModal() {
        console.log('📝 메모 입력 모달 열기');
        this.showNoteInputModal = true;
        // 폼 초기화
        this.noteForm.content = '';
        this.noteForm.tags = '';
        // 포커스를 textarea로 이동 (다음 틱에서)
        this.$nextTick(() => {
            const textarea = document.querySelector('textarea[x-model="noteForm.content"]');
            if (textarea) textarea.focus();
        });
    },

    closeNoteInputModal() {
        console.log('📝 메모 입력 모달 닫기');
        this.showNoteInputModal = false;
        this.noteForm.content = '';
        this.noteForm.tags = '';
        // 선택된 텍스트 정리
        this.selectedText = '';
        this.selectedRange = null;
    },

    async createNoteForHighlight() {
        console.log('📝 하이라이트에 메모 생성');
        if (!this.noteForm.content.trim()) {
            alert('메모 내용을 입력해주세요.');
            return;
        }

        try {
            // 현재 생성된 하이라이트 정보가 필요함
            if (this.highlightManager.lastCreatedHighlight) {
                await this.highlightManager.createNoteForHighlight(
                    this.highlightManager.lastCreatedHighlight,
                    this.noteForm.content.trim(),
                    this.noteForm.tags.trim()
                );
                this.closeNoteInputModal();
            } else {
                alert('하이라이트 정보를 찾을 수 없습니다.');
            }
        } catch (error) {
            console.error('메모 생성 실패:', error);
            alert('메모 생성에 실패했습니다: ' + error.message);
        }
    },

    skipNoteForHighlight() {
        console.log('📝 메모 입력 건너뛰기');
        this.closeNoteInputModal();
    },

    // ==================== UI 메서드 위임 ====================
    toggleFeatureMenu(feature) {
        const result = this.uiManager.toggleFeatureMenu(feature);
        this.updateModalStates(); // 상태 동기화
        return result;
    },

    openNoteModal(highlight = null) {
        const result = this.uiManager.openNoteModal(highlight);
        this.updateModalStates(); // 상태 동기화
        return result;
    },

    closeNoteModal() {
        const result = this.uiManager.closeNoteModal();
        this.updateModalStates(); // 상태 동기화
        return result;
    },

    closeLinkModal() {
        const result = this.uiManager.closeLinkModal();
        this.updateModalStates(); // 상태 동기화
        return result;
    },

    closeBookmarkModal() {
        const result = this.uiManager.closeBookmarkModal();
        this.updateModalStates(); // 상태 동기화
        return result;
    },

    highlightSearchResults(element, searchText) {
        return this.uiManager.highlightSearchResults(element, searchText);
    },

    showSuccessMessage(message) {
        return this.uiManager.showSuccessMessage(message);
    },

    showErrorMessage(message) {
        return this.uiManager.showErrorMessage(message);
    },

    // ==================== 언어 전환 ====================
    toggleLanguage() {
        this.isKorean = !this.isKorean;
        const lang = this.isKorean ? 'ko' : 'en';
        console.log('🌐 언어 전환:', this.isKorean ? '한국어' : 'English');
        
        // 문서에 내장된 언어 전환 기능 찾기 및 실행
        this.findAndExecuteBuiltinLanguageToggle();
    },

    // 문서에 내장된 언어 전환 기능 찾기
    findAndExecuteBuiltinLanguageToggle() {
        console.log('🔍 문서 내장 언어 전환 기능 찾기 시작');
        
        const content = document.getElementById('document-content');
        if (!content) {
            console.warn('❌ document-content 요소를 찾을 수 없습니다');
            return;
        }
        
        // 1. 언어 전환 버튼 찾기 (다양한 패턴)
        const buttonSelectors = [
            'button[onclick*="toggleLanguage"]',
            'button[onclick*="language"]', 
            'button[onclick*="Language"]',
            '.language-toggle',
            '.lang-toggle',
            'button[id*="lang"]',
            'button[class*="lang"]',
            'input[type="button"][onclick*="language"]'
        ];
        
        let foundButton = null;
        for (const selector of buttonSelectors) {
            const buttons = content.querySelectorAll(selector);
            if (buttons.length > 0) {
                foundButton = buttons[0];
                console.log(`✅ 언어 전환 버튼 발견 (${selector}):`, foundButton.outerHTML.substring(0, 100));
                break;
            }
        }
        
        // 2. 버튼이 있으면 클릭
        if (foundButton) {
            console.log('🔘 내장 언어 전환 버튼 클릭');
            try {
                foundButton.click();
                console.log('✅ 언어 전환 버튼 클릭 완료');
                return;
            } catch (error) {
                console.error('❌ 버튼 클릭 실패:', error);
            }
        }
        
        // 3. 버튼이 없으면 스크립트 함수 직접 호출 시도
        this.tryDirectLanguageFunction();
    },

    // 직접 언어 전환 함수 호출 시도
    tryDirectLanguageFunction() {
        console.log('🔧 직접 언어 전환 함수 호출 시도');
        
        const functionNames = [
            'toggleLanguage',
            'changeLanguage', 
            'switchLanguage',
            'toggleLang',
            'changeLang'
        ];
        
        for (const funcName of functionNames) {
            if (typeof window[funcName] === 'function') {
                console.log(`✅ 전역 함수 발견: ${funcName}`);
                try {
                    window[funcName]();
                    console.log(`✅ ${funcName}() 호출 완료`);
                    return;
                } catch (error) {
                    console.error(`❌ ${funcName}() 호출 실패:`, error);
                }
            }
        }
        
        // 4. 문서 내 스크립트에서 함수 찾기
        this.findLanguageFunctionInScripts();
    },

    // 문서 내 스크립트에서 언어 전환 함수 찾기
    findLanguageFunctionInScripts() {
        console.log('📜 문서 내 스크립트에서 언어 함수 찾기');
        
        const content = document.getElementById('document-content');
        const scripts = content.querySelectorAll('script');
        
        console.log(`📜 발견된 스크립트 태그: ${scripts.length}개`);
        
        scripts.forEach((script, index) => {
            const scriptContent = script.textContent || script.innerHTML;
            if (scriptContent.includes('language') || scriptContent.includes('Language') || scriptContent.includes('lang')) {
                console.log(`📜 스크립트 ${index + 1}에서 언어 관련 코드 발견:`, scriptContent.substring(0, 200));
                
                // 함수 실행 시도
                try {
                    eval(scriptContent);
                    console.log(`✅ 스크립트 ${index + 1} 실행 완료`);
                } catch (error) {
                    console.log(`⚠️ 스크립트 ${index + 1} 실행 실패:`, error.message);
                }
            }
        });
        
        console.log('⚠️ 내장 언어 전환 기능을 찾을 수 없습니다');
    },



    async downloadOriginalFile() {
        if (!this.document || !this.document.id) {
            console.warn('문서 정보가 없습니다');
            return;
        }
        
        console.log('📕 PDF 다운로드 시도:', {
            id: this.document.id,
            matched_pdf_id: this.document.matched_pdf_id,
            pdf_path: this.document.pdf_path
        });
        
        // 캐시를 무시하고 최신 문서 정보를 다시 가져오기
        console.log('🔄 최신 문서 정보 재로드 중...');
        try {
            const freshDocument = await this.api.getDocument(this.document.id);
            console.log('📄 최신 문서 정보:', {
                id: freshDocument.id,
                matched_pdf_id: freshDocument.matched_pdf_id,
                pdf_path: freshDocument.pdf_path
            });
            
            // 최신 정보로 업데이트
            if (freshDocument.matched_pdf_id !== this.document.matched_pdf_id) {
                console.log('🔄 PDF 매칭 정보 업데이트:', {
                    old: this.document.matched_pdf_id,
                    new: freshDocument.matched_pdf_id
                });
                this.document.matched_pdf_id = freshDocument.matched_pdf_id;
            }
        } catch (error) {
            console.error('❌ 최신 문서 정보 로드 실패:', error);
        }
        
        // 1. 현재 문서 자체가 PDF인 경우
        if (this.document.pdf_path) {
            console.log('📄 현재 문서가 PDF - 직접 다운로드');
            this.downloadPdfFile(this.document.pdf_path, this.document.title || 'document');
            return;
        }
        
        // 2. 연결된 PDF가 있는지 확인
        if (!this.document.matched_pdf_id) {
            alert('연결된 원본 PDF 파일이 없습니다.\n\n서적 편집 페이지에서 PDF 파일을 연결해주세요.');
            return;
        }
        
        try {
            console.log('📕 연결된 PDF 다운로드 시작:', this.document.matched_pdf_id);
            
            // 연결된 PDF 문서 정보 가져오기
            const pdfDocument = await this.api.getDocument(this.document.matched_pdf_id);
            
            if (!pdfDocument) {
                throw new Error('연결된 PDF 문서를 찾을 수 없습니다');
            }
            
            // PDF 파일 다운로드 URL 생성
            const downloadUrl = `/api/documents/${this.document.matched_pdf_id}/download`;
            
            // 인증 헤더 추가를 위해 fetch 사용
            const response = await fetch(downloadUrl, {
                method: 'GET',
                headers: {
                    'Authorization': `Bearer ${localStorage.getItem('access_token')}`
                }
            });
            
            if (!response.ok) {
                throw new Error('연결된 PDF 다운로드에 실패했습니다');
            }
            
            // Blob으로 변환하여 다운로드
            const blob = await response.blob();
            const url = window.URL.createObjectURL(blob);
            
            // 다운로드 링크 생성 및 클릭
            const link = document.createElement('a');
            link.href = url;
            link.download = pdfDocument.original_filename || `${pdfDocument.title}.pdf`;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            // URL 정리
            window.URL.revokeObjectURL(url);
            
            console.log('📕 PDF 다운로드 완료:', pdfDocument.original_filename);
            
        } catch (error) {
            console.error('PDF 다운로드 오류:', error);
            alert('PDF 다운로드 중 오류가 발생했습니다: ' + error.message);
        }
    },

    // PDF 파일 직접 다운로드
    downloadPdfFile(pdfPath, filename) {
        try {
            console.log('📄 PDF 파일 직접 다운로드:', pdfPath);
            
            // PDF 파일 URL 생성 (상대 경로를 절대 경로로 변환)
            let pdfUrl = pdfPath;
            if (!pdfUrl.startsWith('http')) {
                // 상대 경로인 경우 현재 도메인 기준으로 절대 경로 생성
                const baseUrl = window.location.origin;
                pdfUrl = pdfUrl.startsWith('/') ? baseUrl + pdfUrl : baseUrl + '/' + pdfUrl;
            }
            
            console.log('📄 PDF URL:', pdfUrl);
            
            // 다운로드 링크 생성 및 클릭
            const link = document.createElement('a');
            link.href = pdfUrl;
            link.download = filename.endsWith('.pdf') ? filename : filename + '.pdf';
            link.target = '_blank'; // 새 탭에서 열기 (다운로드 실패 시 뷰어로 열림)
            
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            console.log('✅ PDF 다운로드 링크 클릭 완료');
            
        } catch (error) {
            console.error('PDF 다운로드 오류:', error);
            alert('PDF 다운로드 중 오류가 발생했습니다: ' + error.message);
        }
    },

    // ==================== 통합 툴팁 처리 ====================
    /**
     * 클릭된 요소에서 링크, 백링크, 하이라이트 모두 찾기 (완전 개선 버전)
     */
    getOverlappingElements(clickedElement) {
        const selectedText = clickedElement.textContent.trim();
        console.log('🔍 통합 요소 찾기 시작:', selectedText);
        console.log('🔍 하이라이트 매니저 상태:', {
            highlightManager: !!this.highlightManager,
            highlightsCount: this.highlightManager?.highlights?.length || 0,
            highlights: this.highlightManager?.highlights || []
        });
        
        // 결과 배열들
        const overlappingLinks = [];
        const overlappingBacklinks = [];
        const overlappingHighlights = [];
        
        // 1. 모든 링크 요소 찾기 (같은 텍스트)
        const allLinkElements = document.querySelectorAll('.document-link');
        allLinkElements.forEach(linkEl => {
            if (linkEl.textContent.trim() === selectedText) {
                const linkId = linkEl.dataset.linkId;
                const link = this.linkManager.documentLinks.find(l => l.id === linkId);
                if (link && !overlappingLinks.find(l => l.id === link.id)) {
                    overlappingLinks.push(link);
                    const linkTitle = link.target_note_title || link.target_document_title || 'Unknown';
                    console.log('✅ 겹치는 링크 발견:', linkTitle);
                }
            }
        });
        
        // 2. 모든 백링크 요소 찾기 (같은 텍스트)
        const allBacklinkElements = document.querySelectorAll('.backlink-highlight');
        allBacklinkElements.forEach(backlinkEl => {
            if (backlinkEl.textContent.trim() === selectedText) {
                const backlinkId = backlinkEl.dataset.backlinkId;
                const backlink = this.linkManager.backlinks.find(b => b.id === backlinkId);
                if (backlink && !overlappingBacklinks.find(b => b.id === backlink.id)) {
                    overlappingBacklinks.push(backlink);
                    console.log('✅ 겹치는 백링크 발견:', backlink.source_document_title);
                }
            }
        });
        
        // 3. 모든 하이라이트 요소 찾기 (같은 텍스트)
        const allHighlightElements = document.querySelectorAll('.highlight-span');
        console.log('🔍 페이지의 모든 하이라이트 요소:', allHighlightElements.length, '개');
        allHighlightElements.forEach(highlightEl => {
            const highlightText = highlightEl.textContent.trim();
            
            // 텍스트가 정확히 일치하거나 포함 관계인 경우
            if (highlightText === selectedText || 
                highlightText.includes(selectedText) || 
                selectedText.includes(highlightText)) {
                
                const highlightId = highlightEl.dataset.highlightId;
                console.log('🔍 하이라이트 요소 확인:', {
                    element: highlightEl,
                    highlightId: highlightId,
                    text: highlightText,
                    selectedText: selectedText
                });
                
                const highlight = this.highlightManager.highlights.find(h => h.id === highlightId);
                if (highlight && !overlappingHighlights.find(h => h.id === highlight.id)) {
                    overlappingHighlights.push(highlight);
                    console.log('✅ 겹치는 하이라이트 발견:', {
                        id: highlight.id,
                        text: highlightText,
                        color: highlight.highlight_color
                    });
                } else if (!highlight) {
                    console.log('❌ 하이라이트 데이터를 찾을 수 없음:', highlightId);
                }
            }
        });
        
        console.log('📊 최종 발견된 요소들:', {
            links: overlappingLinks.length,
            backlinks: overlappingBacklinks.length,
            highlights: overlappingHighlights.length,
            selectedText: selectedText
        });
        
        return {
            links: overlappingLinks,
            backlinks: overlappingBacklinks,
            highlights: overlappingHighlights,
            selectedText: selectedText
        };
    },

    /**
     * 통합 툴팁 표시 (링크 + 하이라이트 + 백링크)
     */
    async showUnifiedTooltip(overlappingElements, element) {
        const { links = [], highlights = [], backlinks = [], selectedText } = overlappingElements;
        
        console.log('🎯 통합 툴팁 표시:', { 
            links: links.length, 
            highlights: highlights.length, 
            backlinks: backlinks.length 
        });
        
        // 하이라이트가 있으면 메모 데이터 로드
        if (highlights.length > 0) {
            console.log('📝 통합 툴팁용 메모 로드 시작...');
            const documentId = this.documentId;
            const contentType = this.contentType;
            await this.highlightManager.loadNotes(documentId, contentType);
            console.log('📝 통합 툴팁용 메모 로드 완료:', this.highlightManager.notes.length, '개');
        }
        
        // 기존 툴팁들 숨기기
        this.linkManager.hideTooltip();
        this.highlightManager.hideTooltip();
        
        // 툴팁 컨테이너 생성
        const tooltip = document.createElement('div');
        tooltip.id = 'unified-tooltip';
        tooltip.className = 'fixed z-50 bg-white rounded-xl shadow-2xl border border-gray-200';
        tooltip.style.cssText = `
            background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(148, 163, 184, 0.2);
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            max-width: 90vw;
            max-height: 80vh;
            overflow-y: auto;
            z-index: 9999;
        `;
        
        const totalElements = links.length + highlights.length + backlinks.length;
        
        let tooltipHTML = `
            <div class="p-6">
                <div class="mb-4">
                    <div class="flex items-center justify-between mb-3">
                                                     <div class="text-lg font-semibold text-gray-800 flex items-center">
                                 <svg class="w-5 h-5 mr-2 text-purple-600" fill="currentColor" viewBox="0 0 20 20">
                                     <path fill-rule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/>
                            겹치는 요소들
                        </div>
                        <div class="text-xs text-gray-500">${totalElements}개 요소</div>
                    </div>
                    
                    <div class="font-medium text-gray-900 bg-purple-50 px-4 py-3 rounded-lg border-l-4 border-purple-500">
                        <div class="text-sm text-purple-700 mb-1">선택된 텍스트</div>
                        <div class="text-base">"${selectedText}"</div>
                    </div>
                </div>
        `;
        
        // 하이라이트 섹션
        if (highlights.length > 0) {
            tooltipHTML += `
                <div class="mb-6">
                                             <div class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                             <svg class="w-4 h-4 mr-2 text-yellow-600" fill="currentColor" viewBox="0 0 20 20">
                                 <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
                        하이라이트 (${highlights.length}개)
                    </div>
                    <div class="space-y-2">
            `;
            
            highlights.forEach(highlight => {
                const colorName = this.highlightManager.getColorName(highlight.highlight_color);
                const createdDate = this.formatDate(highlight.created_at);
                const notes = this.highlightManager.notes.filter(note => note.highlight_id === highlight.id);
                
                console.log(`📝 통합 툴팁 - 하이라이트 ${highlight.id}의 메모:`, notes.length, '개');
                if (notes.length > 0) {
                    console.log('📝 메모 내용:', notes.map(n => n.content));
                }
                
                tooltipHTML += `
                    <div class="border rounded-lg p-3 bg-gradient-to-r from-yellow-50 to-orange-50 cursor-pointer hover:shadow-md transition-shadow duration-200"
                         onclick="window.documentViewerInstance.highlightManager.showHighlightTooltip([${JSON.stringify(highlight).replace(/"/g, '&quot;')}], this.parentElement)">
                        <div class="flex items-center justify-between">
                            <div class="flex items-center space-x-2">
                                <div class="w-3 h-3 rounded-full" style="background-color: ${highlight.highlight_color}"></div>
                                <span class="text-sm font-medium text-gray-800">${colorName}</span>
                                <span class="text-xs text-gray-500">${createdDate}</span>
                            </div>
                            <div class="text-xs text-gray-600">${notes.length}개 메모</div>
                        </div>
                    </div>
                `;
            });
            
            tooltipHTML += `
                    </div>
                </div>
            `;
        }
        
        // 링크 섹션
        if (links.length > 0) {
            tooltipHTML += `
                <div class="mb-4">
                    <div class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                        <svg class="w-4 h-4 mr-2 text-purple-600" fill="currentColor" viewBox="0 0 20 20">
                            <path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd"/>
                        </svg>
                        링크 (${links.length}개)
                    </div>
                    <div class="space-y-2">
            `;
            
            links.forEach(link => {
                const isNote = link.target_content_type === 'note';
                const bgClass = isNote ? 'from-green-50 to-emerald-50' : 'from-purple-50 to-indigo-50';
                const iconClass = isNote ? 'text-green-600' : 'text-purple-600';
                const createdDate = this.formatDate(link.created_at);
                
                tooltipHTML += `
                    <div class="border rounded-lg p-3 bg-gradient-to-r ${bgClass} transition-colors duration-200 relative group">
                        <div class="flex items-start justify-between">
                            <div class="flex-1 cursor-pointer" onclick="window.documentViewerInstance.navigateToLink(${JSON.stringify(link).replace(/"/g, '&quot;')})">
                                <div class="flex items-center mb-2">
                                                                             <svg class="w-4 h-4 mr-2 ${iconClass}" fill="currentColor" viewBox="0 0 20 20">
                                             ${isNote ? 
                                                 '<path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"/><path fill-rule="evenodd" d="M4 5a2 2 0 012-2v1a1 1 0 102 0V3a2 2 0 012 0v1a1 1 0 102 0V3a2 2 0 012 2v6.586A2 2 0 0115.414 13L13 15.586A2 2 0 0111.586 16H6a2 2 0 01-2-2V5zm8 4a1 1 0 10-2 0v2a1 1 0 102 0V9z" clip-rule="evenodd"/>' :
                                                 '<path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z" clip-rule="evenodd"/>'
                                             }
                                         </svg>
                                    <span class="font-medium ${iconClass}">${link.target_note_title || link.target_document_title}</span>
                                </div>
                                
                                ${link.target_text ? `
                                    <div class="mb-2 p-2 bg-gray-50 rounded border-l-3 ${isNote ? 'border-green-400' : 'border-purple-400'}">
                                        <div class="text-xs ${isNote ? 'text-green-700' : 'text-purple-700'} mb-1">연결된 텍스트</div>
                                        <div class="text-sm text-gray-800 font-medium">"${link.target_text}"</div>
                                    </div>
                                ` : ''}
                                
                                ${link.description ? `
                                    <div class="mb-2 p-2 bg-blue-50 rounded border-l-3 border-blue-400">
                                        <div class="text-xs text-blue-700 mb-1">링크 설명</div>
                                        <div class="text-sm text-blue-800">${link.description}</div>
                                    </div>
                                ` : ''}
                                
                                <div class="text-xs text-gray-500 flex items-center justify-between">
                                    <span class="flex items-center">
                                        <svg class="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
                                            <path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd"/>
                                        ${link.link_type === 'text_fragment' ? '텍스트 조각 링크' : '문서 링크'}
                                    </span>
                                    <span>${createdDate}</span>
                                </div>
                            </div>
                            
                            <!-- 삭제 버튼 -->
                            <button onclick="event.stopPropagation(); window.documentViewerInstance.deleteLinkWithConfirm('${link.id}', '${(link.target_note_title || link.target_document_title).replace(/'/g, "\\'")}');" 
                                    class="ml-3 p-1 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors duration-200 opacity-0 group-hover:opacity-100"
                                    title="링크 삭제">
                                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
                                </svg>
                            </button>
                        </div>
                    </div>
                `;
            });
            
            tooltipHTML += `
                    </div>
                </div>
            `;
        }
        
        // 백링크 섹션
        if (backlinks.length > 0) {
            tooltipHTML += `
                <div class="mb-4">
                    <div class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                        <svg class="w-4 h-4 mr-2 text-orange-600" fill="currentColor" viewBox="0 0 20 20">
                            <path fill-rule="evenodd" d="M7.707 3.293a1 1 0 010 1.414L5.414 7H11a7 7 0 017 7v2a1 1 0 11-2 0v-2a5 5 0 00-5-5H5.414l2.293 2.293a1 1 0 11-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/>
                        </svg>
                        백링크 (${backlinks.length}개)
                    </div>
                    <div class="space-y-2">
            `;
            
            backlinks.forEach(backlink => {
                const createdDate = this.formatDate(backlink.created_at);
                
                tooltipHTML += `
                    <div class="border rounded-lg p-3 bg-gradient-to-r from-orange-50 to-red-50 transition-colors duration-200 relative group">
                        <div class="cursor-pointer" onclick="window.documentViewerInstance.navigateToBacklink(${JSON.stringify(backlink).replace(/"/g, '&quot;')})">
                            <div class="flex items-center mb-2">
                                                                 <svg class="w-4 h-4 mr-2 text-orange-600" fill="currentColor" viewBox="0 0 20 20">
                                     <path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z" clip-rule="evenodd"/>
                                <span class="font-medium text-orange-600">${backlink.source_document_title}</span>
                            </div>
                            
                            <div class="mb-2 p-2 bg-white rounded border-l-3 border-orange-400">
                                <div class="text-xs text-orange-600 mb-1">원본 문서에서 링크로 설정한 텍스트</div>
                                <div class="text-sm text-gray-800 font-medium">"${backlink.selected_text}"</div>
                            </div>
                            
                            ${backlink.target_text ? `
                                <div class="mb-2 p-2 bg-white rounded border-l-3 border-blue-400">
                                    <div class="text-xs text-blue-600 mb-1">현재 문서에서 연결된 구체적인 텍스트</div>
                                    <div class="text-sm text-blue-800 font-medium">"${backlink.target_text}"</div>
                                </div>
                            ` : ''}
                            
                            ${backlink.description ? `
                                <div class="mb-2 p-2 bg-white rounded border-l-3 border-green-400">
                                    <div class="text-xs text-green-600 mb-1">링크 설명</div>
                                    <div class="text-sm text-green-800">${backlink.description}</div>
                                </div>
                            ` : ''}
                            
                            <div class="text-xs text-gray-500 flex items-center justify-between">
                                                                 <span class="flex items-center">
                                     <svg class="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
                                         <path fill-rule="evenodd" d="M7.707 3.293a1 1 0 010 1.414L5.414 7H11a7 7 0 017 7v2a1 1 0 11-2 0v-2a5 5 0 00-5-5H5.414l2.293 2.293a1 1 0 11-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/>
                                    백링크
                                </span>
                                <span>${createdDate}</span>
                            </div>
                        </div>
                    </div>
                `;
            });
            
            tooltipHTML += `
                    </div>
                </div>
            `;
        }
        
        tooltipHTML += `
                <div class="flex justify-end pt-4 border-t border-gray-200">
                    <button onclick="window.documentViewerInstance.hideUnifiedTooltip()" 
                            class="text-xs bg-gray-500 text-white px-3 py-1 rounded hover:bg-gray-600 transition-colors">
                        닫기
                    </button>
                </div>
            </div>
        `;
        
        tooltip.innerHTML = tooltipHTML;
        document.body.appendChild(tooltip);
        
        // 위치 조정
        this.positionTooltip(tooltip, element);
    },

    /**
     * 통합 툴팁 숨기기
     */
    hideUnifiedTooltip() {
        const tooltip = document.getElementById('unified-tooltip');
        if (tooltip) {
            tooltip.remove();
        }
    },

    /**
     * 툴팁 위치 조정 (화면 밖으로 나가지 않도록 개선)
     */
    positionTooltip(tooltip, element) {
        const rect = element.getBoundingClientRect();
        const tooltipRect = tooltip.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        const scrollX = window.scrollX;
        const scrollY = window.scrollY;
        
        console.log('🎯 툴팁 위치 계산:', {
            elementRect: rect,
            tooltipSize: { width: tooltipRect.width, height: tooltipRect.height },
            viewport: { width: viewportWidth, height: viewportHeight }
        });
        
        // 기본 위치: 요소 아래 중앙
        let left = rect.left + scrollX + (rect.width / 2) - (tooltipRect.width / 2);
        let top = rect.bottom + scrollY + 10;
        
        // 좌우 경계 체크 및 조정
        const margin = 20;
        if (left < margin) {
            left = margin;
            console.log('🔧 좌측 경계 조정:', left);
        } else if (left + tooltipRect.width > viewportWidth - margin) {
            left = viewportWidth - tooltipRect.width - margin;
            console.log('🔧 우측 경계 조정:', left);
        }
        
        // 상하 경계 체크 및 조정
        if (top + tooltipRect.height > viewportHeight - margin) {
            // 요소 위쪽에 표시
            top = rect.top + scrollY - tooltipRect.height - 10;
            console.log('🔧 상단으로 이동:', top);
            
            // 위쪽에도 공간이 부족하면 뷰포트 내에 강제로 맞춤
            if (top < margin) {
                top = margin;
                console.log('🔧 상단 경계 조정:', top);
            }
        }
        
        // 최종 위치 설정
        tooltip.style.position = 'fixed';
        tooltip.style.left = `${left - scrollX}px`;
        tooltip.style.top = `${top - scrollY}px`;
        
        console.log('✅ 최종 툴팁 위치:', {
            left: left - scrollX,
            top: top - scrollY
        });
    },

    // ==================== 유틸리티 메서드 ====================
    formatDate(dateString) {
        return new Date(dateString).toLocaleString('ko-KR');
    },

    formatShortDate(dateString) {
        return new Date(dateString).toLocaleDateString('ko-KR');
    },

    getSelectedBookTitle() {
        const selectedBook = this.availableBooks.find(book => book.id === this.linkForm.target_book_id);
        return selectedBook ? selectedBook.title : '서적을 선택하세요';
    },

    // ==================== 모듈 메서드 위임 ====================
    
    // 하이라이트 관련
    selectHighlight(highlightId) {
        return this.highlightManager.selectHighlight(highlightId);
    },

    deleteHighlight(highlightId) {
        return this.highlightManager.deleteHighlight(highlightId);
    },

    deleteHighlightsByColor(color, highlightIds) {
        return this.highlightManager.deleteHighlightsByColor(color, highlightIds);
    },

    deleteAllOverlappingHighlights(highlightIds) {
        return this.highlightManager.deleteAllOverlappingHighlights(highlightIds);
    },

    hideTooltip() {
        return this.highlightManager.hideTooltip();
    },

    showAddNoteForm(highlightId) {
        return this.highlightManager.showAddNoteForm(highlightId);
    },

    deleteNote(noteId) {
        return this.highlightManager.deleteNote(noteId);
    },

    // 링크 관련
    navigateToLinkedDocument(documentId, linkData) {
        return this.linkManager.navigateToLinkedDocument(documentId, linkData);
    },

    navigateToBacklinkDocument(documentId, backlinkData) {
        return this.linkManager.navigateToBacklinkDocument(documentId, backlinkData);
    },

    // HTML에서 사용되는 링크 이동 함수들
    navigateToLink(link) {
        console.log('🔗 링크 클릭:', link);
        console.log('📋 링크 상세 정보:', {
            target_document_id: link.target_document_id,
            target_note_id: link.target_note_id,
            target_content_type: link.target_content_type,
            target_document_title: link.target_document_title,
            target_note_title: link.target_note_title
        });
        
        // target_content_type이 없으면 ID로 추론
        let targetContentType = link.target_content_type;
        if (!targetContentType) {
            if (link.target_note_id) {
                targetContentType = 'note';
            } else if (link.target_document_id) {
                targetContentType = 'document';
            }
            console.log('🔍 target_content_type 추론됨:', targetContentType);
        }
        
        const targetId = link.target_document_id || link.target_note_id;
        if (!targetId) {
            console.error('❌ 대상 문서/노트 ID가 없습니다!', link);
            alert('링크 대상을 찾을 수 없습니다.');
            return;
        }
        
        // 링크 객체에 추론된 타입 추가
        const linkWithType = {
            ...link,
            target_content_type: targetContentType
        };
        
        console.log('🚀 최종 링크 데이터:', linkWithType);
        return this.linkManager.navigateToLinkedDocument(targetId, linkWithType);
    },

    navigateToBacklink(backlink) {
        console.log('🔙 백링크 클릭:', backlink);
        console.log('📋 백링크 상세 정보:', {
            source_document_id: backlink.source_document_id,
            source_note_id: backlink.source_note_id,
            source_content_type: backlink.source_content_type,
            source_document_title: backlink.source_document_title
        });
        
        // 소스 ID 찾기 (노트 백링크의 경우 source_note_id 우선)
        const sourceId = backlink.source_note_id || backlink.source_document_id;
        if (!sourceId) {
            console.error('❌ 소스 문서/노트 ID가 없습니다!', backlink);
            alert('백링크 소스를 찾을 수 없습니다.');
            return;
        }
        
        console.log('✅ 백링크 소스 ID 발견:', sourceId);
        return this.linkManager.navigateToSourceDocument(sourceId, backlink);
    },

    // 링크 삭제 (확인 후)
    async deleteLinkWithConfirm(linkId, targetTitle) {
        console.log('🗑️ 링크 삭제 요청:', { linkId, targetTitle });
        
        const confirmed = confirm(`"${targetTitle}"로의 링크를 삭제하시겠습니까?`);
        if (!confirmed) {
            console.log('❌ 링크 삭제 취소됨');
            return;
        }
        
        try {
            console.log('🗑️ 링크 삭제 시작:', linkId);
            
            // 출발지 타입에 따라 다른 API 사용
            if (this.contentType === 'note') {
                // 노트에서 출발하는 링크: NoteLink API 사용
                console.log('📝 노트 링크 삭제 API 호출');
                await this.api.delete(`/note-links/${linkId}`);
            } else {
                // 문서에서 출발하는 링크: DocumentLink API 사용
                console.log('📄 문서 링크 삭제 API 호출');
                await this.api.deleteDocumentLink(linkId);
            }
            console.log('✅ 링크 삭제 성공');
            
            // 툴팁 숨기기
            this.linkManager.hideTooltip();
            
            // 캐시 무효화
            console.log('🗑️ 링크 캐시 무효화 시작...');
            if (window.cachedApi && window.cachedApi.invalidateRelatedCache) {
                if (this.contentType === 'note') {
                    window.cachedApi.invalidateRelatedCache(`/note-documents/${this.documentId}/links`, ['links']);
                } else {
                    window.cachedApi.invalidateRelatedCache(`/documents/${this.documentId}/links`, ['links']);
                }
                console.log('✅ 링크 캐시 무효화 완료');
            }
            
            // 링크 목록 새로고침
            console.log('🔄 링크 목록 새로고침 시작...');
            await this.linkManager.loadDocumentLinks(this.documentId, this.contentType);
            this.documentLinks = this.linkManager.documentLinks || [];
            console.log('📊 새로고침된 링크 개수:', this.documentLinks.length);

            // 링크 렌더링
            console.log('🎨 링크 렌더링 시작...');
            this.linkManager.renderDocumentLinks();
            console.log('✅ 링크 렌더링 완료');
            
            // 백링크도 다시 로드 (삭제된 링크가 다른 문서의 백링크였을 수 있음)
            console.log('🔄 백링크 새로고침 시작...');
            if (window.cachedApi && window.cachedApi.invalidateRelatedCache) {
                if (this.contentType === 'note') {
                    window.cachedApi.invalidateRelatedCache(`/note-documents/${this.documentId}/backlinks`, ['links']);
                } else {
                    window.cachedApi.invalidateRelatedCache(`/documents/${this.documentId}/backlinks`, ['links']);
                }
                console.log('✅ 백링크 캐시도 무효화 완료');
            }
            await this.linkManager.loadBacklinks(this.documentId, this.contentType);
            this.backlinks = this.linkManager.backlinks || [];
            this.linkManager.renderBacklinks();
            console.log('✅ 백링크 새로고침 완료');
            
            // 성공 메시지
            this.showSuccessMessage('링크가 삭제되었습니다.');
            
        } catch (error) {
            console.error('❌ 링크 삭제 실패:', error);
            alert('링크 삭제에 실패했습니다: ' + error.message);
        }
    },

    // 성공 메시지 표시
    showSuccessMessage(message) {
        const toast = document.createElement('div');
        toast.className = 'fixed top-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg z-50 transition-opacity duration-300';
        toast.textContent = message;
        
        document.body.appendChild(toast);
        
        setTimeout(() => {
            toast.style.opacity = '0';
            setTimeout(() => {
                if (toast.parentNode) {
                    toast.parentNode.removeChild(toast);
                }
            }, 300);
        }, 2000);
    },

    // 하이라이트 관련 추가 기능들
    async changeHighlightColor(highlightId) {
        console.log('🎨 하이라이트 색상 변경:', highlightId);
        
        const colors = [
            { name: '노란색', value: '#FFFF00' },
            { name: '초록색', value: '#00FF00' },
            { name: '파란색', value: '#00BFFF' },
            { name: '분홍색', value: '#FFB6C1' },
            { name: '주황색', value: '#FFA500' },
            { name: '보라색', value: '#DDA0DD' }
        ];
        
        const colorOptions = colors.map(c => `${c.name} (${c.value})`).join('\n');
        const selectedColor = prompt(`새로운 색상을 선택하세요:\n\n${colorOptions}\n\n색상 코드를 입력하세요 (예: #FFFF00):`);
        
        if (selectedColor && selectedColor.match(/^#[0-9A-Fa-f]{6}$/)) {
            try {
                await this.highlightManager.updateHighlightColor(highlightId, selectedColor);
                this.showSuccessMessage('하이라이트 색상이 변경되었습니다.');
            } catch (error) {
                console.error('❌ 색상 변경 실패:', error);
                alert('색상 변경에 실패했습니다: ' + error.message);
            }
        } else if (selectedColor !== null) {
            alert('올바른 색상 코드를 입력해주세요 (예: #FFFF00)');
        }
    },

    async duplicateHighlight(highlightId) {
        console.log('📋 하이라이트 복사:', highlightId);
        
        try {
            await this.highlightManager.duplicateHighlight(highlightId);
            this.showSuccessMessage('하이라이트가 복사되었습니다.');
        } catch (error) {
            console.error('❌ 하이라이트 복사 실패:', error);
            alert('하이라이트 복사에 실패했습니다: ' + error.message);
        }
    },

    async deleteHighlightWithConfirm(highlightId) {
        console.log('🗑️ 하이라이트 삭제 확인:', highlightId);
        
        const confirmed = confirm('이 하이라이트를 삭제하시겠습니까?\n\n⚠️ 주의: 연결된 모든 메모도 함께 삭제됩니다.');
        if (!confirmed) {
            console.log('❌ 하이라이트 삭제 취소됨');
            return;
        }
        
        try {
            await this.highlightManager.deleteHighlight(highlightId);
            this.highlightManager.hideTooltip();
            this.showSuccessMessage('하이라이트가 삭제되었습니다.');
        } catch (error) {
            console.error('❌ 하이라이트 삭제 실패:', error);
            alert('하이라이트 삭제에 실패했습니다: ' + error.message);
        }
    },

    // ==================== PDF 뷰어 관련 ====================
    async loadPdfViewer() {
        console.log('📄 PDF 뷰어 로드 시작');
        this.pdfLoading = true;
        this.pdfError = false;
        this.pdfLoaded = false;
        
        try {
            const token = localStorage.getItem('access_token');
            if (!token || token === 'null' || token === null) {
                throw new Error('인증 토큰이 없습니다. 다시 로그인해주세요.');
            }
            
            // PDF 뷰어 URL 설정 (토큰 포함)
            this.pdfSrc = `/api/documents/${this.documentId}/pdf?_token=${encodeURIComponent(token)}`;
            console.log('✅ PDF 뷰어 준비 완료:', this.pdfSrc);
            
            // PDF.js로 PDF 로드
            await this.loadPdfWithPdfJs();
            
        } catch (error) {
            console.error('❌ PDF 뷰어 로드 실패:', error);
            this.pdfError = true;
        } finally {
            this.pdfLoading = false;
        }
    },

    async loadPdfWithPdfJs() {
        try {
            // PDF.js 라이브러리 확인
            if (typeof pdfjsLib === 'undefined') {
                throw new Error('PDF.js 라이브러리가 로드되지 않았습니다. 페이지를 새로고침해주세요.');
            }

            // 워커 설정 (이미 전역에서 설정되었지만 재확인)
            if (!pdfjsLib.GlobalWorkerOptions.workerSrc) {
                pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
            }
            
            console.log('📄 PDF.js로 PDF 로드 시작:', this.pdfSrc);
            
            // 토큰 포함된 PDF 로드 설정
            const loadingTask = pdfjsLib.getDocument({
                url: this.pdfSrc,
                httpHeaders: {
                    'Authorization': `Bearer ${localStorage.getItem('access_token')}`
                },
                withCredentials: false
            });
            
            // 로딩 진행률 표시
            loadingTask.onProgress = (progress) => {
                if (progress.total > 0) {
                    const percent = Math.round((progress.loaded / progress.total) * 100);
                    console.log(`📄 PDF 로딩 진행률: ${percent}%`);
                }
            };
            
            this.pdfDocument = await loadingTask.promise;
            
            this.totalPages = this.pdfDocument.numPages;
            this.currentPage = 1;
            
            console.log(`✅ PDF 로드 완료: ${this.totalPages} 페이지`);
            
            // 캔버스 초기화
            this.initPdfCanvas();
            
            // 첫 페이지 렌더링
            await this.renderPdfPage(1);
            
            this.pdfLoaded = true;
            
        } catch (error) {
            console.error('❌ PDF.js 로드 실패:', error);
            
            // 구체적인 에러 메시지 제공
            if (error.name === 'InvalidPDFException') {
                throw new Error('유효하지 않은 PDF 파일입니다.');
            } else if (error.name === 'MissingPDFException') {
                throw new Error('PDF 파일을 찾을 수 없습니다.');
            } else if (error.name === 'UnexpectedResponseException') {
                throw new Error('PDF 파일을 다운로드할 수 없습니다. 권한을 확인해주세요.');
            } else {
                throw new Error(`PDF 로드 실패: ${error.message}`);
            }
        }
    },

    initPdfCanvas() {
        this.pdfCanvas = document.getElementById('pdf-canvas');
        if (this.pdfCanvas) {
            this.pdfContext = this.pdfCanvas.getContext('2d');
        }
    },

    async renderPdfPage(pageNum) {
        if (!this.pdfDocument || !this.pdfCanvas) return;
        
        try {
            console.log(`📄 페이지 ${pageNum} 렌더링 시작`);
            
            const page = await this.pdfDocument.getPage(pageNum);
            const viewport = page.getViewport({ scale: this.pdfScale });
            
            // 캔버스 크기 설정
            this.pdfCanvas.height = viewport.height;
            this.pdfCanvas.width = viewport.width;
            
            // 페이지 렌더링
            const renderContext = {
                canvasContext: this.pdfContext,
                viewport: viewport
            };
            
            await page.render(renderContext).promise;
            
            // 텍스트 내용 추출 (검색용)
            const textContent = await page.getTextContent();
            this.pdfTextContent[pageNum] = textContent.items.map(item => item.str).join(' ');
            
            console.log(`✅ 페이지 ${pageNum} 렌더링 완료`);
            
        } catch (error) {
            console.error(`❌ 페이지 ${pageNum} 렌더링 실패:`, error);
        }
    },

    handlePdfError() {
        console.error('❌ PDF iframe 로드 오류');
        this.pdfError = true;
        this.pdfLoading = false;
    },

    async retryPdfLoad() {
        console.log('🔄 PDF 재로드 시도');
        await this.loadPdfViewer();
    },

    // ==================== PDF 네비게이션 ====================
    async previousPage() {
        if (this.currentPage > 1) {
            this.currentPage--;
            await this.renderPdfPage(this.currentPage);
        }
    },

    async nextPage() {
        if (this.currentPage < this.totalPages) {
            this.currentPage++;
            await this.renderPdfPage(this.currentPage);
        }
    },

    async goToPage(pageNum) {
        const page = parseInt(pageNum);
        if (page >= 1 && page <= this.totalPages) {
            this.currentPage = page;
            await this.renderPdfPage(this.currentPage);
        }
    },

    zoomIn() {
        this.pdfScale = Math.min(this.pdfScale * 1.2, 3.0);
        this.renderPdfPage(this.currentPage);
    },

    zoomOut() {
        this.pdfScale = Math.max(this.pdfScale / 1.2, 0.5);
        this.renderPdfPage(this.currentPage);
    },

    // ==================== PDF 검색 관련 ====================
    openPdfSearchModal() {
        this.showPdfSearchModal = true;
        this.pdfSearchQuery = '';
        this.pdfSearchResults = [];
        
        // 모달이 열린 후 입력 필드에 포커스
        setTimeout(() => {
            const searchInput = document.querySelector('input[x-ref="searchInput"]');
            if (searchInput) {
                searchInput.focus();
                searchInput.select();
            }
        }, 100);
    },

    async searchInPdf() {
        if (!this.pdfSearchQuery.trim()) {
            alert('검색어를 입력해주세요.');
            return;
        }

        console.log('🔍 PDF 검색 시작:', this.pdfSearchQuery);
        this.pdfSearchLoading = true;
        this.pdfSearchResults = [];

        try {
            // 백엔드 API를 통해 PDF 내용 검색
            const searchResults = await this.api.get(
                `/documents/${this.documentId}/search-in-content?q=${encodeURIComponent(this.pdfSearchQuery)}`
            );

            console.log('✅ PDF 검색 결과:', searchResults);

            if (searchResults.matches && searchResults.matches.length > 0) {
                this.pdfSearchResults = searchResults.matches.map(match => ({
                    page: match.page || 1,
                    context: match.context || match.text || this.pdfSearchQuery,
                    position: match.position || 0
                }));
                
                console.log(`📄 ${this.pdfSearchResults.length}개의 검색 결과 발견`);
                
                if (this.pdfSearchResults.length === 0) {
                    alert('검색 결과를 찾을 수 없습니다.');
                }
            } else {
                alert('검색 결과를 찾을 수 없습니다.');
            }

        } catch (error) {
            console.error('❌ PDF 검색 실패:', error);
            alert('PDF 검색 중 오류가 발생했습니다: ' + error.message);
        } finally {
            this.pdfSearchLoading = false;
        }
    },

    jumpToPdfResult(result) {
        console.log('📍 PDF 결과로 이동:', result);
        
        // PDF URL에 페이지 번호 추가하여 해당 페이지로 이동
        const token = localStorage.getItem('access_token');
        let newPdfSrc = `/api/documents/${this.documentId}/pdf?_token=${encodeURIComponent(token)}`;
        
        // 페이지 번호가 있으면 URL 프래그먼트로 추가
        if (result.page && result.page > 1) {
            newPdfSrc += `#page=${result.page}`;
        }
        
        // PDF src 업데이트하여 해당 페이지로 이동
        this.pdfSrc = newPdfSrc;
        
        console.log(`📄 페이지 ${result.page}로 이동:`, newPdfSrc);
        
        // 잠시 후 검색 기능 활성화
        setTimeout(() => {
            const iframe = document.querySelector('#pdf-viewer-iframe');
            if (iframe && iframe.contentWindow) {
                try {
                    iframe.contentWindow.focus();
                    
                    // 브라우저 내장 검색 기능 활용
                    if (iframe.contentWindow.find) {
                        iframe.contentWindow.find(this.pdfSearchQuery);
                    } else {
                        // 대안: 사용자에게 수동 검색 안내
                        this.showSuccessMessage(`페이지 ${result.page}로 이동했습니다. Ctrl+F를 눌러 "${this.pdfSearchQuery}"를 검색하세요.`);
                    }
                } catch (e) {
                    console.warn('PDF iframe 접근 제한:', e);
                    this.showSuccessMessage(`페이지 ${result.page}로 이동했습니다. Ctrl+F를 눌러 "${this.pdfSearchQuery}"를 검색하세요.`);
                }
            }
        }, 1000);
        
        // 모달 닫기
        this.showPdfSearchModal = false;
    },

    async editNote(noteId, currentContent) {
        console.log('✏️ 메모 편집:', noteId);
        console.log('🔍 HighlightManager 상태:', this.highlightManager);
        console.log('🔍 updateNote 함수 존재:', typeof this.highlightManager?.updateNote);
        
        if (!this.highlightManager) {
            console.error('❌ HighlightManager가 초기화되지 않음');
            alert('하이라이트 매니저가 초기화되지 않았습니다.');
            return;
        }
        
        if (typeof this.highlightManager.updateNote !== 'function') {
            console.error('❌ updateNote 함수가 존재하지 않음');
            alert('메모 업데이트 함수가 존재하지 않습니다.');
            return;
        }
        
        const newContent = prompt('메모 내용을 수정하세요:', currentContent);
        if (newContent !== null && newContent.trim() !== currentContent) {
            try {
                await this.highlightManager.updateNote(noteId, newContent.trim());
                this.showSuccessMessage('메모가 수정되었습니다.');
            } catch (error) {
                console.error('❌ 메모 수정 실패:', error);
                alert('메모 수정에 실패했습니다: ' + error.message);
            }
        }
    },

    // 백링크 삭제 (확인 후)
    async deleteBacklinkWithConfirm(backlinkId, sourceTitle) {
        console.log('🗑️ 백링크 삭제 요청:', { backlinkId, sourceTitle });
        
        const confirmed = confirm(`"${sourceTitle}"에서 오는 백링크를 삭제하시겠습니까?\n\n⚠️ 주의: 이는 원본 문서의 링크를 삭제합니다.`);
        if (!confirmed) {
            console.log('❌ 백링크 삭제 취소됨');
            return;
        }
        
        try {
            console.log('🗑️ 백링크 삭제 시작:', backlinkId);
            
            // 백링크 삭제는 실제로는 원본 링크를 삭제하는 것
            await this.api.deleteDocumentLink(backlinkId);
            console.log('✅ 백링크 삭제 성공');
            
            // 툴팁 숨기기
            this.linkManager.hideTooltip();
            
            // 캐시 무효화 (현재 문서의 백링크 캐시)
            console.log('🗑️ 백링크 캐시 무효화 시작...');
            if (window.cachedApi && window.cachedApi.invalidateRelatedCache) {
                if (this.contentType === 'note') {
                    window.cachedApi.invalidateRelatedCache(`/note-documents/${this.documentId}/backlinks`, ['links']);
                } else {
                    window.cachedApi.invalidateRelatedCache(`/documents/${this.documentId}/backlinks`, ['links']);
                }
                console.log('✅ 백링크 캐시 무효화 완료');
            }
            
            // 백링크 목록 새로고침
            console.log('🔄 백링크 목록 새로고침 시작...');
            await this.linkManager.loadBacklinks(this.documentId, this.contentType);
            this.backlinks = this.linkManager.backlinks || [];
            console.log('📊 새로고침된 백링크 개수:', this.backlinks.length);

            // 백링크 렌더링
            console.log('🎨 백링크 렌더링 시작...');
            this.linkManager.renderBacklinks();
            console.log('✅ 백링크 렌더링 완료');
            
            // 성공 메시지
            this.showSuccessMessage('백링크가 삭제되었습니다.');
            
        } catch (error) {
            console.error('❌ 백링크 삭제 실패:', error);
            alert('백링크 삭제에 실패했습니다: ' + error.message);
        }
    },

    // 북마크 관련
    scrollToBookmark(bookmark) {
        return this.bookmarkManager.scrollToBookmark(bookmark);
    },

    deleteBookmark(bookmarkId) {
        return this.bookmarkManager.deleteBookmark(bookmarkId);
    },

    // ==================== 링크 생성 ====================
    async createDocumentLink() {
        console.log('🔗 createDocumentLink 함수 실행');
        console.log('📋 현재 linkForm 상태:', JSON.stringify(this.linkForm, null, 2));
        
        try {
            // 링크 데이터 검증
            if (!this.linkForm.target_document_id) {
                alert('대상 문서를 선택해주세요.');
                return;
            }

            if (this.linkForm.link_type === 'text' && !this.linkForm.target_text) {
                alert('대상 문서에서 텍스트를 선택해주세요. "대상 문서에서 텍스트 선택" 버튼을 클릭하여 연결할 텍스트를 드래그해주세요.');
                return;
            }

            // API 호출용 데이터 준비 (백엔드 필드명에 맞춤)
            const linkData = {
                target_document_id: this.linkForm.target_document_id,
                selected_text: this.linkForm.selected_text,  // 백엔드: selected_text
                start_offset: this.linkForm.start_offset,    // 백엔드: start_offset
                end_offset: this.linkForm.end_offset,        // 백엔드: end_offset
                link_text: this.linkForm.link_text || this.linkForm.selected_text,
                description: this.linkForm.description,
                link_type: this.linkForm.link_type,
                target_text: this.linkForm.target_text || null,
                target_start_offset: this.linkForm.target_start_offset || null,
                target_end_offset: this.linkForm.target_end_offset || null
            };

            console.log('📤 링크 생성 데이터:', linkData);
            console.log('📤 링크 생성 데이터 (JSON):', JSON.stringify(linkData, null, 2));
            
            // 필수 필드 검증
            const requiredFields = ['target_document_id', 'selected_text', 'start_offset', 'end_offset'];
            const missingFields = requiredFields.filter(field => 
                linkData[field] === undefined || linkData[field] === null || linkData[field] === ''
            );
            
            if (missingFields.length > 0) {
                console.error('❌ 필수 필드 누락:', missingFields);
                alert('필수 필드가 누락되었습니다: ' + missingFields.join(', '));
                return;
            }
            
            console.log('✅ 모든 필수 필드 확인됨');

            // API 호출 (출발지와 대상에 따라 다른 API 사용)
            if (this.contentType === 'note') {
                // 노트에서 출발하는 링크
                if (this.linkForm.target_type === 'note') {
                    // 노트 → 노트: 노트 링크 API 사용
                    linkData.target_note_id = linkData.target_document_id;
                    delete linkData.target_document_id;
                    await this.api.post(`/note-documents/${this.documentId}/links`, linkData);
                } else {
                    // 노트 → 문서: 노트 링크 API 사용 (target_document_id 유지)
                    await this.api.post(`/note-documents/${this.documentId}/links`, linkData);
                }
            } else {
                // 문서에서 출발하는 링크
                if (this.linkForm.target_type === 'note') {
                    // 문서 → 노트: 문서 링크 API에 노트 대상 지원 필요 (향후 구현)
                    // 현재는 기존 API 사용
                    await this.api.createDocumentLink(this.documentId, linkData);
                } else {
                    // 문서 → 문서: 기존 문서 링크 API 사용
                    await this.api.createDocumentLink(this.documentId, linkData);
                }
            }
            console.log('✅ 링크 생성됨');

            // 성공 알림
            alert('링크가 성공적으로 생성되었습니다!');

            // 모달 닫기
            this.showLinkModal = false;

            // 캐시 무효화 (새 링크가 반영되도록)
            console.log('🗑️ 링크 캐시 무효화 시작...');
            if (window.cachedApi && window.cachedApi.invalidateRelatedCache) {
                if (this.contentType === 'note') {
                    window.cachedApi.invalidateRelatedCache(`/note-documents/${this.documentId}/links`, ['links']);
                } else {
                    window.cachedApi.invalidateRelatedCache(`/documents/${this.documentId}/links`, ['links']);
                }
                console.log('✅ 링크 캐시 무효화 완료');
            }
            
            // 링크 목록 새로고침
            console.log('🔄 링크 목록 새로고침 시작...');
            await this.linkManager.loadDocumentLinks(this.documentId, this.contentType);
            this.documentLinks = this.linkManager.documentLinks || [];
            console.log('📊 로드된 링크 개수:', this.documentLinks.length);
            console.log('📊 링크 데이터:', this.documentLinks);

            // 링크 렌더링
            console.log('🎨 링크 렌더링 시작...');
            this.linkManager.renderDocumentLinks();
            console.log('✅ 링크 렌더링 완료');
            
            // 백링크도 다시 로드하고 렌더링 (새 링크가 다른 문서의 백링크가 될 수 있음)
            console.log('🔄 백링크 새로고침 시작...');
            // 백링크 캐시도 무효화
            if (window.cachedApi && window.cachedApi.invalidateRelatedCache) {
                if (this.contentType === 'note') {
                    window.cachedApi.invalidateRelatedCache(`/note-documents/${this.documentId}/backlinks`, ['links']);
                } else {
                    window.cachedApi.invalidateRelatedCache(`/documents/${this.documentId}/backlinks`, ['links']);
                }
                console.log('✅ 백링크 캐시도 무효화 완료');
            }
            await this.linkManager.loadBacklinks(this.documentId, this.contentType);
            this.backlinks = this.linkManager.backlinks || [];
            this.linkManager.renderBacklinks();
            console.log('✅ 백링크 새로고침 완료');
            
        } catch (error) {
            console.error('링크 생성 실패:', error);
            console.error('에러 상세:', {
                message: error.message,
                stack: error.stack,
                response: error.response
            });
            
            // 422 에러인 경우 상세 정보 표시
            if (error.response && error.response.status === 422) {
                console.error('422 Validation Error Details:', error.response.data);
                alert('데이터 검증 실패: ' + JSON.stringify(error.response.data, null, 2));
            } else {
                alert('링크 생성에 실패했습니다: ' + error.message);
            }
        }
    },

    // 네비게이션 함수들
    goBack() {
        console.log('🔙 뒤로가기');
        window.history.back();
    },

    navigateToDocument(documentId) {
        if (!documentId) {
            console.warn('⚠️ 문서 ID가 없습니다');
            return;
        }
        console.log('📄 문서로 이동:', documentId);
        window.location.href = `/viewer.html?id=${documentId}`;
    },

    goToBookContents() {
        if (!this.navigation?.book_info?.id) {
            console.warn('⚠️ 서적 정보가 없습니다');
            return;
        }
        console.log('📚 서적 목차로 이동:', this.navigation.book_info.id);
        window.location.href = `/book-documents.html?book_id=${this.navigation.book_info.id}`;
    }
});

// Alpine.js 컴포넌트 등록
document.addEventListener('alpine:init', () => {
    console.log('🔧 Alpine.js 컴포넌트 로드됨');
    
    // 전역 함수들 (말풍선에서 사용)
    window.cancelTextSelection = () => {
        if (window.documentViewerInstance && window.documentViewerInstance.linkManager) {
            window.documentViewerInstance.linkManager.cancelTextSelection();
        }
    };
    
    window.confirmTextSelection = (selectedText, startOffset, endOffset) => {
        if (window.documentViewerInstance && window.documentViewerInstance.linkManager) {
            window.documentViewerInstance.linkManager.confirmTextSelection(selectedText, startOffset, endOffset);
        }
    };
});

// Alpine.js Store 등록
document.addEventListener('alpine:init', () => {
    Alpine.store('documentViewer', {
        instance: null,
        
        init() {
            // DocumentViewer 인스턴스가 생성되면 저장
            setTimeout(() => {
                this.instance = window.documentViewerInstance;
            }, 500);
        },
        
        downloadOriginalFile() {
            console.log('🏪 Store downloadOriginalFile 호출');
            if (this.instance) {
                return this.instance.downloadOriginalFile();
            } else {
                console.warn('DocumentViewer 인스턴스가 없습니다');
            }
        },
        
        toggleLanguage() {
            console.log('🏪 Store toggleLanguage 호출');
            if (this.instance) {
                return this.instance.toggleLanguage();
            } else {
                console.warn('DocumentViewer 인스턴스가 없습니다');
            }
        },
        
        loadBacklinks() {
            console.log('🏪 Store loadBacklinks 호출');
            if (this.instance) {
                return this.instance.loadBacklinks();
            } else {
                console.warn('DocumentViewer 인스턴스가 없습니다');
            }
        }
    });
});
