"""External HTTPS read-only probe for the active-work security halt walkthrough."""

import argparse
from datetime import datetime, timezone
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
import os
from pathlib import Path
import ssl
import threading
import time
from uuid import UUID


class Evidence:
    def __init__(self, directory, run_id):
        self.run_id = str(UUID(run_id))
        self.directory = Path(directory) / self.run_id
        self.directory.mkdir(mode=0o700, parents=True, exist_ok=False)
        self.lock = threading.Lock()
        self.counts = {}

    def record(self, phase):
        with self.lock:
            self.counts[phase] = self.counts.get(phase, 0) + 1
            event = {"run_id": self.run_id, "phase": phase, "count": self.counts[phase],
                     "observed_at": datetime.now(timezone.utc).isoformat()}
            text = json.dumps(event) + "\n"
            with (self.directory / "events.jsonl").open("a") as log:
                log.write(text)
                log.flush()
                os.fsync(log.fileno())
            # Publish complete markers atomically so the waiting operator cannot read half a JSON object.
            temporary = self.directory / f"{phase}.tmp"
            temporary.write_text(text)
            temporary.replace(self.directory / f"{phase}.json")
            print(text, end="", flush=True)


class ProbeHandler(BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        # Only bounded phase records are logged; URLs, headers and client data are excluded.
        pass

    def do_GET(self):
        evidence = self.server.evidence
        if self.path == f"/hold/{evidence.run_id}":
            phase = "hold"
        elif self.path == f"/after/{evidence.run_id}":
            phase = "after"
        else:
            self.send_error(404)
            return
        evidence.record(f"{phase}-received")
        if phase == "hold":
            time.sleep(self.server.hold_seconds)
        body = json.dumps({"probe": phase, "run_id": evidence.run_id}).encode("utf-8")
        evidence.record(f"{phase}-response-attempted")
        try:
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.send_header("Cache-Control", "no-store")
            self.end_headers()
            self.wfile.write(body)
            self.wfile.flush()
        except (BrokenPipeError, ConnectionResetError, ssl.SSLEOFError):
            evidence.record(f"{phase}-client-disconnected")
        else:
            # A successful local write does not prove the agent received or persisted the response.
            evidence.record(f"{phase}-response-written")


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--run-id", required=True)
    parser.add_argument("--evidence-dir", required=True, type=Path)
    parser.add_argument("--cert-file", required=True)
    parser.add_argument("--key-file", required=True)
    parser.add_argument("--host", default="127.0.0.1")
    parser.add_argument("--port", type=int, default=8443)
    parser.add_argument("--hold-seconds", type=int, choices=range(1, 13), default=10)
    args = parser.parse_args()
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    context.load_cert_chain(args.cert_file, args.key_file)
    evidence = Evidence(args.evidence_dir, args.run_id)
    with ThreadingHTTPServer((args.host, args.port), ProbeHandler) as server:
        server.evidence = evidence
        server.hold_seconds = args.hold_seconds
        server.socket = context.wrap_socket(server.socket, server_side=True)
        print(json.dumps({"ready": True, "run_id": evidence.run_id,
                          "evidence_directory": str(evidence.directory)}), flush=True)
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            pass


if __name__ == "__main__":
    main()
