# Git Board — Starlark Backend (v0.2.0)
#
# Library consumer — delegates all Gitea API work to gitea-client.
#
# Entry points:
#   on_request(req)              → surface API routes
#   on_tool_call(tool_name, params) → LLM tool execution
#
# Modules:
#   connections — resolve gitea connection (connections.read)
#   lib         — load gitea-client library
#   json        — encode/decode (universal)
#   settings    — user: default_owner, default_repo

gitea = lib.require("gitea-client")


def _conn():
    """Resolve the first available gitea connection."""
    return connections.get("gitea")


# ═══════════════════════════════════════════════
#  Surface API routes (/s/git-board/api/*)
# ═══════════════════════════════════════════════

def on_request(req):
    path   = req["path"]
    method = req["method"]

    conn = _conn()
    if conn == None:
        return _resp(400, {"error": "no gitea connection configured — add one in Settings > Connections"})

    if method == "GET" and path == "/repos":
        return _handle_repos(conn)
    elif method == "GET" and path == "/board":
        return _handle_board(conn, req)
    elif method == "GET" and path.startswith("/issue/"):
        return _handle_get_issue(conn, path[len("/issue/"):])
    elif method == "POST" and path.startswith("/issue/"):
        return _handle_post_issue(conn, path[len("/issue/"):], req)
    elif method == "GET" and path.startswith("/ci/"):
        return _handle_ci(conn, path[len("/ci/"):])

    return _resp(404, {"error": "not found"})


def _handle_repos(conn):
    """List repositories accessible via the connection."""
    repos = gitea.get_repos(conn)
    if repos == None:
        return _resp(502, {"error": "gitea request failed"})
    return _resp(200, {"data": repos})


def _handle_board(conn, req):
    """Combined issues + PRs for kanban board."""
    q = req.get("query", {})
    owner = _str(q.get("owner", "")) or settings.get("default_owner") or ""
    repo  = _str(q.get("repo", ""))  or settings.get("default_repo")  or ""
    if not owner or not repo:
        return _resp(400, {"error": "owner and repo required (query params or user settings)"})

    issues = gitea.get_issues(conn, owner, repo, "open") or []
    prs    = gitea.get_prs(conn, owner, repo, "open")    or []

    board = {"issues": issues, "pull_requests": prs}
    return _resp(200, board)


def _handle_get_issue(conn, issue_path):
    """Get issue detail: /issue/:owner/:repo/:number"""
    parts = issue_path.split("/", 2)
    if len(parts) < 3:
        return _resp(400, {"error": "path must be /issue/:owner/:repo/:number"})
    owner, repo, num = parts[0], parts[1], int(parts[2])
    data = gitea.get_issue(conn, owner, repo, num)
    if data == None:
        return _resp(404, {"error": "issue not found"})
    return _resp(200, data)


def _handle_post_issue(conn, issue_path, req):
    """Update issue or add comment: /issue/:owner/:repo/:number[/comment]"""
    parts = issue_path.split("/", 3)
    if len(parts) < 3:
        return _resp(400, {"error": "path must be /issue/:owner/:repo/:number"})
    owner, repo, num = parts[0], parts[1], int(parts[2])
    action = parts[3] if len(parts) > 3 else ""

    body = json.decode(req.get("body", "{}"))

    if action == "comment":
        text = body.get("body", "")
        if not text:
            return _resp(400, {"error": "comment body required"})
        result = gitea.add_comment(conn, owner, repo, num, text)
        if result == None:
            return _resp(502, {"error": "failed to add comment"})
        return _resp(201, result)

    # Default: update issue fields (state, title, body, assignee)
    title = body.get("title", "")
    issue_body = body.get("body", "")
    state = body.get("state", "")
    result = gitea.update_issue(conn, owner, repo, num, title, issue_body, state)
    if result == None:
        return _resp(502, {"error": "failed to update issue"})
    return _resp(200, result)


def _handle_ci(conn, ref_path):
    """CI status for owner/repo/ref."""
    parts = ref_path.split("/", 2)
    if len(parts) < 3:
        return _resp(400, {"error": "path must be /ci/:owner/:repo/:ref"})
    owner, repo, ref = parts[0], parts[1], parts[2]
    result = gitea.get_ci_status(conn, owner, repo, ref)
    if result == None:
        return _resp(502, {"error": "CI status request failed"})
    return _resp(200, result)


# ═══════════════════════════════════════════════
#  LLM Tools (called by AI during chat)
# ═══════════════════════════════════════════════

def on_tool_call(tool_name, params):
    conn = _conn()
    if conn == None:
        return {"error": "no gitea connection configured — add one in Settings > Connections"}

    owner = params.get("owner", "")
    repo  = params.get("repo", "")

    if tool_name == "list_issues":
        state = params.get("state", "open")
        data = gitea.get_issues(conn, owner, repo, state)
        if data == None:
            return {"error": "failed to list issues"}
        return {"issues": data, "count": len(data)}

    elif tool_name == "get_issue":
        num = int(params.get("number", 0))
        data = gitea.get_issue(conn, owner, repo, num)
        if data == None:
            return {"error": "issue not found"}
        return data

    elif tool_name == "create_issue":
        data = gitea.create_issue(conn, owner, repo,
                                  params.get("title", ""),
                                  params.get("body", ""),
                                  params.get("labels", ""))
        if data == None:
            return {"error": "failed to create issue"}
        return data

    elif tool_name == "update_issue":
        num = int(params.get("number", 0))
        data = gitea.update_issue(conn, owner, repo, num,
                                  params.get("title", ""),
                                  params.get("body", ""),
                                  params.get("state", ""))
        if data == None:
            return {"error": "failed to update issue"}
        return data

    elif tool_name == "add_comment":
        num = int(params.get("number", 0))
        data = gitea.add_comment(conn, owner, repo, num, params.get("body", ""))
        if data == None:
            return {"error": "failed to add comment"}
        return data

    elif tool_name == "list_pull_requests":
        state = params.get("state", "open")
        data = gitea.get_prs(conn, owner, repo, state)
        if data == None:
            return {"error": "failed to list PRs"}
        return {"pull_requests": data, "count": len(data)}

    elif tool_name == "get_ci_status":
        ref = params.get("ref", "")
        data = gitea.get_ci_status(conn, owner, repo, ref)
        if data == None:
            return {"error": "failed to get CI status"}
        return data

    return {"error": "unknown tool: " + tool_name}


# ═══════════════════════════════════════════════
#  Response helpers
# ═══════════════════════════════════════════════

def _resp(status, data):
    return {"status": status, "body": json.encode(data), "headers": {"Content-Type": "application/json"}}

def _str(v):
    """Coerce Starlark query param to string."""
    if v == None:
        return ""
    return str(v)
