from pathlib import Path
from urllib.parse import urlencode
from urllib.request import Request, urlopen
import json

from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles

app = FastAPI(title="格士立青岛出口本体接口")

ROOT = Path(__file__).resolve().parents[1]
QUERIES = ROOT / "queries"
STATIC = ROOT / "app" / "static"
FUSEKI_ENDPOINT = "http://localhost:3030/gesli/sparql"

app.mount("/static", StaticFiles(directory=STATIC), name="static")


@app.get("/health")
def health():
    return {"status": "ok"}


@app.get("/")
def index():
    return FileResponse(STATIC / "index.html")


@app.get("/api/orders")
def orders():
    return query_file("order-status.rq")


@app.get("/api/risks")
def risks():
    return query_file("risk-orders.rq")


@app.get("/api/flow")
def flow():
    return query_file("operation-flow.rq")


@app.get("/api/node-times")
def node_times():
    return query_file("node-time-status.rq")


@app.get("/api/order-cutoffs")
def order_cutoffs():
    return query_file("order-cutoff-times.rq")


@app.get("/api/exception-map")
def exception_map():
    return query_file("exception-risk-map.rq")


def query_file(filename: str):
    path = QUERIES / filename
    if not path.exists():
        raise HTTPException(status_code=404, detail=f"Query file not found: {filename}")
    return run_sparql(path.read_text(encoding="utf-8"))


def run_sparql(query: str):
    data = urlencode({"query": query}).encode("utf-8")
    request = Request(
        FUSEKI_ENDPOINT,
        data=data,
        headers={
            "Accept": "application/sparql-results+json",
            "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
        },
        method="POST",
    )

    try:
        with urlopen(request, timeout=10) as response:
            payload = json.loads(response.read().decode("utf-8"))
    except Exception as exc:
        raise HTTPException(
            status_code=502,
            detail="无法连接 Fuseki。请确认 Docker 和 http://localhost:3030/gesli/sparql 正常运行。",
        ) from exc

    variables = payload.get("head", {}).get("vars", [])
    rows = []
    for binding in payload.get("results", {}).get("bindings", []):
        rows.append({
            variable: binding.get(variable, {}).get("value", "")
            for variable in variables
        })
    return {"rows": rows}
