"""
Phase 104: Mutation Safety Gate

The final safeguard before autonomous changes are committed to the codebase.
This gate enforces:
1. Circuit Breaker status (halts if the system is thrashing).
2. Protected Zones (prevents AI from modifying the testing framework itself).
3. Test Validation (runs tests and instantly rolls back if any fail).
"""

import logging
import subprocess
from pathlib import Path
from typing import List, Tuple

from brynq.circuit_breaker import is_execution_allowed, record_success, record_failure

logger = logging.getLogger("brynq.safety_gate")

# The evaluation harness and core security modules must never be auto-mutated.
PROTECTED_FILES = {
    "test_guard.py",
    "src/brynq/mutation_safety_gate.py",
    "src/brynq/circuit_breaker.py",
    "src/brynq/enforcer.py",
    "src/brynq/api_security.py",
}

def _git(*args: str) -> subprocess.CompletedProcess:
    return subprocess.run(
        ["git", *args], capture_output=True, text=True,
        encoding="utf-8", errors="replace"
    )

def check_protected_zones() -> Tuple[bool, str]:
    """Check if any currently modified file is in a protected zone."""
    status = _git("status", "--porcelain")
    
    modified_files = []
    for line in (status.stdout or "").strip().splitlines():
        if not line.strip():
            continue
        filepath = line[3:].strip()
        modified_files.append(filepath.replace("\\", "/"))
        
    for filepath in modified_files:
        if filepath in PROTECTED_FILES or any(filepath.endswith(pf) for pf in PROTECTED_FILES):
            return False, f"Attempted to mutate protected file: {filepath}"
            
    return True, ""

def rollback_changes():
    """Instantly wipe any uncommitted changes to restore the baseline."""
    logger.warning("Safety Gate: Rolling back changes...")
    _git("reset", "--hard")
    _git("clean", "-fd")

def validate_and_commit(commit_message: str, test_dir: str = "tests/") -> dict:
    """
    The main execution gate. 
    Checks circuit breaker -> Checks protected zones -> Runs tests -> Commits OR Rolls back.
    """
    # 1. Circuit Breaker Check
    if not is_execution_allowed():
        logger.error("Safety Gate: Execution blocked by Circuit Breaker.")
        rollback_changes()
        return {"status": "rejected", "reason": "Circuit Breaker OPEN"}
        
    # 2. Protected Zones Check
    allowed, reason = check_protected_zones()
    if not allowed:
        logger.error(f"Safety Gate: {reason}")
        record_failure("Mutated protected zone")
        rollback_changes()
        return {"status": "rejected", "reason": reason}
        
    # 3. Test Validation
    logger.info("Safety Gate: Running tests...")
    import sys
    # Import run_tests from test_guard
    try:
        from test_guard import run_tests
    except ImportError:
        logger.error("Safety Gate: Could not load test_guard.py")
        record_failure("Missing test_guard")
        rollback_changes()
        return {"status": "error", "reason": "Missing test harness"}

    report = run_tests(test_dir, quick=True)
    verdict = report.get("verdict", "FAIL")
    
    # 4. Action
    if verdict == "PASS":
        logger.info("Safety Gate: Tests passed. Approving mutation.")
        _git("add", "-A")
        commit_res = _git("commit", "-m", commit_message)
        
        # Reset circuit breaker
        record_success()
        return {"status": "accepted", "commit": commit_res.stdout.strip()}
    else:
        logger.warning(f"Safety Gate: Tests failed ({len(report.get('failed', []))} failures).")
        record_failure(f"Tests failed: {', '.join(report.get('failed', [])[:3])}")
        rollback_changes()
        return {"status": "rejected", "reason": "Tests failed", "report": report}
