"""Minimal mock of the enforce REST endpoints for bats hook tests.

/api/v1/consult       -> {"is_governed_decision": true, "rules": [...], ...}
/api/v1/gate/check    -> verdict depends on action_path / session_id
/api/v1/compliance    -> {"counts": {}, "by_agent": {}}
/api/v1/audit/event   -> {"recorded": true}
"""
import json
import os
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer


class Handler(BaseHTTPRequestHandler):
    def log_message(self, *args):  # silence
        pass

    def _send(self, obj, code=200):
        body = json.dumps(obj).encode()
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self):
        if self.path.startswith("/api/v1/compliance"):
            self._send({"counts": {}, "by_agent": {}})
        else:
            self._send({"error": "not_found"}, 404)

    def do_POST(self):
        length = int(self.headers.get("Content-Length", "0"))
        raw = self.rfile.read(length) or b"{}"
        body = json.loads(raw or b"{}")
        # When KB_MOCK_CAPTURE_FILE is set, append the raw request body (one JSON
        # object per line) for EVERY POST before routing. Opt-in so the existing
        # bats tests (which do not set it) are unaffected. Lets a test assert the
        # action_diff threaded into the gate body and the gate_degraded event POST.
        capture = os.getenv("KB_MOCK_CAPTURE_FILE")
        if capture:
            with open(capture, "a", encoding="utf-8") as fh:
                fh.write(raw.decode("utf-8", "replace") + "\n")
        if self.path == "/api/v1/consult":
            self._send({
                "is_governed_decision": True,
                "rules": [{"id": "STD-U-002", "path": "p", "title": "Style",
                           "snippet": "...", "score": 1.0, "status": "", "type": ""}],
                "consulted_at": 1.0, "ttl_seconds": 300,
            })
        elif self.path == "/api/v1/gate/check":
            path = (body.get("action_path") or "")
            # Test trigger: an action_path containing the substring "boom" forces an
            # HTTP 500 (with a misleading verdict:allow body) so the hook's non-2xx
            # gate-unavailable path can be exercised. A hook that ignores HTTP status
            # would wrongly parse verdict=allow and let the action through.
            if "boom" in path:
                self._send({"error": "internal_error", "verdict": "allow"}, 500)
            elif path.endswith("pyproject.toml") and body.get("session_id") != "allowme":
                self._send({"verdict": "consult_required",
                            "reason": "governed action; call kb_consult first",
                            "rules": []})
            else:
                self._send({"verdict": "allow", "reason": "ok", "rules": []})
        elif self.path == "/api/v1/audit/event":
            self._send({"recorded": True})
        else:
            self._send({"error": "not_found"}, 404)


if __name__ == "__main__":
    port = int(sys.argv[1])
    HTTPServer(("127.0.0.1", port), Handler).serve_forever()
