"""Tests for the bootstrap-side runtime-snapshot writer (mgf.common._doctor_snapshot)."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING

from mgf.common._doctor_snapshot import RUNTIME_SNAPSHOT_ENV_VAR, emit_runtime_snapshot

if TYPE_CHECKING:
    from pathlib import Path

    import pytest


# ---------------------------------------------------------------------------
# emit_runtime_snapshot — bootstrap-side helper.
# ---------------------------------------------------------------------------


class TestEmitRuntimeSnapshot:
    def test_writes_when_env_var_set(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        emit_runtime_snapshot({"app_name": "test", "app_version": "1.0"})
        assert target.exists()
        loaded = json.loads(target.read_text())
        assert loaded == {"app_name": "test", "app_version": "1.0"}

    def test_noop_when_env_var_unset(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
        monkeypatch.delenv(RUNTIME_SNAPSHOT_ENV_VAR, raising=False)
        emit_runtime_snapshot({"app_name": "test"})
        # No file written anywhere predictable.

    def test_creates_parent_directory(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        target = tmp_path / "nested" / "deep" / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        emit_runtime_snapshot({"app_name": "test"})
        assert target.exists()

    def test_overwrites_existing_snapshot(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        target = tmp_path / "runtime.json"
        target.write_text('{"old": "data"}')
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        emit_runtime_snapshot({"new": "data"})
        loaded = json.loads(target.read_text())
        assert loaded == {"new": "data"}

    def test_does_not_raise_on_oserror(self, monkeypatch: pytest.MonkeyPatch) -> None:
        # Path that can't be written (root dir on a read-only-mounted file).
        # Use an obviously-invalid path that triggers OSError.
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, "/proc/this/cannot/be/created")
        # Must not raise — bootstrap depends on it being safe.
        emit_runtime_snapshot({"x": "y"})

    # -----------------------------------------------------------------
    # SH-02 — file mode + settings-secret scrubbing
    # -----------------------------------------------------------------

    def test_sh02_file_written_at_mode_0o600(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """SH-02: runtime snapshots are owner-only-readable; the
        previous code wrote at the process umask (typically
        ``0o644`` = world-readable), exposing the settings dump
        on shared hosts."""
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        emit_runtime_snapshot({"app_name": "test", "app_version": "1.0"})
        assert target.exists()
        # Last three octal digits = user/group/world bits.
        assert oct(target.stat().st_mode)[-3:] == "600", (
            f"snapshot mode is {oct(target.stat().st_mode)[-3:]}, expected 600"
        )

    def test_sh02_sentry_dsn_replaced_with_presence_indicator(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """SH-02: the snapshot's ``settings.crash.sentry_dsn`` MUST
        NOT carry the raw DSN. A configured value becomes ``"<set>"``
        (operator still sees "yes it's configured"); an unset value
        becomes ``"<unset>"``."""
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        secret_dsn = "https://abc123@sentry.io/4567"
        emit_runtime_snapshot(
            {
                "app_name": "test",
                "settings": {
                    "crash": {
                        "sentry_dsn": secret_dsn,
                        "http_url": "https://hook.example.invalid/c?t=tok123",
                        "otlp_endpoint": "https://otel.example.invalid",
                        "sinks": ["local"],
                    },
                },
            }
        )
        body = target.read_text()
        assert secret_dsn not in body, f"sentry_dsn leaked verbatim into snapshot: {body}"
        assert "tok123" not in body, "http_url secret leaked"
        loaded = json.loads(body)
        assert loaded["settings"]["crash"]["sentry_dsn"] == "<set>"
        assert loaded["settings"]["crash"]["http_url"] == "<set>"
        assert loaded["settings"]["crash"]["otlp_endpoint"] == "<set>"
        # Non-secret sibling fields are untouched.
        assert loaded["settings"]["crash"]["sinks"] == ["local"]

    def test_sh02_unset_secrets_marked_unset(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """The "<unset>" indicator distinguishes "not configured"
        from "configured (value hidden)" — important for the
        diagnostic the snapshot exists to provide."""
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        emit_runtime_snapshot(
            {
                "settings": {
                    "crash": {
                        "sentry_dsn": None,
                        "http_url": "",
                        "otlp_endpoint": None,
                    },
                },
            }
        )
        loaded = json.loads(target.read_text())
        assert loaded["settings"]["crash"]["sentry_dsn"] == "<unset>"
        assert loaded["settings"]["crash"]["http_url"] == "<unset>"
        assert loaded["settings"]["crash"]["otlp_endpoint"] == "<unset>"

    def test_sh02_scrub_is_robust_to_missing_sections(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """A snapshot whose ``settings`` is missing or malformed
        (a future refactor changes the shape) MUST still write —
        the SH-02 scrub is best-effort defence-in-depth, not a
        precondition for the diagnostic."""
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        # No settings field at all.
        emit_runtime_snapshot({"app_name": "x"})
        assert target.exists()
        # settings is not a dict.
        emit_runtime_snapshot({"app_name": "x", "settings": "not-a-dict"})
        # settings.crash is not a dict.
        emit_runtime_snapshot({"settings": {"crash": "weird"}})
        # No exception raised in any of the above.

    def test_sh02_does_not_mutate_callers_snapshot(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """The scrub operates on a copy — the caller's snapshot
        dict is untouched. Important because the caller
        (``_lifecycle._maybe_emit_runtime_snapshot``) may not
        expect its local dict to be mutated by a write helper."""
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))
        original_dsn = "https://k@sentry.io/9"
        snapshot = {
            "settings": {"crash": {"sentry_dsn": original_dsn}},
        }
        emit_runtime_snapshot(snapshot)
        # Caller's dict still carries the raw DSN — only the
        # on-disk version is scrubbed.
        assert snapshot["settings"]["crash"]["sentry_dsn"] == original_dsn


# ---------------------------------------------------------------------------
# Integration with bootstrap.
# ---------------------------------------------------------------------------


class TestBootstrapWritesSnapshot:
    def test_bootstrap_writes_snapshot_when_env_set(
        self,
        tmp_path: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        target = tmp_path / "runtime.json"
        monkeypatch.setenv(RUNTIME_SNAPSHOT_ENV_VAR, str(target))

        from mgf.common._test_helpers import bootstrap_for_test

        with bootstrap_for_test():
            assert target.exists()
            loaded = json.loads(target.read_text())
            assert loaded["app_name"] == "test-app"
            assert "log_handler_count" in loaded
            assert "redaction_pattern_groups" in loaded

    def test_bootstrap_no_snapshot_when_env_unset(
        self,
        monkeypatch: pytest.MonkeyPatch,
        tmp_path: Path,
    ) -> None:
        monkeypatch.delenv(RUNTIME_SNAPSHOT_ENV_VAR, raising=False)
        target = tmp_path / "runtime.json"

        from mgf.common._test_helpers import bootstrap_for_test

        with bootstrap_for_test():
            assert not target.exists()
