"""Local end-to-end checks; no external service or fixed port required."""
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import time
from threading import Thread

client = Path(__file__).with_name("fetch_cached.py")
state = {"etag": 'W/"v1"', "body": b'{"count": 1}', "mode": "normal"}
seen = []


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        validator = self.headers.get("If-None-Match")
        seen.append(validator)
        mode = state["mode"]
        if mode == "slow":
            time.sleep(0.2)
        if mode == "error":
            self.send_response(503)
            self.end_headers()
            return
        if mode == "unexpected304" or (mode == "normal" and validator == state["etag"]):
            self.send_response(304)
            self.end_headers()
            return
        body = b'not json' if mode == "badjson" else state["body"]
        if mode == "large":
            body = b' ' * (1024 * 1024 + 1)
        self.send_response(200)
        if mode != "noetag":
            self.send_header("ETag", state["etag"])
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        try:
            self.wfile.write(body)
        except (BrokenPipeError, ConnectionResetError):
            pass

    def log_message(self, *args):
        pass


server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
thread = Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
    with tempfile.TemporaryDirectory(prefix="etag-check-") as directory:
        cache = Path(directory) / "cache.json"
        url = f"http://127.0.0.1:{server.server_port}/data"
        env = dict(os.environ, no_proxy="127.0.0.1", NO_PROXY="127.0.0.1")

        def run(expected, status=None, path=cache, extra=()):
            result = subprocess.run(
                [sys.executable, str(client), url, str(path), *extra],
                capture_output=True, text=True, env=env, timeout=15,
            )
            assert result.returncode == expected, result
            if status is not None:
                report = json.loads(result.stdout)
                assert report == {"status": status, "data": json.loads(state["body"])}, report
                assert not result.stderr, result
            else:
                assert not result.stdout and result.stderr, result
            return result

        run(0, "updated")
        assert seen[-1] is None
        assert json.loads(cache.read_text())["etag"] == 'W/"v1"'
        before = cache.read_bytes(), cache.stat().st_mtime_ns
        run(0, "not_modified")
        assert seen[-1] == 'W/"v1"'
        assert (cache.read_bytes(), cache.stat().st_mtime_ns) == before
        print("PASS: 200 stores; 304 reuses without rewriting; weak ETag preserved")

        state.update(etag='"v2"', body=b'{"count": 2}')
        run(0, "updated")
        assert seen[-1] == 'W/"v1"'
        assert json.loads(cache.read_text())["etag"] == '"v2"'
        print("PASS: changed ETag replaces data and validator together")

        before = cache.read_bytes()
        for mode in ("error", "badjson", "large"):
            state["mode"] = mode
            run(1)
            assert cache.read_bytes() == before
        state["mode"] = "slow"
        run(1, extra=("--timeout", "0.05"))
        assert cache.read_bytes() == before
        print("PASS: 503, invalid JSON, oversized body, timeout preserve old cache")

        state["mode"] = "noetag"
        run(0, "updated")
        assert json.loads(cache.read_text())["etag"] is None
        run(0, "updated")
        assert seen[-1] is None
        print("PASS: no ETag means another unconditional GET")

        state["mode"] = "unexpected304"
        missing = Path(directory) / "missing.json"
        run(1, path=missing)
        assert not missing.exists()
        print("PASS: unsolicited 304 fails without creating a cache")

        state["mode"] = "normal"
        cache.write_text('{broken', encoding="utf-8")
        count = len(seen)
        run(1)
        assert len(seen) == count and cache.read_text() == '{broken'
        cache.write_text('{"url":"other","etag":null,"data":1}', encoding="utf-8")
        run(1)
        assert len(seen) == count
        run(2, extra=("--timeout", "0"))
        print("PASS: corrupt cache, URL mismatch, invalid timeout rejected")
finally:
    server.shutdown()
    server.server_close()
    thread.join()
print("OK: all conditional-fetch checks passed")
