"""Loopback-only HTTP fixture for approved PBF download tests."""

from __future__ import annotations

import base64
import threading
from dataclasses import dataclass
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

import pytest

_FIXTURE_PATH = Path(__file__).parents[2] / "fixtures" / "pbf" / "tiny.osm.pbf.b64"


@dataclass(frozen=True, slots=True)
class PbfTestEndpoint:
    host: str
    port: int
    payload: bytes

    def url(self, name: str = "tiny.osm.pbf") -> str:
        return f"http://{self.host}:{self.port}/{name}"


class _Handler(BaseHTTPRequestHandler):
    payload = b""

    def do_GET(self) -> None:
        if self.path == "/redirect.osm.pbf":
            self.send_response(302)
            self.send_header("Location", "/tiny.osm.pbf")
            self.end_headers()
            return
        if self.path == "/corrupt.osm.pbf":
            body = b"not-a-pbf"
        elif self.path == "/tiny.osm.pbf":
            body = self.payload
        else:
            self.send_error(404)
            return

        self.send_response(200)
        self.send_header("Content-Type", "application/octet-stream")
        self.send_header("Content-Length", str(len(body)))
        self.send_header("ETag", '"synthetic-pbf-v1"')
        self.send_header("Last-Modified", "Sat, 11 Jul 2026 00:00:00 GMT")
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, format: str, *args: object) -> None:
        del format, args


@pytest.fixture
def pbf_test_endpoint() -> PbfTestEndpoint:
    payload = base64.b64decode(_FIXTURE_PATH.read_text(encoding="ascii").strip(), validate=True)
    handler = type("SyntheticPbfHandler", (_Handler,), {"payload": payload})
    server = ThreadingHTTPServer(("127.0.0.1", 0), handler)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    endpoint = PbfTestEndpoint(
        host="127.0.0.1",
        port=int(server.server_address[1]),
        payload=payload,
    )
    try:
        yield endpoint
    finally:
        server.shutdown()
        server.server_close()
        thread.join(timeout=5)
