"""Synthetic HTTP example. Python 3 standard library; loopback only.

No Kubernetes cluster, Argo CD installation, cloud account, or credentials.
Two local servers model an application and a dependency; neither is public.
No files are written. Servers are stopped before this script exits.
"""
from contextlib import contextmanager
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from threading import Thread
from urllib.error import HTTPError
from urllib.request import ProxyHandler, build_opener


def request(url):
    # Do not send local example traffic through a configured HTTP proxy.
    opener = build_opener(ProxyHandler({}))
    try:
        response = opener.open(url, timeout=5)
    except HTTPError as error:
        response = error
    with response:
        return response.status, response.read().decode("utf-8")


class QuietHandler(BaseHTTPRequestHandler):
    def log_message(self, *args):
        pass

    def reply(self, status, body):
        payload = body.encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.send_header("Content-Length", str(len(payload)))
        self.end_headers()
        self.wfile.write(payload)


class Dependency(QuietHandler):
    def do_GET(self):
        self.reply(403, "AccessDenied")


@contextmanager
def running(handler):
    server = ThreadingHTTPServer(("127.0.0.1", 0), handler)
    thread = Thread(target=server.serve_forever, daemon=True)
    thread.start()
    try:
        yield "http://127.0.0.1:" + str(server.server_port)
    finally:
        server.shutdown()
        server.server_close()
        thread.join()


def main():
    with running(Dependency) as dependency:
        class Application(QuietHandler):
            def do_GET(self):
                if self.path == "/ready":
                    self.reply(200, "ready")
                elif self.path == "/report":
                    status, _ = request(dependency + "/records")
                    self.reply(200 if status == 200 else 503,
                               "report" if status == 200 else "dependency denied access")
                else:
                    self.reply(404, "not found")

        with running(Application) as application:
            for label, url, expected in [
                ("GET /ready", application + "/ready", 200),
                ("Dependency GET /records", dependency + "/records", 403),
                ("GET /report", application + "/report", 503),
            ]:
                status, body = request(url)
                assert status == expected, (label, status, body)
                print(f"{label}: {status} {body}")
    print("Result: readiness passed; the business request failed")


if __name__ == "__main__":
    main()
