"""Headless Blender render worker — accepts scripts via HTTP, returns rendered images."""

import json
import os
import random
import shutil
import string
import subprocess
import time
from http.server import HTTPServer, BaseHTTPRequestHandler

GENERATED_DIR = "/data/files/generated"
BLENDER_TIMEOUT = 90  # seconds (fits within CF 100s limit)


class RenderHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/health":
            self._json_response(200, {"ok": True, "service": "blender-worker"})
        else:
            self._json_response(404, {"error": "not found"})

    def do_POST(self):
        if self.path != "/render":
            self._json_response(404, {"error": "not found"})
            return

        try:
            length = int(self.headers.get("Content-Length", 0))
            body = json.loads(self.rfile.read(length))
        except (json.JSONDecodeError, ValueError):
            self._json_response(400, {"error": "invalid JSON"})
            return

        script = body.get("script", "").strip()
        if not script:
            self._json_response(400, {"error": "script required"})
            return

        # Write script to temp file
        script_path = "/tmp/scene.py"
        render_path = "/tmp/render.png"

        with open(script_path, "w") as f:
            f.write(script)

        # Clean any previous render
        if os.path.exists(render_path):
            os.remove(render_path)

        # Run Blender headless
        try:
            result = subprocess.run(
                ["blender", "--background", "--python", script_path],
                capture_output=True,
                text=True,
                timeout=BLENDER_TIMEOUT,
            )
        except subprocess.TimeoutExpired:
            self._json_response(504, {
                "success": False,
                "error": f"Blender timed out after {BLENDER_TIMEOUT}s",
            })
            return

        # Check if render was produced
        if not os.path.exists(render_path):
            self._json_response(422, {
                "success": False,
                "error": "Blender finished but no render output at /tmp/render.png",
                "stdout": result.stdout[-2000:] if result.stdout else "",
                "stderr": result.stderr[-2000:] if result.stderr else "",
            })
            return

        # Move render to shared volume with unique name
        rand = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
        filename = f"blender-{int(time.time())}-{rand}.png"
        dest = os.path.join(GENERATED_DIR, filename)

        os.makedirs(GENERATED_DIR, exist_ok=True)
        shutil.move(render_path, dest)

        self._json_response(200, {
            "success": True,
            "render_url": f"/data/files/generated/{filename}",
            "filename": filename,
        })

    def _json_response(self, status, data):
        body = json.dumps(data).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, fmt, *args):
        print(f"[blender-worker] {fmt % args}")


if __name__ == "__main__":
    server = HTTPServer(("0.0.0.0", 8810), RenderHandler)
    print("[blender-worker] listening on :8810")
    server.serve_forever()
