"""Environment-variable backed vault.

Stdlib-only. Useful for CI environments where secrets come from
the orchestrator (GitHub Actions secrets, Codeberg secrets,
Kubernetes downward API) and land in the process env. Reads /
writes never touch disk.

Threading: not thread-safe in the strict sense — ``os.environ``
is a process-global. Concurrent ``set`` / ``delete`` from
multiple threads can race. The pattern's normal usage (read-only
in worker threads; write at startup) avoids the race.

Audit logging: every ``get`` / ``set`` / ``delete`` emits an
``audit=true`` log record per rule SC-17. The KEY is logged;
the VALUE is not.
"""

from __future__ import annotations

import os

from mgf.common.observability import get_logger

_LOG = get_logger(__name__)


class EnvVault:
    """Vault backed by environment variables.

    Each key is mapped to ``<prefix><KEY>`` (uppercased). Reading
    / writing is plain ``os.environ`` access.

    Use this backend for CI / containerised deployments where the
    orchestrator injects secrets at process-start time. Not
    suitable for desktop apps that need persistent storage —
    use :class:`mgf.common.vault.KeyringVault` or
    :class:`mgf.common.vault.EncryptedFileVault` instead.

    Implements :class:`mgf.common.typing.VaultProtocol`.
    """

    __slots__ = ("_prefix",)

    def __init__(self, *, prefix: str = "MGF_VAULT_") -> None:
        """Create an env-backed vault.

        Parameters
        ----------
        prefix
            Env-var prefix for every key. Defaults to
            ``"MGF_VAULT_"``. Per rule SC-12, consumer apps SHOULD
            use their own prefix (e.g., ``"MYAPP_VAULT_"``) to
            avoid collisions with library env vars.
        """
        self._prefix = prefix

    @property
    def backend(self) -> str:
        """Returns ``"env"`` — see rule DP-10 (no silent fallback)."""
        return "env"

    def get(self, key: str) -> str | None:
        """Return ``os.environ[<prefix><KEY>]`` or ``None`` if absent."""
        env_key = self._env_key(key)
        value = os.environ.get(env_key)
        _LOG.info(
            "vault read",
            extra={
                "audit": True,
                "event": "vault.read",
                "vault_key": key,
                "vault_backend": "env",
                "found": value is not None,
            },
        )
        return value

    def set(self, key: str, value: str) -> None:
        """Set ``os.environ[<prefix><KEY>] = value``. Idempotent.

        Note: env-var changes affect the entire process. Other
        threads / subprocesses started after this call see the
        new value.
        """
        env_key = self._env_key(key)
        os.environ[env_key] = value
        _LOG.info(
            "vault write",
            extra={
                "audit": True,
                "event": "vault.write",
                "vault_key": key,
                "vault_backend": "env",
            },
        )

    def delete(self, key: str) -> None:
        """Remove ``os.environ[<prefix><KEY>]``. No-op if absent."""
        env_key = self._env_key(key)
        existed = env_key in os.environ
        os.environ.pop(env_key, None)
        _LOG.info(
            "vault delete",
            extra={
                "audit": True,
                "event": "vault.delete",
                "vault_key": key,
                "vault_backend": "env",
                "existed": existed,
            },
        )

    def list_keys(self) -> list[str]:
        """Return every stored key (lower-cased; sorted).

        Scans ``os.environ`` for entries with ``self._prefix``;
        strips the prefix; lower-cases. Stable / deterministic
        order.
        """
        prefix_len = len(self._prefix)
        return sorted(k[prefix_len:].lower() for k in os.environ if k.startswith(self._prefix))

    def _env_key(self, key: str) -> str:
        """Map a key to its env-var name. Uppercased."""
        return f"{self._prefix}{key.upper()}"

    def __repr__(self) -> str:
        return f"EnvVault(prefix={self._prefix!r})"


__all__ = ["EnvVault"]
