#!/usr/bin/env python3
"""
Minimal backend for Circuit Builder UI.
Serves the static UI and runs entropyk-cli validate/run on POST.
Run from repository root: python tools/circuit-builder-ui/server.py
Then open http://localhost:8765
"""

import json
import os
import subprocess
import tempfile
from http.server import HTTPServer, BaseHTTPRequestHandler
from pathlib import Path
from urllib.parse import parse_qs, urlparse

PORT = 8765
# Path to entropyk-cli from repo root (run server from repo root)
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
CLI_PATH = REPO_ROOT / "target" / "release" / "entropyk-cli"
UI_DIR = Path(__file__).resolve().parent


def run_cli(subcommand, config_json_str, run_output=None):
    """Run entropyk-cli validate or run; config_json_str written to temp file."""
    if not CLI_PATH.exists():
        return False, f"CLI not found. Build first: cargo build --release -p entropyk-cli\nExpected: {CLI_PATH}", ""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
        f.write(config_json_str)
        tmp_path = f.name
    try:
        cmd = [str(CLI_PATH), subcommand, "--config", tmp_path]
        if run_output is not None:
            cmd.extend(["-o", run_output])
        r = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=60,
            cwd=str(REPO_ROOT),
        )
        stdout = r.stdout or ""
        stderr = r.stderr or ""
        if r.returncode != 0:
            return False, stdout or stderr or f"Exit code {r.returncode}", stderr
        return True, stdout, stderr
    except subprocess.TimeoutExpired:
        return False, "Timeout (60s)", ""
    except Exception as e:
        return False, str(e), ""
    finally:
        try:
            os.unlink(tmp_path)
        except Exception:
            pass


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        path = urlparse(self.path).path
        if path == "/" or path == "/index.html":
            self.serve_file(UI_DIR / "index.html", "text/html")
        elif path == "/examples/simple_working.json":
            self.serve_file(REPO_ROOT / "crates" / "cli" / "examples" / "simple_working.json", "application/json")
        elif path == "/examples/chiller_r410a_minimal.json":
            self.serve_file(REPO_ROOT / "crates" / "cli" / "examples" / "chiller_r410a_minimal.json", "application/json")
        else:
            self.send_error(404)

    def serve_file(self, filepath, content_type):
        try:
            with open(filepath, "rb") as f:
                data = f.read()
        except FileNotFoundError:
            self.send_error(404)
            return
        self.send_response(200)
        self.send_header("Content-Type", content_type)
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    def do_POST(self):
        path = urlparse(self.path).path
        if path != "/validate" and path != "/run":
            self.send_error(404)
            return
        content_len = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(content_len)
        try:
            config_str = body.decode("utf-8")
            json.loads(config_str)
        except Exception as e:
            self.send_json(400, {"ok": False, "error": f"Invalid JSON: {e}"})
            return
        if path == "/validate":
            ok, out, err = run_cli("validate", config_str)
        else:
            ok, out, err = run_cli("run", config_str, run_output=os.path.devnull)
        self.send_json(200, {"ok": ok, "stdout": out, "stderr": err})

    def send_json(self, status, obj):
        body = json.dumps(obj).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, format, *args):
        print(f"[{self.log_date_time_string()}] {format % args}")


def main():
    os.chdir(REPO_ROOT)
    print(f"Entropyk Circuit Builder UI")
    print(f"  UI:    http://localhost:{PORT}/")
    print(f"  CLI:   {CLI_PATH} {'(found)' if CLI_PATH.exists() else '(not found — run: cargo build --release -p entropyk-cli)'}")
    print(f"  Root:  {REPO_ROOT}")
    server = HTTPServer(("", PORT), Handler)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\nBye.")
    server.server_close()


if __name__ == "__main__":
    main()
