from __future__ import annotations

from pathlib import Path

import pytest

from adw_modules import agents, git_helper
from adw_modules.data_types import (AgentCall, ConfigDefaults, GenericOutput,
                                    ObservabilityConfig, PhaseParams, SSSFConfig)
from adw_modules.permissions import PermissionBreach
from adw_modules.runner import Run
from adw_modules.tracer import Tracer


def test_permission_breach_records_failed_phase_without_propagating(
        tmp_path: Path, monkeypatch, capsys) -> None:
    repo = tmp_path / "repo"
    repo.mkdir()
    monkeypatch.setattr(git_helper, "repo_root", lambda: repo)
    cfg = SSSFConfig(
        defaults=ConfigDefaults(data_dir=str(tmp_path / "data")),
        observability=ObservabilityConfig(db=str(tmp_path / "sssf.db")),
    )
    tracer = Tracer(tmp_path / "sssf.db", tmp_path / "events.jsonl")
    run = Run(cfg, "breach123", tracer, "engineer")
    tracer.session_start(run.adw_id, run.engineer, repo=repo)
    message = (
        "builder is barred from ['modules/harness/factory/'] but modified 1 path(s):\n"
        "  - modules/harness/factory/adw_modules/tracer.py — rolled back"
    )

    def breach(*_args, **_kwargs):
        raise PermissionBreach(message)

    monkeypatch.setattr(agents, "execute", breach)

    with pytest.raises(SystemExit) as exit_info:
        with run.phase(PhaseParams(
            name="build", kind="agent", owner="builder",
            description="Implement the requested change",
        )) as ph:
            ph.call(AgentCall(output_type=GenericOutput, prompt="build it"))

    assert exit_info.value.code == 1
    assert tracer.conn.execute(
        "SELECT status, error FROM phases WHERE adw_id=? AND name='build'",
        (run.adw_id,),
    ).fetchone() == ("fail", message)
    assert tracer.conn.execute(
        "SELECT status FROM sessions WHERE adw_id=?", (run.adw_id,),
    ).fetchone() == ("fail",)
    assert "Traceback" not in capsys.readouterr().err
    tracer.conn.close()
