import http.client
import json
from urllib.parse import urlsplit, quote


def review_with_session(base_url, session_id, admin_token, read_arguments,
                        original_request_id, persist_evidence, origin=None):
    """Use one already initialized, retained session on the configured fs host.
    read_arguments is the original admitted read_file argument object.
    persist_evidence must durably store each private observation before returning.
    Credentials are never printed or included in that evidence.
    """
    base = urlsplit(base_url)
    if base.scheme not in ("http", "https") or base.path not in ("", "/") or base.query or base.fragment:
        raise ValueError("supply the exact trusted host origin")

    def request(method, path, token, body=None, session=False):
        cls = http.client.HTTPSConnection if base.scheme == "https" else http.client.HTTPConnection
        conn = cls(base.hostname, base.port, timeout=20)
        headers = {"Authorization": "Bearer " + token, "Accept": "application/json, text/event-stream"}
        if session:
            headers["Mcp-Session-Id"] = session_id
            if origin is not None:
                headers["Origin"] = origin
        if body is not None:
            headers["Content-Type"] = "application/json"
        try:
            conn.request(method, path, None if body is None else json.dumps(body), headers)
            response = conn.getresponse()
            # http.client does not follow redirects to another credential recipient.
            if 300 <= response.status < 400:
                raise RuntimeError("trusted host redirected the request")
            content_type = response.getheader("Content-Type", "").split(";", 1)[0].strip()
            if content_type == "text/event-stream":
                data = []
                expected_id = body.get("id") if isinstance(body, dict) else None
                while True:
                    line = response.readline()
                    if not line:
                        raise RuntimeError("stream ended before the original terminal response")
                    line = line.decode("utf-8").rstrip("\r\n")
                    if line.startswith("data:"):
                        data.append(line[5:].lstrip(" "))
                    elif not line and data:
                        payload = "\n".join(data); data = []
                        if not payload.strip():
                            continue  # MCP may send an initial empty SSE event.
                        event = json.loads(payload)
                        if event.get("id") == expected_id and ("result" in event or "error" in event):
                            return response.status, event
            raw = response.read()
            try:
                body = json.loads(raw)
            except json.JSONDecodeError:
                body = raw.decode("utf-8", errors="replace")
            return response.status, body
        finally:
            conn.close()

    admin_path = "/admin/sessions/" + quote(session_id, safe="") + "/credential"
    status, issued = request("POST", admin_path, admin_token,
                             {"ttlSeconds": 120, "allowedTools": ["read_file"]})
    if status != 200:
        raise RuntimeError("session credential exchange refused: " + str(status))
    token = issued["bearerToken"]
    original = {"jsonrpc": "2.0", "id": original_request_id, "method": "tools/call",
                "params": {"name": "read_file", "arguments": read_arguments,
                           "_meta": {"chioRequestId": original_request_id}}}
    evidence = {"binding": {k:v for k,v in issued.items() if k != "bearerToken"},
                "request": original}
    status, result = request("POST", "/mcp", token, original, session=True)
    evidence["original_status"] = status; evidence["original"] = result
    persist_evidence(evidence)  # Must return only after private durable storage.
    if status != 200 or not isinstance(result, dict) or "error" in result:
        raise RuntimeError("original read needs retained-session diagnosis")
    # Keep the original result before acknowledging delivery. Acknowledge an
    # authenticated terminal tool error too; acknowledgement does not mean success.
    acknowledgement = result["result"]["_meta"]["chioDelivery"]
    status, acknowledged = request("POST", "/mcp", token,
        {"jsonrpc": "2.0", "id": "ack-" + original_request_id, "method": "chio/acknowledge",
         "params": acknowledgement}, session=True)
    evidence["ack_status"] = status; evidence["acknowledged"] = acknowledged
    persist_evidence(evidence)
    if status != 200 or not isinstance(acknowledged, dict) or not acknowledged.get("result", {}).get("acknowledged"):
        raise RuntimeError("retain original result and acknowledgement for recovery")
    status, revoked = request("POST", admin_path + "/revoke", admin_token)
    evidence["revoke_status"] = status; evidence["revoked"] = revoked
    persist_evidence(evidence)
    if status != 200:
        raise RuntimeError("revocation not established")
    status, rejected = request("POST", "/mcp", token, original, session=True)
    evidence["refused_status"] = status; evidence["refusal"] = rejected
    persist_evidence(evidence)
    assert status == 401, "revoked session credential reached the call path"
    return evidence
