import os
import pytest
from app.models.stt import STTRequest, STTResponse
from app.core.exceptions import AudioFileNotFoundError, ModelNotFoundError
from app.services.stt_service import WhisperSTTService

class MockSegment:
    def __init__(self, text):
        self.text = text

class MockInfo:
    def __init__(self, language):
        self.language = language

class MockWhisperModel:
    """faster-whisper 엔진을 흉내내는 테스트용 Mock 클래스"""
    def __init__(self, model_size_or_path, device="cpu", compute_type="int8"):
        self.model_size_or_path = model_size_or_path
        
    def transcribe(self, audio_path, beam_size=5):
        # 의도된 테스트 출력 결과 (무전 기록)
        segments = [MockSegment("열차 번호 1234, 기지 입고 확인했습니다. 수신 양호합니다.")]
        info = MockInfo(language="ko")
        return segments, info

def test_pydantic_schema_validation():
    """Pydantic 모델이 오염된 데이터를 차단하고 정상 생성되는지 테스트"""
    req = STTRequest(audio_file_path="dummy.wav")
    assert req.audio_file_path == "dummy.wav"
    assert req.language == "ko" # Default 값 확인

def test_stt_transcription_success(monkeypatch, tmp_path):
    """STT 전체 프로세스가 정상적으로 처리되는지 확인하는 테스트"""
    
    # 1. 테스트용 더미 오디오
    dummy_audio = tmp_path / "test_audio.wav"
    dummy_audio.touch()
    
    # 2. 서비스 인스턴스 초기화
    service = WhisperSTTService()
    service.model_name = "test_base"
    
    # 3. WhisperModel 및 AudioParser Mock 객체로 대체(Patch)
    monkeypatch.setattr("app.services.stt_service.WhisperModel", MockWhisperModel)
    
    # AudioParser는 변환 대신 그대로 리턴하게 모킹
    class MockAudioParser:
        @staticmethod
        def preprocess_audio(file_path, sample_rate=16000):
            return file_path
        @staticmethod
        def cleanup(file_path):
            pass
            
    monkeypatch.setattr("app.services.stt_service.AudioParser", MockAudioParser)
    
    # 4. Request 생성 및 실행
    request = STTRequest(audio_file_path=str(dummy_audio))
    response = service.transcribe(request)
    
    # 5. Response 검증 (Pydantic 모델인지, 텍스트가 정상인지 검사)
    assert isinstance(response, STTResponse)
    assert "열차 번호 1234" in response.text
    assert response.language == "ko"
    assert response.processing_time_sec is not None

def test_stt_audio_file_not_found():
    """존재하지 않는 오디오 파일 요청 시 커스텀 예외 발생 테스트"""
    service = WhisperSTTService()
    request = STTRequest(audio_file_path="invalid_path.wav")
    
    with pytest.raises(AudioFileNotFoundError) as exc_info:
        service.transcribe(request)
        
    assert "오디오 파일을 찾을 수 없습니다" in str(exc_info.value)

def test_stt_model_file_not_found(monkeypatch, tmp_path):
    """Whisper 모델 로딩 실패 시 발생하는 예외 테스트"""
    dummy_audio = tmp_path / "test_audio.wav"
    dummy_audio.touch()
    
    # AudioParser 모킹
    class MockAudioParser:
        @staticmethod
        def preprocess_audio(file_path, sample_rate=16000):
            return file_path
        @staticmethod
        def cleanup(file_path):
            pass
            
    monkeypatch.setattr("app.services.stt_service.AudioParser", MockAudioParser)
    
    # 모델 로딩을 강제로 실패하게 하는 모킹
    def mock_init(*args, **kwargs):
        raise ValueError("Simulated model loading error")
        
    monkeypatch.setattr("app.services.stt_service.WhisperModel", mock_init)
    
    service = WhisperSTTService()
    service.model_name = "invalid_model_path_or_name"
    
    request = STTRequest(audio_file_path=str(dummy_audio))
    
    with pytest.raises(ModelNotFoundError) as exc_info:
        service.transcribe(request)
