(function () {
    'use strict';

    if (window.HerSTTEngine) {
        return;
    }

    const DEBUG_MODE = false; // 개발 시에만 true

    // 모든 console.log를 제거합니다. 오류/예외 상황(console.error 등)은 남깁니다.

    class HerSTTEngine {
        static instance = null;

        static getInstance() {
            if (!HerSTTEngine.instance) {
                HerSTTEngine.instance = new HerSTTEngine();
            }
            return HerSTTEngine.instance;
        }

        constructor() {
            if (HerSTTEngine.instance) {
                return HerSTTEngine.instance;
            }

            this.recognition = null;
            this.isRunning = false;
            this.language = 'ko-KR';
            this.callbacks = {
                onUpdate: null,
                onStateChange: null
            };
            this.isCallbackBound = false;
            this.onUpdate = null;
            this.onStateChange = null;
            this._sessionId = null;

            // 단순한 누적 방식
            this.finalTranscript = "";

            // 🚨 에러 재시도 제한
            this.retryCount = 0;
            this.maxRetries = 3;

            // 🚨 세션 종료 타입 추가
            this.sessionEndType = null; // 'explicit' | 'error' | 'auto'

            // 🎯 자동 종료 감지 관련
            this.sessionStartTime = null;
            this.maxSessionDuration = 5 * 60 * 1000; // 5분 (STT 스펙 한계)
            this.autoStopTimer = null;

            HerSTTEngine.instance = this;
        }

        init() {
            // debugLog('[Her] HerSTTEngine 초기화 완료');
        }

        setLanguage(lang) {
            this.language = lang;
            if (this.recognition) {
                this.recognition.lang = lang;
            }
            // debugLog('[STT] 언어 설정:', lang);
        }

        setCallbacks(onUpdate, onStateChange) {
            // 기존 콜백 정리
            this.clearCallbacks();

            this.callbacks.onUpdate = onUpdate;
            this.callbacks.onStateChange = onStateChange;
            this.isCallbackBound = true;

            /* console.log('[STT] 콜백 설정 완료:', {
                hasOnUpdate: !!onUpdate,
                hasOnStateChange: !!onStateChange,
                isCallbackBound: this.isCallbackBound
            }); */
        }

        clearCallbacks() {
            this.callbacks.onUpdate = null;
            this.callbacks.onStateChange = null;
            this.isCallbackBound = false;

            // 기존 방식의 콜백도 정리
            this.onUpdate = null;
            this.onStateChange = null;
        }

        async start(sessionId, context = 'content', options = {}) {
            // console.log(`[STT] 🚀 녹음 시작 시도: ${sessionId}, ${context}`);

            // 🎯 단순하고 강력한 사전 차단
            if (!window.HerGlobalState.tryStartRecording(sessionId, context)) {
                const currentState = window.HerGlobalState.getState();
                // console.log(`[STT] ❌ 녹음 차단됨 - 현재 녹음 중:`, currentState);

                // 예외 던지기 (명확한 실패)
                const error = new Error('다른 곳에서 이미 녹음 중입니다.');
                error.type = 'concurrent_recording';
                error.currentContext = currentState.currentContext;
                throw error;
            }

            // 기존 녹음 완전 정리 (안전 장치)
            if (this.isRunning) {
                // console.log(`[STT] 🔄 기존 세션 강제 중지`);
                await this.forceStop();
                // 정리 완료 대기
                await new Promise(resolve => setTimeout(resolve, 100));
            }
            
            // 🎯 완전한 상태 초기화 (두 번째 레코딩 문제 해결)
            // 주의: clearCallbacks() 호출하면 안됨 - 이미 setCallbacks()로 설정된 콜백이 삭제됨
            this.recognition = null;

            // 🎯 세션 ID 설정
            this._sessionId = sessionId;

            // 🚨 텍스트 초기화 로직 개선
            const shouldPreserveText = options.preserveText ||
                (this.sessionEndType === 'error' && this.finalTranscript.trim());

            if (shouldPreserveText) {
                // console.log('[STT] 📄 텍스트 보존 모드:', this.finalTranscript.length, '글자');
            } else {
                // console.log('[STT] 🆕 새 세션 시작 - 텍스트 초기화');
                this.finalTranscript = "";
            }

            this.lastProcessedIndex = 0;
            this.retryCount = 0; // 재시도 횟수 초기화
            this.sessionEndType = null; // 세션 종료 타입 초기화

            // 🎯 창 포커스 유지 강화 - Visibility API 사용
            this.setupVisibilityHandling();

            try {
                // 🎯 환경 체크 및 권한 확인
                await this.checkEnvironmentAndPermissions();

                if (!window.SpeechRecognition && !window.webkitSpeechRecognition) {
                    throw new Error('Speech recognition not supported');
                }

                this.recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
                this.recognition.lang = this.language;
                this.recognition.interimResults = true;
                this.recognition.continuous = true;
                this.recognition.maxAlternatives = 1;  // 안정성 개선
                this.recognition.serviceURI = null;    // 기본 서비스 사용

                // 이벤트 리스너 설정
                this.setupRecognitionEvents();

                // console.log(`[STT] 🎤 실제 recognition.start() 호출`);
                this.recognition.start();
                this.isRunning = true;
                
                // 🎯 자동 종료 타이머 설정
                this.sessionStartTime = Date.now();
                this.setupAutoStopTimer();
                
                // console.log(`[STT] ✅ 녹음 시작 성공`);

                // 🎯 창 포커스 유지 강화 - Visibility API 사용
                this.setupVisibilityHandling();

            } catch (error) {
                console.error('[STT] ❌ 시작 실패:', error);
                this.isRunning = false;
                // 🚨 실패 시 전역 상태 초기화
                // console.log(`[STT] 🔄 실패로 인한 전역 상태 초기화`);
                window.HerGlobalState.reset();
                throw error;
            }
        }

        // 🎯 환경 체크 및 권한 확인 메서드 추가
        async checkEnvironmentAndPermissions() {
            // HTTPS 체크 (확장 프로그램 환경 고려)
            const isSecureContext = location.protocol === 'https:' || 
                                   location.protocol === 'chrome-extension:' ||
                                   location.hostname === 'localhost' || 
                                   location.hostname === '127.0.0.1';
            
            if (!isSecureContext) {
                const error = new Error('Speech Recognition requires HTTPS or localhost');
                error.type = 'https_required';
                throw error;
            }

            // 마이크 권한 확인
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                stream.getTracks().forEach(track => track.stop()); // 권한 확인 후 즉시 해제
                // console.log('[STT] ✅ 마이크 권한 확인 완료');
            } catch (permissionError) {
                console.error('[STT] ❌ 마이크 권한 없음:', permissionError);
                const error = new Error('Microphone permission denied');
                error.type = 'microphone_permission_denied';
                error.originalError = permissionError;
                throw error;
            }

            // Speech Recognition API 지원 확인
            if (!window.SpeechRecognition && !window.webkitSpeechRecognition) {
                const error = new Error('Speech Recognition API not supported');
                error.type = 'api_not_supported';
                throw error;
            }

            // console.log('[STT] ✅ 환경 및 권한 체크 완료');
        }

        // 🎯 자동 종료 타이머 설정
        setupAutoStopTimer() {
            // 기존 타이머 정리
            if (this.autoStopTimer) {
                clearTimeout(this.autoStopTimer);
            }

            // 새로운 타이머 설정
            this.autoStopTimer = setTimeout(() => {
                if (this.isRunning) {
                    // console.log('[STT] ⏰ 자동 종료 타이머 실행 - STT 스펙 한계 도달');
                    this.handleAutoStop();
                }
            }, this.maxSessionDuration);

            // console.log(`[STT] ⏰ 자동 종료 타이머 설정 완료 (${this.maxSessionDuration / 1000}초)`);
        }

        // 🎯 자동 종료 처리
        async handleAutoStop() {
            // console.log('[STT] 🛑 자동 종료 처리 시작');

            // 현재까지의 텍스트 보존
            const preservedText = this.finalTranscript.trim();
            
            // 자동 종료로 처리
            await this.stop('auto_stop', this._sessionId);

            // 자동 종료 콜백 호출
            const autoStopData = {
                sessionId: this._sessionId,
                finalText: preservedText,
                endType: 'auto_stop',
                reason: 'STT 스펙 한계로 인한 자동 종료',
                duration: this.sessionStartTime ? Date.now() - this.sessionStartTime : 0
            };

            if (this.callbacks.onStateChange) {
                this.callbacks.onStateChange('auto_stop', autoStopData);
            } else if (this.onStateChange) {
                this.onStateChange('auto_stop', autoStopData);
            }

            // console.log('[STT] ✅ 자동 종료 처리 완료');
        }

        async stop(endType = 'explicit', sessionId = null) {
            // console.log(`[STT] stop() 호출 - endType: ${endType}`);

            this.isRunning = false;
            this.sessionEndType = endType;

            // 🚨 핫픽스: stop 호출 시 즉시 상태 콜백 전달
            const stateData = {
                sessionId: this._sessionId,
                finalText: this.finalTranscript.trim(),
                endType: endType
            };

            // console.log(`[STT] 🔥 핫픽스 - stop 콜백 강제 호출:`, stateData);

            // 새로운 방식과 기존 방식 모두 지원
            if (this.callbacks.onStateChange) {
                this.callbacks.onStateChange('stop', stateData);
            } else if (this.onStateChange) {
                this.onStateChange('stop', stateData);
            }

            if (this.recognition) {
                try {
                    this.recognition.stop();
                    this.recognition = null;
                } catch (error) {
                    console.error('[STT] 중지 에러:', error);
                }
            }

            // 🎯 자동 종료 타이머 정리
            if (this.autoStopTimer) {
                clearTimeout(this.autoStopTimer);
                this.autoStopTimer = null;
            }

            this._sessionId = null;
            this.clearCallbacks();
            window.HerGlobalState.reset();

            // console.log(`[STT] 중지 완료 - 종료 타입: ${endType}`);
        }

        // 강제 정지 메서드 추가
        async forceStop() {
            // console.log(`[STT] 🛑 강제 중단 시작`);

            this.isRunning = false;
            if (this.recognition) {
                try {
                    this.recognition.abort(); // stop 대신 abort
                    this.recognition = null;
                } catch (error) {
                    console.error('[STT] 강제 중단 에러:', error);
                }
            }

            // 전역 상태도 정리
            window.HerGlobalState.reset();

            // console.log(`[STT] ✅ 강제 중단 완료`);
        }

        getCurrentTabId() {
            // 현재 탭 ID를 가져오는 헬퍼 메서드
            try {
                return chrome.tabs ? chrome.tabs.TAB_ID_NONE : null;
            } catch (e) {
                return null;
            }
        }



        setupRecognitionEvents() {
            if (!this.recognition) return;

            this.recognition.onstart = () => {
                this.isRunning = true;
                if (this.onStateChange) {
                    this.onStateChange('start', { sessionId: this._sessionId });
                }
            };

            // 텍스트 보정 최소화 - 안정성 우선
            this.recognition.onresult = (event) => {
                let interimTranscript = "";

                // 새로 추가된 결과만 처리 (인덱스 기반)
                for (let i = this.lastProcessedIndex || 0; i < event.results.length; i++) {
                    const result = event.results[i];
                    const transcript = result[0].transcript;

                    if (result.isFinal) {
                        // Final 결과의 신뢰도 체크
                        const confidence = result[0].confidence || 1;

                        // 🎯 신뢰도가 너무 낮으면 경고 로그만 출력
                        if (confidence < 0.3) {
                            console.warn(`[STT] 낮은 신뢰도 (${(confidence * 100).toFixed(1)}%):`, transcript);
                        }

                        // 신뢰도와 관계없이 사용자가 말한 것은 모두 보존
                        this.finalTranscript += transcript;
                        this.lastProcessedIndex = i + 1;

                        // 디버그 로그
                        // console.log(`[STT] Final 텍스트 추가 (신뢰도: ${(confidence * 100).toFixed(1)}%):`, transcript);
                    } else {
                        interimTranscript += transcript;
                    }
                }

                // 콜백 호출 부분만 수정:
                const updateData = {
                    sessionId: this._sessionId,
                    finalText: this.finalTranscript,
                    interimText: interimTranscript,
                    text: this.finalTranscript + interimTranscript
                };

                // 새로운 방식과 기존 방식 모두 지원
                if (this.callbacks.onUpdate) {
                    this.callbacks.onUpdate(updateData);
                } else if (this.onUpdate) {
                    this.onUpdate(updateData);
                }
            };

            this.recognition.onend = () => {
                /* console.log(`[STT] onend 이벤트 발생:`, {
                    isRunning: this.isRunning,
                    sessionId: this._sessionId,
                    finalTranscript: this.finalTranscript
                }); */

                if (this.isRunning && this._sessionId) {
                    // console.log(`[STT] 🔄 재시작 모드 - 텍스트 백업 후 재시작`);
                    // 텍스트 백업 후 재시작
                    const backupText = this.finalTranscript;
                    setTimeout(() => {
                        if (this.isRunning) {
                            try {
                                // 새 recognition 객체 생성
                                this.recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
                                this.recognition.lang = this.language;
                                this.recognition.interimResults = true;
                                this.recognition.continuous = true;
                                this.recognition.maxAlternatives = 1;  // 안정성 개선
                                this.recognition.serviceURI = null;    // 기본 서비스 사용

                                // 백업된 텍스트 복원
                                this.finalTranscript = backupText;
                                // 인덱스 초기화
                                this.lastProcessedIndex = 0;

                                // 이벤트 리스너 재설정
                                this.setupRecognitionEvents();

                                this.recognition.start();
                                // console.log(`[STT] ✅ 재시작 완료`);
                            } catch (error) {
                                console.error('[STT] 재시작 실패:', error);
                            }
                        }
                    }, 100);
                } else {
                    // console.log(`[STT] 🛑 완전 종료 모드 - stop 콜백 호출`);
                    this.isRunning = false;
                    const stateData = {
                        sessionId: this._sessionId,
                        finalText: this.finalTranscript.trim(),
                        endType: this.sessionEndType || 'auto'
                    };

                    // console.log(`[STT] onend - stop 콜백 호출:`, stateData);

                    // 새로운 방식과 기존 방식 모두 지원
                    if (this.callbacks.onStateChange) {
                        this.callbacks.onStateChange('stop', stateData);
                    } else if (this.onStateChange) {
                        this.onStateChange('stop', stateData);
                    }
                }
            };

            this.recognition.onerror = (event) => {
                /* console.log(`[STT] 🚨 에러 발생:`, {
                    error: event.error,
                    currentSessionId: this._sessionId,
                    isRunning: this.isRunning
                }); */

                // 🎯 aborted 에러는 동시 녹음 차단으로 인한 것 - 무시
                if (event.error === 'aborted') {
                    // console.log(`[STT] 🚫 aborted 에러 - 동시 녹음 차단으로 인한 정상적인 중단`);
                    this.isRunning = false;
                    window.HerGlobalState.reset();
                    return;
                }

                // 🎯 no-speech는 자연스러운 종료
                if (event.error === 'no-speech') {
                    // console.log(`[STT] 🤫 no-speech 에러 - 정상 종료로 처리`);
                    this.isRunning = false;

                    const stateData = {
                        sessionId: this._sessionId,
                        finalText: this.finalTranscript.trim(),
                        endType: 'no-speech'
                    };

                    if (this.callbacks.onStateChange) {
                        this.callbacks.onStateChange('stop', stateData);
                    } else if (this.onStateChange) {
                        this.onStateChange('stop', stateData);
                    }
                    return;
                }

                // 🎯 network 에러 처리 개선
                if (event.error === 'network') {
                    console.error('[STT] ❌ 네트워크 에러 발생');
                    
                    // 재시도 로직
                    if (this.retryCount < this.maxRetries) {
                        this.retryCount++;
                        // console.log(`[STT] 🔄 네트워크 에러 재시도 ${this.retryCount}/${this.maxRetries}`);
                        
                        setTimeout(() => {
                            if (this.isRunning) {
                                this.restartRecognition();
                            }
                        }, 1000 * this.retryCount); // 지수 백오프
                        return;
                    } else {
                        console.error('[STT] ❌ 최대 재시도 횟수 초과');
                        const errorData = {
                            sessionId: this._sessionId,
                            error: { 
                                type: 'network',
                                message: '네트워크 연결 문제로 녹음을 시작할 수 없습니다. 인터넷 연결을 확인해주세요.',
                                maxRetriesExceeded: true
                            },
                            preservedText: this.finalTranscript || '',
                            endType: 'error'
                        };

                        this.isRunning = false;
                        window.HerGlobalState.reset();

                        if (this.callbacks.onStateChange) {
                            this.callbacks.onStateChange('error', errorData);
                        } else if (this.onStateChange) {
                            this.onStateChange('error', errorData);
                        }
                        return;
                    }
                }

                // 🎯 not-allowed 에러 (마이크 권한)
                if (event.error === 'not-allowed') {
                    console.error('[STT] ❌ 마이크 권한 거부');
                    const errorData = {
                        sessionId: this._sessionId,
                        error: { 
                            type: 'not-allowed',
                            message: '마이크 권한이 거부되었습니다. 브라우저 설정에서 마이크 권한을 허용해주세요.'
                        },
                        preservedText: this.finalTranscript || '',
                        endType: 'error'
                    };

                    this.isRunning = false;
                    window.HerGlobalState.reset();

                    if (this.callbacks.onStateChange) {
                        this.callbacks.onStateChange('error', errorData);
                    } else if (this.onStateChange) {
                        this.onStateChange('error', errorData);
                    }
                    return;
                }

                // 🎯 audio-capture 에러 (마이크 접근 실패)
                if (event.error === 'audio-capture') {
                    console.error('[STT] ❌ 마이크 접근 실패');
                    const errorData = {
                        sessionId: this._sessionId,
                        error: { 
                            type: 'audio-capture',
                            message: '마이크에 접근할 수 없습니다. 다른 앱에서 마이크를 사용 중인지 확인해주세요.'
                        },
                        preservedText: this.finalTranscript || '',
                        endType: 'error'
                    };

                    this.isRunning = false;
                    window.HerGlobalState.reset();

                    if (this.callbacks.onStateChange) {
                        this.callbacks.onStateChange('error', errorData);
                    } else if (this.onStateChange) {
                        this.onStateChange('error', errorData);
                    }
                    return;
                }

                console.error('[STT] ❌ 기타 에러:', event.error);

                // 🎯 기타 에러들
                this.isRunning = false;
                window.HerGlobalState.reset();

                const errorData = {
                    sessionId: this._sessionId,
                    error: { 
                        type: event.error,
                        message: `음성 인식 중 오류가 발생했습니다: ${event.error}`
                    },
                    preservedText: this.finalTranscript || '',
                    endType: 'error'
                };

                if (this.callbacks.onStateChange) {
                    this.callbacks.onStateChange('error', errorData);
                } else if (this.onStateChange) {
                    this.onStateChange('error', errorData);
                }
            };
        }

        setupVisibilityHandling() {
            // 이미 설정되어 있으면 중복 설정 방지
            if (this.visibilityHandlerSet) return;
            this.visibilityHandlerSet = true;

            // 창이 숨겨졌다가 다시 보일 때 STT 재활성화
            document.addEventListener('visibilitychange', () => {
                if (this.isRunning && this._sessionId) {
                    if (document.hidden) {
                        // console.log('[STT] 창이 숨겨짐 - STT 일시 중단');
                        // 창이 숨겨져도 강제로 중단하지 않음 (백그라운드에서 계속 실행)
                    } else {
                        // console.log('[STT] 창이 다시 보임 - STT 확인');
                        // 창이 다시 보이면 STT 상태 확인 및 복구
                        setTimeout(() => {
                            if (this.isRunning && this._sessionId && (!this.recognition || this.recognition.readyState === 'closed')) {
                                // console.log('[STT] 창 복귀 시 STT 재시작');
                                this.restartRecognition();
                            }
                        }, 500);
                    }
                }
            });
        }

        restartRecognition() {
            if (!this.isRunning || !this._sessionId) return;

            try {
                const backupText = this.finalTranscript;

                // 새 recognition 객체 생성
                this.recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
                this.recognition.lang = this.language;
                this.recognition.interimResults = true;
                this.recognition.continuous = true;
                this.recognition.maxAlternatives = 1;
                this.recognition.serviceURI = null;

                // 텍스트 복원
                this.finalTranscript = backupText;
                this.lastProcessedIndex = 0;

                // 이벤트 리스너 재설정
                this.setupRecognitionEvents();

                // 재시작
                this.recognition.start();

                // 상태 동기화
                this.isRunning = true;
                if (this.onStateChange) {
                    this.onStateChange('restart', {
                        sessionId: this._sessionId,
                        preservedText: backupText,
                        recovered: true,
                        reason: 'visibility',
                        endType: 'visibility_recovery'
                    });
                }

                // console.log('[STT] 창 복귀 시 재시작 성공');
            } catch (error) {
                console.error('[STT] 창 복귀 시 재시작 실패:', error);
            }
        }
    }

    // 전역 등록
    window.HerSTTEngine = HerSTTEngine;

    if (window.HerCoreManager) {
        window.HerCoreManager.registerModule('HerSTTEngine', HerSTTEngine.getInstance());
    }
})();