"""Regression tests for #93593: a malformed provider key in .env must not
silently shadow a valid credential-pool key.

Before the fix, ``_resolve_api_key_provider_secret`` returned the FIRST env
value that passed ``has_usable_secret`` (length + placeholder check only), so
an obviously malformed OPENROUTER_API_KEY (e.g. a truncated paste or another
provider's key) in ~/.hermes/.env won over a valid pool entry and produced
opaque ``401 Missing Authentication header`` errors.

The fix:
- providers with a declared key prefix (KNOWN_PROVIDER_KEY_PREFIXES) skip
  env values that don't match, with a WARNING naming the env var, and fall
  through to the next env var / credential pool;
- the credential-pool fallback iterates entries instead of only peek(), so a
  malformed pool entry doesn't block a valid one either;
- providers WITHOUT a declared prefix are fail-open (unchanged behavior);
- a VALID env key still wins over the pool (precedence unchanged).
"""

import logging
from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest


def _make_pconfig(provider_id, env_vars=None):
    from hermes_cli.auth import ProviderConfig
    return ProviderConfig(
        id=provider_id,
        name=provider_id.title(),
        auth_type="api_key",
        api_key_env_vars=tuple(env_vars or [f"{provider_id.upper()}_API_KEY"]),
    )


@pytest.fixture
def isolated_hermes_home(tmp_path, monkeypatch):
    home = tmp_path / ".hermes"
    home.mkdir()
    monkeypatch.setattr(Path, "home", lambda: tmp_path)
    monkeypatch.setenv("HERMES_HOME", str(home))
    for key in ["OPENROUTER_API_KEY", "DEEPSEEK_API_KEY", "OPENAI_API_KEY"]:
        monkeypatch.delenv(key, raising=False)
    return home


def _write_env_file(home: Path, **kwargs) -> None:
    lines = [f"{k}={v}" for k, v in kwargs.items()]
    (home / ".env").write_text("\n".join(lines) + "\n")


def _mock_pool(*entries):
    pool = MagicMock()
    pool.has_credentials.return_value = bool(entries)
    pool.peek.return_value = entries[0] if entries else None
    pool.entries.return_value = list(entries)
    return pool


def _entry(token):
    e = MagicMock()
    e.access_token = token
    e.runtime_api_key = ""
    return e


class TestMalformedEnvKeySkipped:
    """Declared-prefix mismatch in .env → warn + fall through to pool."""

    def test_malformed_openrouter_env_key_falls_back_to_pool(
        self, isolated_hermes_home, caplog
    ):
        _write_env_file(isolated_hermes_home, OPENROUTER_API_KEY="not-a-real-openrouter-key")
        pool = _mock_pool(_entry("sk-or-v1-valid-pool-key-abc123"))

        from hermes_cli.auth import _resolve_api_key_provider_secret
        with patch("agent.credential_pool.load_pool", return_value=pool):
            with caplog.at_level(logging.WARNING):
                key, source = _resolve_api_key_provider_secret(
                    provider_id="openrouter",
                    pconfig=_make_pconfig("openrouter"),
                )
        assert key == "sk-or-v1-valid-pool-key-abc123"
        assert source == "credential_pool:openrouter"
        warnings = [r for r in caplog.records if "OPENROUTER_API_KEY" in r.getMessage()]
        assert warnings, "expected a WARNING naming the malformed env var"

    def test_malformed_env_key_with_empty_pool_returns_empty(
        self, isolated_hermes_home, caplog
    ):
        """Malformed env key + no pool → empty result, never the bad key."""
        _write_env_file(isolated_hermes_home, OPENROUTER_API_KEY="sk-proj-wrong-provider-key")
        pool = _mock_pool()

        from hermes_cli.auth import _resolve_api_key_provider_secret
        with patch("agent.credential_pool.load_pool", return_value=pool):
            with caplog.at_level(logging.WARNING):
                key, source = _resolve_api_key_provider_secret(
                    provider_id="openrouter",
                    pconfig=_make_pconfig("openrouter"),
                )
        assert key == ""
        assert source == ""

    def test_malformed_pool_entry_skipped_for_valid_one(self, isolated_hermes_home):
        """Pool iteration: a malformed first entry must not block a valid second."""
        pool = _mock_pool(
            _entry("garbage-pool-entry"),
            _entry("sk-or-v1-second-entry-good"),
        )

        from hermes_cli.auth import _resolve_api_key_provider_secret
        with patch("agent.credential_pool.load_pool", return_value=pool):
            key, source = _resolve_api_key_provider_secret(
                provider_id="openrouter",
                pconfig=_make_pconfig("openrouter"),
            )
        assert key == "sk-or-v1-second-entry-good"
        assert source == "credential_pool:openrouter"


class TestNoDeclaredPrefixUnaffected:
    """Providers without a declared prefix keep today's fail-open behavior."""

    def test_undeclared_provider_env_key_returned_verbatim(self, isolated_hermes_home):
        _write_env_file(isolated_hermes_home, DEEPSEEK_API_KEY="totally-unknown-format-key")

        from hermes_cli.auth import _resolve_api_key_provider_secret
        pool = _mock_pool(_entry("pool-key-should-not-win"))
        with patch("agent.credential_pool.load_pool", return_value=pool) as mp:
            key, source = _resolve_api_key_provider_secret(
                provider_id="deepseek",
                pconfig=_make_pconfig("deepseek"),
            )
        assert key == "totally-unknown-format-key"
        assert source == "DEEPSEEK_API_KEY"
        mp.assert_not_called()


class TestValidEnvKeyStillWins:
    """Precedence unchanged: a valid env key beats the credential pool."""

    def test_valid_openrouter_env_key_wins_over_pool(self, isolated_hermes_home):
        _write_env_file(isolated_hermes_home, OPENROUTER_API_KEY="sk-or-v1-env-key-wins")
        pool = _mock_pool(_entry("sk-or-v1-pool-key-loses"))

        from hermes_cli.auth import _resolve_api_key_provider_secret
        with patch("agent.credential_pool.load_pool", return_value=pool) as mp:
            key, source = _resolve_api_key_provider_secret(
                provider_id="openrouter",
                pconfig=_make_pconfig("openrouter"),
            )
        assert key == "sk-or-v1-env-key-wins"
        assert source == "OPENROUTER_API_KEY"
        mp.assert_not_called()

    def test_second_env_var_wins_when_first_is_malformed(self, isolated_hermes_home):
        """Malformed first env var falls through to a valid SECOND env var."""
        _write_env_file(
            isolated_hermes_home,
            OPENROUTER_API_KEY="malformed-first-var",
            OPENROUTER_KEY="sk-or-v1-second-var-good",
        )

        from hermes_cli.auth import _resolve_api_key_provider_secret
        key, source = _resolve_api_key_provider_secret(
            provider_id="openrouter",
            pconfig=_make_pconfig(
                "openrouter", env_vars=["OPENROUTER_API_KEY", "OPENROUTER_KEY"]
            ),
        )
        assert key == "sk-or-v1-second-var-good"
        assert source == "OPENROUTER_KEY"
