"""
Model loader tests - critical for ensuring YAML config works correctly.
Tests the fix for os.environ vs import-time constant issue.
"""

import pytest
import os
from unittest.mock import patch, MagicMock


@pytest.mark.unit
def test_model_loader_reads_env_at_call_time(clean_env):
    """CRITICAL: Test that model_loader reads env vars at call time, not import time."""
    from ytqgen.model_loader import get_llm_client
    
    # Set environment variables
    os.environ['LLM_PROVIDER'] = 'groq'
    os.environ['GROQ_API_KEY'] = 'test_key_123'
    os.environ['YTQGEN_GROQ_MODEL'] = 'llama-3.3-70b-versatile'
    
    # Import here to ensure model_loader has already imported Groq
    from ytqgen.model_loader import get_llm_client
    
    # Mock Groq client - use create=True to work even when groq not installed
    with patch('ytqgen.model_loader.GROQ_AVAILABLE', True):
        with patch('ytqgen.model_loader.Groq', create=True) as mock_groq:
            mock_client = MagicMock()
            mock_groq.return_value = mock_client
            
            client, model, provider = get_llm_client()
            
            assert provider == 'groq'
            assert model == 'llama-3.3-70b-versatile', f"Expected llama-3.3-70b-versatile, got {model}"
            mock_groq.assert_called_once_with(api_key='test_key_123')


@pytest.mark.unit
def test_model_loader_respects_yaml_config(clean_env):
    """Test that model_loader picks up YAML config applied via os.environ."""
    from ytqgen.model_loader import get_llm_client
    
    # Simulate YAML config being applied
    os.environ['LLM_PROVIDER'] = 'groq'
    os.environ['GROQ_API_KEY'] = 'yaml_key_456'
    os.environ['YTQGEN_GROQ_MODEL'] = 'mixtral-8x7b-32768'  # Different model from default
    
    with patch('ytqgen.model_loader.GROQ_AVAILABLE', True):
        with patch('ytqgen.model_loader.Groq', create=True) as mock_groq:
            mock_client = MagicMock()
            mock_groq.return_value = mock_client
            
            client, model, provider = get_llm_client()
            
            assert model == 'mixtral-8x7b-32768', "Should use YAML-configured model"


@pytest.mark.unit
def test_model_loader_openai_provider(clean_env):
    """Test OpenAI provider initialization."""
    from ytqgen.model_loader import get_llm_client
    
    os.environ['LLM_PROVIDER'] = 'openai'
    os.environ['OPENAI_API_KEY'] = 'sk-test123'
    os.environ['YTQGEN_OPENAI_MODEL'] = 'gpt-4o-mini'
    
    with patch('ytqgen.model_loader.OPENAI_AVAILABLE', True):
        with patch('ytqgen.model_loader.OpenAI', create=True) as mock_openai:
            mock_client = MagicMock()
            mock_openai.return_value = mock_client
            
            client, model, provider = get_llm_client()
            
            assert provider == 'openai'
            assert model == 'gpt-4o-mini'
            mock_openai.assert_called_once_with(api_key='sk-test123')


@pytest.mark.unit
def test_model_loader_mistral_provider(clean_env):
    """Test Mistral provider initialization."""
    from ytqgen.model_loader import get_llm_client
    
    os.environ['LLM_PROVIDER'] = 'mistral'
    os.environ['MISTRAL_API_KEY'] = 'mistral-test-key'
    os.environ['YTQGEN_MISTRAL_MODEL'] = 'mistral-small-latest'
    
    with patch('ytqgen.model_loader.MISTRAL_AVAILABLE', True):
        with patch('ytqgen.model_loader.Mistral', create=True) as mock_mistral:
            mock_client = MagicMock()
            mock_mistral.return_value = mock_client
            
            client, model, provider = get_llm_client()
            
            assert provider == 'mistral'
            assert model == 'mistral-small-latest'
            mock_mistral.assert_called_once_with(api_key='mistral-test-key')


@pytest.mark.unit
def test_model_loader_missing_api_key(clean_env):
    """Test that missing API key raises error."""
    from ytqgen.model_loader import get_llm_client
    
    os.environ['LLM_PROVIDER'] = 'groq'
    # Explicitly remove GROQ_API_KEY to test missing key scenario
    os.environ.pop('GROQ_API_KEY', None)
    
    with patch('ytqgen.model_loader.GROQ_AVAILABLE', True):
        with pytest.raises(ValueError, match="GROQ_API_KEY is not set"):
            get_llm_client()


@pytest.mark.unit
def test_model_loader_provider_not_available(clean_env):
    """Test that unavailable provider raises error."""
    from ytqgen.model_loader import get_llm_client
    
    os.environ['LLM_PROVIDER'] = 'groq'
    os.environ['GROQ_API_KEY'] = 'test-key'
    
    with patch('ytqgen.model_loader.GROQ_AVAILABLE', False):
        with pytest.raises(ValueError, match="Groq provider not available"):
            get_llm_client()


@pytest.mark.unit
def test_model_loader_invalid_provider(clean_env):
    """Test that invalid provider raises error."""
    from ytqgen.model_loader import get_llm_client
    
    os.environ['LLM_PROVIDER'] = 'invalid_provider'
    # Set a valid API key to get past that check
    os.environ['GROQ_API_KEY'] = 'dummy-key'
    
    with pytest.raises(ValueError, match="Unsupported LLM provider"):
        get_llm_client()


@pytest.mark.unit
def test_model_loader_defaults_when_no_env_vars(clean_env):
    """Test that defaults are used when env vars not set."""
    from ytqgen.model_loader import get_llm_client
    
    # Set minimum required env vars (provider defaults to "openai" if not set)
    os.environ['LLM_PROVIDER'] = 'groq'
    os.environ['GROQ_API_KEY'] = 'test-key'
    # Don't set YTQGEN_GROQ_MODEL - should use default
    
    with patch('ytqgen.model_loader.GROQ_AVAILABLE', True):
        with patch('ytqgen.model_loader.Groq', create=True) as mock_groq:
            mock_client = MagicMock()
            mock_groq.return_value = mock_client
            
            client, model, provider = get_llm_client()
            
            # Should use default model (llama-3.3-70b-versatile as per your fix)
            assert model == 'llama-3.3-70b-versatile'
