import logging
import stat

import pytest

from machine_backup.logs import CommandError, redact, run_logged, setup_logging


@pytest.mark.parametrize(
    "raw,gone",
    [
        ("password=SuperSecret123", "SuperSecret123"),
        ("MY_API_TOKEN: abcdef", "abcdef"),
        ("AGE-SECRET-KEY-1QQPZRV9X8GF2TVDW0S3JN54KHCE6MUA7L", "QQPZRV9X8"),
        ("postgres://bob:hunter2@localhost/db", "hunter2"),
        ("PGPASSWORD=tropfacile pg_dump", "tropfacile"),
    ],
)
def test_redact_removes_secret(raw, gone):
    out = redact(raw)
    assert gone not in out
    assert "[REDACTED]" in out


def test_redact_preserves_normal_text():
    assert redact("dump de la base elevaspeed ok") == "dump de la base elevaspeed ok"


def test_setup_logging_dir_700_and_rotation(tmp_path):
    for i in range(25):
        (tmp_path / f"run-20260101-0000{i:02d}-1.log").write_text("old")
    path = setup_logging(log_dir=tmp_path, keep=20)
    assert stat.S_IMODE(tmp_path.stat().st_mode) == 0o700
    assert len(list(tmp_path.glob("run-*.log"))) == 20
    assert path.exists()


def test_debug_log_always_full_and_redacted(tmp_path):
    setup_logging(verbosity=0, log_dir=tmp_path, keep=20)
    logging.getLogger("machine_backup.test").debug("connexion password=TopSecret ok")
    logging.shutdown()
    content = max(tmp_path.glob("run-*.log")).read_text()
    # Le DEBUG est ecrit meme si la console est en WARNING.
    assert "connexion" in content
    assert "TopSecret" not in content


def test_run_logged_captures(tmp_path):
    setup_logging(log_dir=tmp_path)
    r = run_logged(["/bin/echo", "hello"])
    assert r.returncode == 0
    assert r.stdout.strip() == "hello"
    assert r.duration_s >= 0


def test_run_logged_traces_command_in_debug_log(tmp_path):
    setup_logging(log_dir=tmp_path)
    run_logged(["/bin/echo", "trace-moi"])
    logging.shutdown()
    content = max(tmp_path.glob("run-*.log")).read_text()
    assert "/bin/echo" in content
    assert "trace-moi" in content


def test_run_logged_check_raises_and_carries_result(tmp_path):
    setup_logging(log_dir=tmp_path)
    with pytest.raises(CommandError) as excinfo:
        run_logged(["/usr/bin/false"], check=True)
    assert excinfo.value.result.returncode != 0


def test_run_logged_never_passes_env(tmp_path, monkeypatch):
    """L'invariant : aucune variable d'environnement n'est injectee ni capturee."""
    import subprocess

    seen = {}
    real_run = subprocess.run

    def spy(*args, **kwargs):
        seen.update(kwargs)
        return real_run(*args, **kwargs)

    monkeypatch.setattr(subprocess, "run", spy)
    setup_logging(log_dir=tmp_path)
    run_logged(["/bin/echo", "x"])
    assert "env" not in seen
