import os

import powermem.config_loader as config_loader
import powermem.settings as settings


def _reset_env(monkeypatch, keys):
    for key in keys:
        monkeypatch.delenv(key, raising=False)


def _disable_env_file(monkeypatch):
    monkeypatch.setattr(config_loader, "_DEFAULT_ENV_FILE", None, raising=False)
    monkeypatch.setattr(settings, "_DEFAULT_ENV_FILE", None, raising=False)
    new_config = dict(config_loader.EmbeddingSettings.model_config)
    new_config["env_file"] = None
    monkeypatch.setattr(config_loader.EmbeddingSettings, "model_config", new_config)


def test_load_config_from_env_builds_core_config(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "DATABASE_PROVIDER",
            "OCEANBASE_HOST",
            "OCEANBASE_PORT",
            "OCEANBASE_USER",
            "OCEANBASE_PASSWORD",
            "OCEANBASE_DATABASE",
            "OCEANBASE_COLLECTION",
            "LLM_PROVIDER",
            "LLM_API_KEY",
            "LLM_MODEL",
            "QWEN_LLM_BASE_URL",
            "EMBEDDING_PROVIDER",
            "EMBEDDING_API_KEY",
            "EMBEDDING_MODEL",
            "OPENAI_EMBEDDING_BASE_URL",
            "AGENT_MEMORY_MODE",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("DATABASE_PROVIDER", "oceanbase")
    monkeypatch.setenv("OCEANBASE_HOST", "10.0.0.1")
    monkeypatch.setenv("OCEANBASE_PORT", "2881")
    monkeypatch.setenv("OCEANBASE_USER", "root@sys")
    monkeypatch.setenv("OCEANBASE_PASSWORD", "secret")
    monkeypatch.setenv("OCEANBASE_DATABASE", "powermem")
    monkeypatch.setenv("OCEANBASE_COLLECTION", "memories")
    monkeypatch.setenv("LLM_PROVIDER", "qwen")
    monkeypatch.setenv("LLM_API_KEY", "llm-key")
    monkeypatch.setenv("LLM_MODEL", "qwen-plus")
    monkeypatch.setenv("QWEN_LLM_BASE_URL", "https://qwen.example.com/v1")
    monkeypatch.setenv("EMBEDDING_PROVIDER", "openai")
    monkeypatch.setenv("EMBEDDING_API_KEY", "embed-key")
    monkeypatch.setenv("EMBEDDING_MODEL", "text-embedding-3-small")
    monkeypatch.setenv("OPENAI_EMBEDDING_BASE_URL", "https://emb.example.com/v1")
    monkeypatch.setenv("AGENT_MEMORY_MODE", "auto")

    config = config_loader.load_config_from_env()

    assert config["vector_store"]["provider"] == "oceanbase"
    assert config["vector_store"]["config"]["connection_args"]["host"] == "10.0.0.1"
    assert config["llm"]["provider"] == "qwen"
    assert config["llm"]["config"]["dashscope_base_url"] == "https://qwen.example.com/v1"
    assert config["embedder"]["provider"] == "openai"
    assert (
        config["embedder"]["config"]["openai_base_url"]
        == "https://emb.example.com/v1"
    )
    assert config["agent_memory"]["mode"] == "auto"


def test_load_config_from_env_graph_store_fallback(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "GRAPH_STORE_ENABLED",
            "GRAPH_STORE_HOST",
            "GRAPH_STORE_MAX_HOPS",
            "OCEANBASE_HOST",
            "OCEANBASE_PORT",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("GRAPH_STORE_ENABLED", "true")
    monkeypatch.setenv("OCEANBASE_HOST", "127.0.0.2")
    monkeypatch.setenv("OCEANBASE_PORT", "2881")

    config = config_loader.load_config_from_env()

    graph_store = config["graph_store"]
    assert graph_store["enabled"] is True
    assert graph_store["config"]["host"] == "127.0.0.2"
    assert graph_store["config"]["max_hops"] == 3


def test_load_config_from_env_loads_internal_settings(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "MEMORY_BATCH_SIZE",
            "ENCRYPTION_ENABLED",
            "ACCESS_CONTROL_ENABLED",
            "MEMORY_DECAY_ENABLED",
            "DATABASE_SSLMODE",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("MEMORY_BATCH_SIZE", "200")
    monkeypatch.setenv("ENCRYPTION_ENABLED", "true")
    monkeypatch.setenv("ACCESS_CONTROL_ENABLED", "false")
    monkeypatch.setenv("MEMORY_DECAY_ENABLED", "false")
    monkeypatch.setenv("DATABASE_SSLMODE", "require")

    config = config_loader.load_config_from_env()

    # These settings should be included in the config
    assert "performance" in config
    assert config["performance"]["memory_batch_size"] == 200
    
    assert "security" in config
    assert config["security"]["encryption_enabled"] is True
    assert config["security"]["access_control_enabled"] is False
    
    assert "memory_decay" in config
    assert config["memory_decay"]["enabled"] is False


def test_load_config_from_env_telemetry_aliases(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "TELEMETRY_ENABLED",
            "TELEMETRY_BATCH_SIZE",
            "TELEMETRY_FLUSH_INTERVAL",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("TELEMETRY_ENABLED", "true")
    monkeypatch.setenv("TELEMETRY_BATCH_SIZE", "42")
    monkeypatch.setenv("TELEMETRY_FLUSH_INTERVAL", "15")

    config = config_loader.load_config_from_env()

    telemetry = config["telemetry"]
    assert telemetry["enable_telemetry"] is True
    assert telemetry["telemetry_batch_size"] == 42
    assert telemetry["telemetry_flush_interval"] == 15
    assert telemetry["batch_size"] == 42
    assert telemetry["flush_interval"] == 15


def test_load_config_from_env_embedding_provider_values(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "EMBEDDING_PROVIDER",
            "EMBEDDING_API_KEY",
            "AZURE_OPENAI_API_KEY",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("EMBEDDING_PROVIDER", "azure_openai")
    monkeypatch.setenv("AZURE_OPENAI_API_KEY", "azure-key")

    config = config_loader.load_config_from_env()

    assert config["embedder"]["provider"] == "azure_openai"
    assert config["embedder"]["config"]["api_key"] == "azure-key"


def test_load_config_from_env_embedding_common_override(monkeypatch):
    _reset_env(
        monkeypatch,
        [
            "EMBEDDING_PROVIDER",
            "EMBEDDING_API_KEY",
            "AZURE_OPENAI_API_KEY",
        ],
    )
    _disable_env_file(monkeypatch)
    monkeypatch.setenv("EMBEDDING_PROVIDER", "azure_openai")
    monkeypatch.setenv("AZURE_OPENAI_API_KEY", "azure-key")
    monkeypatch.setenv("EMBEDDING_API_KEY", "common-key")

    config = config_loader.load_config_from_env()

    assert config["embedder"]["provider"] == "azure_openai"
    assert config["embedder"]["config"]["api_key"] == "common-key"


def test_load_dotenv_uses_powermem_env_file(monkeypatch, tmp_path):
    monkeypatch.delenv("DASHSCOPE_API_KEY", raising=False)
    monkeypatch.setattr(config_loader, "_DEFAULT_ENV_FILE", None, raising=False)
    env_path = tmp_path / "powermem.env"
    env_path.write_text("DASHSCOPE_API_KEY=key-from-cli-env-file\n", encoding="utf-8")
    monkeypatch.setenv("POWERMEM_ENV_FILE", str(env_path))
    config_loader._load_dotenv_if_available()
    assert os.environ.get("DASHSCOPE_API_KEY") == "key-from-cli-env-file"


def test_load_dotenv_powermem_env_file_wins_over_default(monkeypatch, tmp_path):
    monkeypatch.delenv("DASHSCOPE_API_KEY", raising=False)
    default = tmp_path / ".env"
    default.write_text("DASHSCOPE_API_KEY=from-default\n", encoding="utf-8")
    custom = tmp_path / "custom.env"
    custom.write_text("DASHSCOPE_API_KEY=from-custom\n", encoding="utf-8")
    monkeypatch.setattr(config_loader, "_DEFAULT_ENV_FILE", str(default), raising=False)
    monkeypatch.setenv("POWERMEM_ENV_FILE", str(custom))
    config_loader._load_dotenv_if_available()
    assert os.environ.get("DASHSCOPE_API_KEY") == "from-custom"
