# shellcheck shell=dash

# GitHub / GitLab / Codeberg Release API client

___x_cmd_eget_api_release(){
    local forge="$1" owner="$2" repo="$3" tag="$4" pre_release="$5" source="$6"

    local base_url
    case "$forge" in
        codeberg)   base_url="https://codeberg.org/api/v1" ;;
        gitlab)     base_url="https://gitlab.com/api/v4" ;;
        github|*)   base_url="https://api.github.com" ;;
    esac

    local token=""
    case "$forge" in
        codeberg)   token="${EGET_CODEBERG_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
        gitlab)     token="${EGET_GITLAB_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
        github|*)   token="${EGET_GITHUB_TOKEN:-${GITHUB_TOKEN:-}}" ;;
    esac

    if [ "$source" = "1" ]; then
        ___x_cmd_eget_api_source "$base_url" "$owner" "$repo" "$tag" "$token" "$forge"
        return
    fi

    if [ "$forge" = "gitlab" ]; then
        local project_id
        project_id="$( printf "%s/%s" "$owner" "$repo" | ___x_cmd_cmds jq -sRr @uri )"
        if [ -n "$tag" ]; then
            ___x_cmd_eget_api_curl "$base_url/projects/$project_id/releases/$tag" "$token"
        else
            local releases_json
            releases_json="$( ___x_cmd_eget_api_curl "$base_url/projects/$project_id/releases?per_page=10" "$token" )" || return
            printf "%s" "$releases_json" | ___x_cmd_cmds jq -r '.[0]'
        fi
    else
        if [ -n "$tag" ]; then
            ___x_cmd_eget_api_curl "$base_url/repos/$owner/$repo/releases/tags/$tag" "$token"
        else
            local releases_json
            releases_json="$( ___x_cmd_eget_api_curl "$base_url/repos/$owner/$repo/releases?per_page=10" "$token" )" || return
            if [ "$pre_release" = "1" ]; then
                printf "%s" "$releases_json" | ___x_cmd_cmds jq -r '.[0]'
            else
                printf "%s" "$releases_json" | ___x_cmd_cmds jq -r '[ .[] | select(.prerelease != true) ][0]'
            fi
        fi
    fi
}

___x_cmd_eget_api_source(){
    local base_url="$1" owner="$2" repo="$3" tag="$4" token="$5"

    if [ -n "$tag" ]; then
        local ref="tags/$tag"
    else
        local ref="latest"
    fi

    case "$base_url" in
        *github*)
            printf '{"tag_name":"%s","assets":[{"name":"source.tar.gz","browser_download_url":"%s/repos/%s/%s/tarball/%s"}]}' \
                "${tag:-latest}" "$base_url" "$owner" "$repo" "$ref" | ___x_cmd_cmds jq .
            ;;
        *codeberg*)
            printf '{"tag_name":"%s","assets":[{"name":"source.tar.gz","browser_download_url":"%s/repos/%s/%s/archive/%s.tar.gz"}]}' \
                "${tag:-latest}" "$base_url" "$owner" "$repo" "$ref" | ___x_cmd_cmds jq .
            ;;
        *gitlab*)
            printf '{"tag_name":"%s","assets":[{"name":"source.tar.gz","browser_download_url":"https://gitlab.com/%s/%s/-/archive/%s/%s-%s.tar.gz"}]}' \
                "${tag:-latest}" "$owner" "$repo" "$ref" "$repo" "${tag:-latest}" | ___x_cmd_cmds jq .
            ;;
    esac
}

___x_cmd_eget_api_curl(){
    local url="$1" token="$2"
    local ssl_opts=""
    [ "$___X_CMD_EGET_DISABLE_SSL" = "1" ] && ssl_opts="-k"

    local auth_opts=""
    if [ -n "$token" ]; then
        auth_opts="-H \"Authorization: Bearer $token\""
    fi

    # Cache API responses for 10 minutes
    if [ "$___X_CMD_EGET_UPDATE" != "1" ] && [ "$___X_CMD_EGET_NO_CCMD" != "1" ]; then
        eval "x ccmd 10m -- curl -sS -L -f $ssl_opts $auth_opts \"$url\"" 2>/dev/null && return $?
    fi

    eval "___x_cmd_cmds curl -sS -L -f $ssl_opts $auth_opts \"$url\""
}

# Apply ___X_CMD_GHPROXY_ENDPOINT to a github.com download URL.
# Auto-detects two endpoint shapes:
#   - prefix mode:  ENDPOINT="https://ghproxy.com"        -> https://ghproxy.com/https://github.com/...
#   - replace mode: ENDPOINT="https://gh-proxy.com/github.com" -> https://gh-proxy.com/github.com/...
# Non-github URLs and unset endpoints are returned unchanged. Sets x_.
___x_cmd_eget_api___ghproxy_(){
    local url="$1"
    local endpoint="${___X_CMD_GHPROXY_ENDPOINT:-}"
    x_="$url"

    [ -z "$endpoint" ] && return 1
    case "$url" in
        https://github.com/*|http://github.com/*) ;;
        *) return 1 ;;
    esac

    local ep="${endpoint%/}"
    [ -z "$ep" ] && return 1

    case "$ep" in
        */github.com)
            local path="${url#https://github.com}"
            path="${path#http://github.com}"
            x_="${ep}${path}"
            ;;
        *)
            x_="${ep}/${url}"
            ;;
    esac
}

___x_cmd_eget_api_download(){
    local url="$1" outfile="$2"
    local ssl_opts=""
    [ "$___X_CMD_EGET_DISABLE_SSL" = "1" ] && ssl_opts="-k"

    local token=""
    case "$url" in
        *github*)   token="${EGET_GITHUB_TOKEN:-${GITHUB_TOKEN:-}}" ;;
        *codeberg*) token="${EGET_CODEBERG_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
        *gitlab*)   token="${EGET_GITLAB_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
    esac

    local auth_opts=""
    if [ -n "$token" ]; then
        auth_opts="-H \"Authorization: Bearer $token\""
    fi

    local fetch_url="$url"
    ___x_cmd_eget_api___ghproxy_ "$url"
    if [ "$x_" != "$url" ]; then
        fetch_url="$x_"
        [ "$___X_CMD_EGET_QUIET" = "0" ] && eget:info "Using GHPROXY: $fetch_url"
    fi

    ___x_cmd mkdirp "$(dirname "$outfile")"
    [ "$___X_CMD_EGET_QUIET" = "0" ] && eget:info --url "$fetch_url" "Downloading $(basename "$outfile")"
    eval "___x_cmd_cmds curl -sS -L -f $ssl_opts -o \"$outfile\" $auth_opts \"$fetch_url\""
}

___x_cmd_eget_api_list_releases(){
    local forge="$1" owner="$2" repo="$3" limit="${4:-20}"

    local base_url token
    case "$forge" in
        codeberg)   base_url="https://codeberg.org/api/v1" ;;
        gitlab)     base_url="https://gitlab.com/api/v4" ;;
        github|*)   base_url="https://api.github.com" ;;
    esac
    case "$forge" in
        codeberg)   token="${EGET_CODEBERG_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
        gitlab)     token="${EGET_GITLAB_TOKEN:-${EGET_FORGE_TOKEN:-}}" ;;
        github|*)   token="${EGET_GITHUB_TOKEN:-${GITHUB_TOKEN:-}}" ;;
    esac

    if [ "$forge" = "gitlab" ]; then
        local project_id
        project_id="$( printf "%s/%s" "$owner" "$repo" | ___x_cmd_cmds jq -sRr @uri )"
        ___x_cmd_eget_api_curl "$base_url/projects/$project_id/releases?per_page=$limit" "$token"
    else
        ___x_cmd_eget_api_curl "$base_url/repos/$owner/$repo/releases?per_page=$limit" "$token"
    fi
}

___x_cmd_eget_api_rate(){
    case "${1:-}" in -h|--help) ___x_cmd help -m eget rate; return 0 ;; esac
    local forge="${1:-github}"
    case "$forge" in
        gh)  forge="github" ;;
    esac

    # Only GitHub exposes a public /rate_limit endpoint that returns
    # the per-token counters in the body. GitLab and Codeberg (Gitea)
    # report rate-limit info only via HTTP headers on each request —
    # there is no standalone query endpoint, so we don't support them.
    if [ "$forge" != "github" ]; then
        N=eget M="rate: only GitHub is supported (GitLab / Codeberg expose rate limits only via HTTP headers, no query endpoint)" log:ret:64
        return
    fi

    local token="${EGET_GITHUB_TOKEN:-${GITHUB_TOKEN:-}}"
    local auth_opts=""
    [ -n "$token" ] && auth_opts="-H \"Authorization: Bearer $token\""

    local resp
    resp="$( eval "___x_cmd_cmds curl -sS -L -f $auth_opts \"https://api.github.com/rate_limit\"" )" || {
        N=eget M="rate: failed to fetch from api.github.com" log:ret:1
        return
    }
    printf "%s" "$resp" | ___x_cmd_cmds jq -r '.resources.core | "Rate limit: \(.remaining)/\(.limit) (resets at \(.reset | todate))"' 2>/dev/null || \
        printf "Unable to fetch rate limit info\n"
}
