# shellcheck shell=sh
# shellcheck disable=SC2039,3043,SC2120
# shellcheck disable=SC2046

# Section: Help
_____x_cmd_gh_help__token_setting(){
    printf "\n%s %s \n%s\n" \
        "$(___x_cmd_ui yellow 'Run command to add|repleace token:')" \
        "$(___x_cmd_ui bold cyan "\`x gh --cfg token=<token>\`")"   \
        "$(___x_cmd_ui "$(___x_cmd_gh___get_web_endpoint)/settings/tokens")"
}

_____x_cmd_gh_help__owner_setting(){
    printf "|\n    %s %s\n    %s %s\n" \
        "$(___x_cmd_ui yellow 'Run current command to setup default owner in the current session:')" \
        "$(___x_cmd_ui bold cyan "\`x gh --cur owner=<owner>\`")" \
        "$(___x_cmd_ui yellow 'Run config  command to save default owner to local configure file:')" \
        "$(___x_cmd_ui bold cyan "\`x gh --cfg owner=<owner>\`")"
}

_____x_cmd_gh_help(){
    ___x_cmd help -m gh "$@" 1>&2
    return 1
}

# EndSection

# Section: HTTP header & body & request
___x_cmd_gh_resp_header() {
    local fp="$___X_CMD_GH_TMP/.____x_cmd_gh_curl_header.$$"
    [ -f "$fp" ] || return
    if [ "$#" -le 0 ]; then
        x rat "$fp"
    else
        ___x_cmd_cmds_awk '
            ( match($0, "page=[0-9]+&per_page=[0-9]+>") ){
                GH_MATCH_LINK = 1
                amount = substr($0, RSTART, RLENGTH-1)
                split(amount, _, "&")
                split(_[1], arr1, "=")
                split(_[2], arr2, "=")
                page_num = arr1[2]
                per_page_num = arr2[2]
                printf("%d\n", int(page_num - 1) * int(per_page_num) + 1)
            }
            END{
                if (GH_MATCH_LINK == 0) printf("%s\n" , "1")
            }
        ' <"$fp"
    fi
}

___x_cmd_gh_resp_code(){
    ___x_cmd_gh_resp_header | _____x_cmd_gx_get_resp_code_by_header
}

___x_cmd_gh_curl(){
    local op="$1"
    local _api_url="$2"
    shift 2
    local ___X_CMD_API_GH_HEADER="-s -H \"Accept:application/vnd.github.v3+json\" -D \"$___X_CMD_GH_TMP/.____x_cmd_gh_curl_header.$$\""

    local ___X_CMD_API_GH_TOKEN=""; local _curl_endpoint_tmp="";
    ___x_cmd_gh_cur    ___X_CMD_API_GH_TOKEN:=token   _curl_endpoint_tmp:=endpoint 2>/dev/null
    local ___X_CMD_API_GH_ENDPOINT="${___X_CMD_API_GH_ENDPOINT:-"$_curl_endpoint_tmp"}"

    local ___X_CMD_GH_SHOW_HTTP_CODE=1
    case "$op" in
         get)
            if [ -n "$NO_CACHE" ]; then
                ___x_cmd_api_gh get "$_api_url" $(eval "printf '%s ' $(x curl gencode $(___x_cmd_gh_curl___use_query_data "$@"))")
            else
                x ccmd 10s --        eval "___X_CMD_API_GH_ENDPOINT=$___X_CMD_API_GH_ENDPOINT ___X_CMD_API_GH_TOKEN=$___X_CMD_API_GH_TOKEN ___x_cmd_api_gh get \"$_api_url\" $(eval "printf '%s ' $(x curl gencode $(___x_cmd_gh_curl___use_query_data "$@"))")"
            fi
            ___x_cmd_gh_http_error   eval "___X_CMD_API_GH_ENDPOINT=$___X_CMD_API_GH_ENDPOINT ___X_CMD_API_GH_TOKEN=$___X_CMD_API_GH_TOKEN ___x_cmd_api_gh get \"$_api_url\" $(eval "printf '%s ' $(x curl gencode $(___x_cmd_gh_curl___use_query_data "$@"))")"
            ;;
        post|put|patch|del)
            ___x_cmd_api_gh "$op" "$_api_url" "$(x curl gencode "$@")"
            ___x_cmd_gh_http_error
            ;;
        download)
            [ -n "$1" ] || M='Please provide output dir' arg:ret:64
            local __out="$1"
            case "$__out" in
                */*)   x mkdirp "${__out%/*}"  ;;
                *)     __out="./${__out}"      ;;
            esac
            ___X_CMD_API_GH_HEADER="-L -# -H \"accept: application/vnd.github+json\" -D \"$___X_CMD_GH_TMP/.____x_cmd_gh_curl_header.$$\""
            ___x_cmd_api_gh "${___X_CMD_GH_DOWNLOAD_REQ_METHOD:-"get"}" "$_api_url" -o "\"$__out\""
            if ! ___x_cmd_gh_http_error; then
                (
                    ___x_cmd_cmds_cat "$__out" 2>/dev/null | x jo env . gh_resp_msg=.message gh_resp_err=.errors
                    ___x_cmd_ui_tf false "Download failure:" >&2
                    ___x_cmd_gh____handle_resp
                    return 1
                )
            fi
            ;;
        upload)
            [ -n "$1" ] || M='Please provide upload filepath' arg:ret:64
            local __file_path="$1"; shift;
            local __file_type="\"Content-Type: ${file_type:-"octet-stream"}\""
            ___X_CMD_API_GH_HEADER="-L -# -H \"accept: application/vnd.github.v3+json\" -D \"$___X_CMD_GH_TMP/.____x_cmd_gh_curl_header.$$\" -H ${__file_type}"
            [ -f "$__file_path" ] || {
                gh:error "Upload Failure. Not found target file. Please check file exist $__file_path"
                return 1
            }
            gh:info "Uploading file $1..."
            ___x_cmd_api_gh "${___X_CMD_GH_UPLOAD_REQ_METHOD:-"post"}" "$_api_url" -T "\"$__file_path\""
            ___x_cmd_gh_http_error
            ;;
    esac
}

# shellcheck disable=SC2154
___x_cmd_gh_curl___use_query_data(){
    [ $# -gt 0 ] || return
    printf "%s " "-G"
    local name=""
    for name in "$@"; do
        case "$name" in
            p)          [ -z "$p" ]   || printf "%s " "path==$p"    ;;
            sta)        [ -z "$sta" ] || printf "%s " "status==$sta";;
            *)                           printf "%s " "$name=="     ;;
        esac
    done
}

___x_cmd_gh_http_error(){
    if [ "$op" = get ] && [ -n "$___X_CMD_CCMD_AGE" ] && [ "$___X_CMD_CCMD_AGE" -ne -1 ]; then
        gh:debug "Is cache data"
        return 0
    fi
    local http_resp_code=""
    http_resp_code=$(___x_cmd_gh_resp_code)
    if [ -n "$http_resp_code" ] && [ "$http_resp_code" -ge 200 ] && [ "$http_resp_code" -le 303 ]; then
        return 0
    else
        [ $# -eq 0 ] || {
            gh:debug "Cache Clear"
            x ccmd invalidate "$@" 1>/dev/null 2>&1
        }
        [ -z "$___X_CMD_GH_SHOW_HTTP_CODE" ] || {
            gh:error "HTTP Code is $http_resp_code"
            if command -v unset 1>/dev/null; then
                unset ___X_CMD_GH_SHOW_HTTP_CODE
            fi
        }
        return 1
    fi
}

___x_cmd_gh____handle_resp(){
    [ -z "$gh_resp_msg" ] || ___x_cmd_gx_printf_error "$gh_resp_msg"
    [ -z "$gh_resp_err" ] || ___x_cmd_gx_printf_error "$gh_resp_err"
}
# EndSection

# Section: Resolve pagination

___x_cmd_gh_st_tab(){
    if ___x_cmd_is_stdout2tty && ___x_cmd_runmode_allow_chatty; then
        x csv static_tab "$@"
    else
        x csv static_tab
    fi
}

___x_cmd_gh_get_multi() {
    if [ -n "$page" ] || [ -n "$per_page" ]; then
        ___x_cmd_gh_curl get "$@" page per_page
        return
    fi

    local page=1
    local per_page=100
    local NO_CACHE=1
    if [ -n "$json" ] || [ -n "$ENFORCE_JSON" ]; then
        ___x_cmd_gh_get_multi___json_prt "$@"
    else
        ___x_cmd_gh_get_multi___ui_table "$@"
    fi

}
___x_cmd_gh_get_multi___ui_table(){
    ___x_cmd_gh_curl get "$@" page per_page
    printf "\n"
    local next_url=""
    _____x_cmd_gh_next_url
    [ -n "$next_url" ] || return

    while [ -n "$next_url" ]; do
        ___x_cmd_gh_curl get "$next_url" || return
        printf "\n"
        _____x_cmd_gh_next_url
    done
}

___x_cmd_gh_get_multi___json_prt(){
    local tmp=""
    tmp=$(command mktemp)
    ___x_cmd_gh_curl get "$@" page per_page > "$tmp"
    printf "\n" >> "$tmp"

    local next_url=""
    _____x_cmd_gh_next_url
    if [ -z "$next_url" ]; then
        ___x_cmd_cmds_cat "$tmp"
        x rmrf "$tmp"
        return
    fi

    while [ -n "$next_url" ]; do
        ___x_cmd_gh_curl get "$next_url" >> "$tmp" || return
        printf "\n" >> "$tmp"
        _____x_cmd_gh_next_url
    done
    < "$tmp" x jo q0 \*.\* . | ___x_cmd_gx_merge_multi_page_json_array
    x rmrf "$tmp"
}

_____x_cmd_gh_next_url() {
    next_url="$(command grep "link:" "$___X_CMD_GH_TMP/.____x_cmd_gh_curl_header.$$")"
    next_url="${next_url#*'rel="prev", <'}"
    local tmp_url="${next_url%%'>; rel="next"'*}"
    if [ "$next_url" != "$tmp_url" ]; then
        local _split_endpoint=""
        if ! _split_endpoint="$(___x_cmd_gh_cfg get endpoint 2>/dev/null)"; then
            _split_endpoint="https://api.github.com"
        fi
        next_url="${tmp_url#*"${_split_endpoint}"}"
    else
        next_url=""
    fi
}

# EndSection

# Section: Default param util
alias ___x_cmd_gh_param_init_owner_repo='
    local owner_repo=""
    ___x_cmd_gh_param_normalize_repo  || return
'

# shellcheck disable=SC2154,SC2034
___x_cmd_gh_param_normalize_repo() {
    local op="$repo"
    [ -n "$op" ] || op="$1"
    case "$op" in
    */*)
        owner_repo="$op"
        ;;
    "")
        local owner=""; local repo="";
        ___x_cmd_gh_cur owner:=owner repo:=repo 2>/dev/null
        case "$repo" in
            */*) owner_repo="$repo"     ;;
            "")  owner_repo="$(___x_cmd_gx_get_owner_repo)" ;;
            *)
                if [ -n "$owner" ]; then
                    owner_repo="${owner}/${repo}"
                else
                    gh:error -h "$(_____x_cmd_gh_help__owner_setting)" "The <owner>/<repo> ${repo}. No owner provided. And default owner not set."
                    return 1
                fi
            ;;
        esac
        ;;
    *)
        local x_=""; ___x_cmd_gh_cur get_ owner 2>/dev/null
        if [ -z "$x_" ]; then
            gh:error -h "$(_____x_cmd_gh_help__owner_setting)" "The <owner>/<repo> ${repo}. No owner provided. And default owner not set."
            return 1
        fi
        owner_repo="${x_}/${op}"
        ;;
    esac
}
# EndSection

# Section: gh util
# NOTE: remove prefix: _endpoint_tmp="${_endpoint_tmp#*'://'}";
___x_cmd_gh___get_web_endpoint(){
    local _endpoint_tmp=""
    if _endpoint_tmp="$(___x_cmd_gh_cfg get web_endpoint 2>/dev/null)"; then
        printf "%s" "$_endpoint_tmp"
    else
        printf "%s" "https://github.com"
    fi
}

# return: $x_default_branch
___x_cmd_gh___get_x_default_branch_(){
    if [ -n "$owner_repo" ]; then
        x jo env . x_default_branch=.default_branch <<A
            $(___x_cmd_gh_curl get "/repos/${owner_repo}")
A
    elif [ -n "$repo" ]; then
        x jo env . x_default_branch=.default_branch <<A
            $(___x_cmd_gh_repo_info --json "$repo")
A
    else
        M='Please privide owner/repo' arg:ret:64
    fi
    [ -n "$x_default_branch" ] || return 1
}

# return: $x_
___x_cmd_gh___get_x_repo_tree_sha_by_branch_tag_(){
    x_=""
    [ -n "$owner_repo" ]  || M='Please privide owner/repo' arg:ret:64
    local ref="$1"
    if [ -z "$ref" ]; then
        local x_default_branch=""
        if ! ___x_cmd_gh___get_x_default_branch_; then
            gh:error "Can not get default branch of repo $owner_repo. Please have check it."
            return 1
        fi
        ref="$x_default_branch"
    fi
    x jo env . x_=.object.sha <<A
        $(___x_cmd_gh_curl get "/repos/${owner_repo}/git/ref/heads/${ref}"  2>/dev/null))
A
    [ -z "$x_" ] || return 0
    x jo env . x_=.object.sha <<A
        $(___x_cmd_gh_curl get "/repos/${owner_repo}/git/ref/tags/${ref}"   2>/dev/null))
A
    [ -n "$x_" ] || x_="$ref"
}

# NOTE: need unset json ENFORCE_JSON. the util func only using on subshell
___x_cmd_gh_owner_type_query() {
    param:void
    local owner="$1";   arg:init gh;
    [ -n "$owner" ]  || M='Please privide owner name' arg:ret:64
    [ "${owner##*/}" = "${owner}" ] || { printf "%s" "repo"; return 0; }
    unset json ENFORCE_JSON
    local types=""
    for types in "org" "user"
    do
        if  ___x_cmd_gh_${types}_info "$owner" 1>/dev/null 2>&1;then
            printf "%s" "$types"
            return
        fi
    done
    return 1
}
# EndSection
