import pytest
import importlib
import yaml
from app.config import EmbeddingProvider, TTSProvider, Settings


@pytest.fixture
def tmp_config_file(tmp_path):
    """
    Creates a temporary config.yaml file and returns its path.
    Corrected the 'provider' value to be lowercase 'mock' to match the Enum.
    Added database and TTS settings for testing.
    """
    config_content = {
        "application": {
            "project_name": "Test Project from YAML",
            "log_level": "WARNING"
        },
        "llm_providers": {"deepseek_model_name": "deepseek-from-yaml"},
        "embedding_provider": {
            # This value must be lowercase to match the Pydantic Enum member
            "provider": "mock",
            "model_name": "embedding-model-from-yaml",
            "api_key": "embedding-api-from-yaml"
        },
        "database": {
            "mode": "sqlite",
            "local_path": "custom_folder/test_ai_hub.db",
            "url": "postgresql://user:pass@host/dbname"  # Should be ignored for sqlite mode
        },
        "tts_provider": {
            "provider": "google_genai",
            "voice_name": "Laomedeia",
            "api_key": "tts-api-from-yaml"
        }
    }
    config_path = tmp_path / "test_config.yaml"
    with open(config_path, 'w') as f:
        yaml.dump(config_content, f)
    return str(config_path)


@pytest.fixture
def clear_all_env(monkeypatch):
    """
    A fixture to clear all relevant environment variables for test isolation.
    """
    monkeypatch.delenv("CONFIG_PATH", raising=False)
    monkeypatch.delenv("DEEPSEEK_API_KEY", raising=False)
    monkeypatch.delenv("GEMINI_API_KEY", raising=False)
    monkeypatch.delenv("EMBEDDING_API_KEY", raising=False)
    monkeypatch.delenv("TTS_PROVIDER", raising=False)
    monkeypatch.delenv("TTS_VOICE_NAME", raising=False)
    monkeypatch.delenv("TTS_API_KEY", raising=False)
    monkeypatch.delenv("DB_MODE", raising=False)
    monkeypatch.delenv("LOCAL_DB_PATH", raising=False)
    monkeypatch.delenv("DATABASE_URL", raising=False)


@pytest.fixture
def mock_all_keys(monkeypatch):
    """
    A fixture to set all mock API keys.
    """
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_deepseek_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_gemini_key")
    monkeypatch.setenv("EMBEDDING_API_KEY", "mock_embedding_key")
    monkeypatch.setenv("TTS_API_KEY", "mock_tts_key")


def test_sqlite_db_url_from_yaml(monkeypatch, tmp_config_file, clear_all_env):
    """Tests DATABASE_URL is constructed correctly from YAML sqlite local_path."""
    monkeypatch.setenv("CONFIG_PATH", tmp_config_file)
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    expected_path = "sqlite:///./custom_folder/test_ai_hub.db"
    assert settings.DB_MODE == "sqlite"
    assert settings.DATABASE_URL == expected_path


def test_sqlite_db_url_from_env_local_path(monkeypatch, tmp_path, clear_all_env):
    """Tests that LOCAL_DB_PATH env var overrides YAML for sqlite DATABASE_URL."""
    monkeypatch.setenv("DB_MODE", "sqlite")
    monkeypatch.setenv("LOCAL_DB_PATH", "env_folder/env_ai_hub.db")
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    expected_path = "sqlite:///./env_folder/env_ai_hub.db"
    assert settings.DB_MODE == "sqlite"
    assert settings.DATABASE_URL == expected_path


def test_external_db_url_used_when_not_sqlite(monkeypatch, tmp_config_file, clear_all_env):
    """Tests DATABASE_URL uses external URL when DB_MODE is not sqlite."""
    monkeypatch.setenv("CONFIG_PATH", tmp_config_file)
    monkeypatch.setenv("DB_MODE", "postgresql")
    monkeypatch.setenv("DATABASE_URL", "postgresql://env_user:env_pass@env_host/env_db")
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    assert settings.DB_MODE == "postgresql"
    assert settings.DATABASE_URL == "postgresql://env_user:env_pass@env_host/env_db"


def test_external_db_url_from_yaml_when_not_sqlite(monkeypatch, tmp_path, clear_all_env):
    """Tests DATABASE_URL uses YAML url when DB_MODE != sqlite and no env DATABASE_URL."""
    # Write YAML with postgresql mode and url
    config_content = {
        "database": {
            "mode": "postgresql",
            "url": "postgresql://yaml_user:yaml_pass@yaml_host/yaml_db",
            "local_path": "ignored_path_for_postgresql.db"
        },
        "llm_providers": {"deepseek_model_name": "deepseek-from-yaml"}
    }
    config_path = tmp_path / "test_config_pg.yaml"
    with open(config_path, 'w') as f:
        yaml.dump(config_content, f)
    monkeypatch.setenv("CONFIG_PATH", str(config_path))
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    assert settings.DB_MODE == "postgresql"
    assert settings.DATABASE_URL == "postgresql://yaml_user:yaml_pass@yaml_host/yaml_db"


def test_sqlite_db_url_defaults(monkeypatch, clear_all_env):
    """Tests DATABASE_URL defaults to sqlite path if no env or YAML."""
    monkeypatch.setenv("DB_MODE", "sqlite")
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")
    settings = Settings()

    assert settings.DB_MODE == "sqlite"
    assert settings.DATABASE_URL == "sqlite:///./data/ai_hub.db"


# --- Tests for TTS Configuration ---

def test_tts_settings_from_yaml(monkeypatch, tmp_config_file, clear_all_env):
    """Tests that TTS settings are loaded correctly from a YAML file."""
    monkeypatch.setenv("CONFIG_PATH", tmp_config_file)
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    assert settings.TTS_PROVIDER == TTSProvider.GOOGLE_GENAI
    assert settings.TTS_VOICE_NAME == "Laomedeia"
    assert settings.TTS_API_KEY == "tts-api-from-yaml"


def test_tts_settings_from_env(monkeypatch, tmp_config_file, clear_all_env):
    """Tests that TTS environment variables override the YAML file."""
    monkeypatch.setenv("CONFIG_PATH", tmp_config_file)
    # Explicitly set all TTS env vars for this test
    monkeypatch.setenv("TTS_PROVIDER", "google_genai")
    monkeypatch.setenv("TTS_VOICE_NAME", "Zephyr")
    monkeypatch.setenv("TTS_API_KEY", "env_tts_key")
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")

    settings = Settings()
    assert settings.TTS_PROVIDER == TTSProvider.GOOGLE_GENAI
    assert settings.TTS_VOICE_NAME == "Zephyr"
    assert settings.TTS_API_KEY == "env_tts_key"


def test_tts_settings_defaults(monkeypatch, clear_all_env):
    """Tests that TTS settings fall back to Pydantic defaults if no env or YAML are present."""
    monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_key")
    monkeypatch.setenv("GEMINI_API_KEY", "mock_key")
    settings = Settings()

    assert settings.TTS_PROVIDER == TTSProvider.GOOGLE_GENAI
    assert settings.TTS_VOICE_NAME == "Kore"
    assert settings.TTS_API_KEY is None
