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

# Should be like this.
# gh repo collaborator add el:admin
# gh repo collaborator remove user-a
# gh repo collaborator add user-b

# gh repo collaborator +el:admin -user-a +user-b
___x_cmd_gh_repo_collaborator() {
    param:scope  ___x_cmd_github
    param:subcmd ___x_cmd_gh_repo_collaborator              \
        ls             "Interactive UI show repo of user"   \
        ll             "List collaborator"                  \
        "edit|ed"      "Edit collaborator permission"       \
        add            "Add collaborator"                   \
        rm             "Remove collaborator"                \
        invitation     "repo invitations management"
    param:subcmd:try
    param:run

    ___x_cmd_gh_repo_collaborator_ll
}

# Section: List
___x_cmd_gh_repo_collaborator_ls(){
    if ___x_cmd_gx_has_format_args "$@"; then
        ___x_cmd_gh_repo_collaborator_ll "$@"
        return
    fi

    param:scope     ___x_cmd_gh
    param:dsl       '
type:
    Affiliation =   outside direct all
options:
    --affiliation   "Filter collaborators returned by their affiliation."               <>:Affiliation="all"
    --per_page      "Results per page"                                                  <>=30
    --page          "Page number of the results to fetch."                              <>=1
    --repo|-r       "<owner_path>/<repo_path>"                                          <>:RepoName
'
    param:run
    local ___gh_error_msg=""
    ___x_cmd_gh_param_init_owner_repo
    if ___x_cmd_gx_is_interactive_env; then
        local ___X_CMD_TUI_TABLE_FINAL_COMMAND
        local ___X_CMD_TUI_TABLE_CUR_LINE
        local ___X_CMD_TUI_TABLE_CUR_ITEM

        ___x_cmd_gh_tui_app --owner_repo "$owner_repo" --affiliation "$affiliation" --per_page "$per_page" --page "$page" --repo "$repo" \
            --request-code '___x_cmd_gh_get_multi "/repos/${owner_repo}/collaborators" affiliation per_page page' \
            --error-msg "Get collaborator list fail" \
            --end ___x_cmd_gh_repo_collaborator_app_status_handler \
            "repo.collaborator.app.awk"
    else
        ___x_cmd_gh_get_multi "/repos/${owner_repo}/collaborators" affiliation | \
            x jo 2c             .login
    fi
}

___x_cmd_gh_repo_collaborator_app_status_handler(){
    local user_name
    user_name="${___X_CMD_TUI_TABLE_CUR_LINE##*Name: }"
    user_name=${user_name%%
Url:*}
    case "$___X_CMD_TUI_TABLE_FINAL_COMMAND" in
            "ENTER")        printf "%s\n" "$___X_CMD_TUI_TABLE_CUR_LINE"  ;;
            "c")            ___x_cmd_gh_repo_collaborator_add    --repo "${repo}"                     ;;
            "u")            ___x_cmd_gh_repo_collaborator_edit   --repo "${repo}"    "$user_name"     ;;
            "d")            ___x_cmd_gh_repo_collaborator_rm     --repo "${repo}"    "$user_name"     ;;
            *)              return   ;;
    esac
}
# EndSection

# Section: List
# https://docs.github.com/en/rest/collaborators/collaborators#list-repository-collaborators
___x_cmd_gh_repo_collaborator_ll() {
    param:scope ___x_cmd_github
    param:dsl '
type:
    Affiliation =   outside direct all
options:
    --affiliation   "Filter collaborators returned by their affiliation."               <>:Affiliation="all"
    --per_page      "Results per page"                                                  <>=30
    --page          "Page number of the results to fetch."                              <>=1
    --repo|-r       "<owner_path>/<repo_path>"                                          <>:RepoName

    --json|-j   "output origin json data"
    --csv       "output csv data"
    --yml       "output yml data"
'
    param:run
    ___x_cmd_gh_param_init_owner_repo
    [ -n "$owner_repo" ] || M='Please provide --repo <owner/repo>"' arg:ret:64
    if ___x_cmd_gx_output_is_format; then
        ___x_cmd_gh_get_multi "/repos/${owner_repo}/collaborators" affiliation | ___x_cmd_gx_output_format
    else
        ___x_cmd_gh_get_multi "/repos/${owner_repo}/collaborators" affiliation | \
            x jo 2c             .login     .role_name  .html_url .id | \
            x csv header --add   Username   Role        Url       Id | \
            if [ -n "$csv" ]; then  ___x_cmd_cmds cat
            else                    x csv static_tab
            fi
    fi
}
# EndSection

# Section: Add
# https://docs.github.com/en/rest/collaborators/collaborators#add-a-repository-collaborator
___x_cmd_gh_repo_collaborator_add() {
    param:scope ___x_cmd_github
    param:dsl '
options:
    #1              "user login path"                                               <>:Username_multiple
    --repo|-r       "<owner_path>/<repo_path>"                                      <>:MultipleRepoName
    --permission|-p "The permission to grant the collaborator."                     <>="push"     = pull triage push maintain admin
    --json|-j       "output json data"
'
    param:run

    [ "$#" -ne 0 ] || M='accepts arg(s) (username), received empty' arg:ret:64
    local _tmp_repo="$repo"
    local _avt_name=""
    while true; do
        repo="${_tmp_repo%%,*}"
        _tmp_repo="${_tmp_repo#*,}"
        ___x_cmd_gh_param_init_owner_repo
        for _avt_name in "$@"; do
            ___x_cmd_gh____transform_avt_name || return
            ___x_cmd_gh_curl put  "/repos/$owner_repo/collaborators/${_avt_name##*/}" -- permission | {
                ___x_cmd_gh_collaborator____ui_handler Add || return
            }
        done
        [ "$repo" != "$_tmp_repo" ] || return 0
    done
}
# EndSection

# Section: Edit
# https://docs.github.com/en/rest/collaborators/collaborators#add-a-repository-collaborator
___x_cmd_gh_repo_collaborator_edit() {
    param:scope ___x_cmd_github
    param:dsl '
options:
    #1              "Username"                                                      <>:Username_multiple
    --repo|-r       "<owner_path>/<repo_path>"                                      <>:RepoName
    --permission|-p "The permission to grant the collaborator."                     <>="push"     = pull triage push maintain admin

    --json|-j       "output json data"
'
    param:run

    [ -n "$1" ] || M='accepts 1 arg (username), received empty' arg:ret:64
    local _avt_name="$1"
    ___x_cmd_gh____transform_avt_name || return
    ___x_cmd_gh_param_init_owner_repo
    ___x_cmd_gh_curl put  "/repos/$owner_repo/collaborators/${_avt_name##*/}" -- permission | ___x_cmd_gh_collaborator____ui_handler Edit
}
# EndSection

# Section: Remove
# https://docs.github.com/en/rest/collaborators/collaborators#remove-a-repository-collaborator
# shellcheck disable=2154
___x_cmd_gh_repo_collaborator_rm() {
    param:scope ___x_cmd_github
    param:dsl '
options:
    #1          "Username list"                           <>:Username
    --repo|-r   "<owner_path>/<repo_path>"                <>:RepoName
    --yes|-y    "Ignore remove prompt interception"
'
    param:run

    [ "$#" -ne 0 ] || M='accepts arg(s) (username), received empty' arg:ret:64
    ___x_cmd_gh_param_init_owner_repo
    local _avt_name=""
    for _avt_name in "$@"; do
        ___x_cmd_gh____transform_avt_name || return
        [ "$yes" = "true" ] || ___x_cmd_ui_yesno "Are you sure $owner_repo to remove user: $(___x_cmd_ui bold red "$_avt_name") ?" || continue
        ___x_cmd_gh_curl del "/repos/$owner_repo/collaborators/${_avt_name##*/}" | (
                [ -z "$___X_CMD_GH_IN_TEST" ] || { ___x_cmd_cmds_cat; return; }
                x jo env . gh_resp_msg=.message gh_resp_err=.errors
                if ___x_cmd_gh_http_error; then
                    ___x_cmd_ui_tf  true "[Success]: Remove $_avt_name collaborator from $owner_repo repo"
                else
                    ___x_cmd_ui_tf false "Remove $_avt_name collaborator from $owner_repo repo failure:" >&2
                    ___x_cmd_gh____handle_resp
                    return 1
                fi
            )
    done
}
# EndSection

# Section: collaborator UI
___x_cmd_gh_collaborator____ui_handler(){
    if [ -n "$ENFORCE_JSON" ] || [ -n "$json" ]; then
        ___x_cmd_cmds_cat
        ___x_cmd_gh_http_error
        return
    fi
    (
        local permissions=""; local invitee=""
        x jo env . gh_resp_msg=.message gh_resp_err=.errors \
            repo=.repository.full_name permissions=.permissions invitee=.invitee.login __id=.id
        case "$1" in
            Add|Edit)
                if [ -n "$permissions" ]; then
                    _inf_msg="$1 $_avt_name user to $owner_repo repo successfully:"
                else
                    _inf_msg="[Success]: $1 $_avt_name user to $owner_repo repo"
                fi
                _err_msg="$1 $_avt_name user to $owner_repo repo failure:"
                ;;
        esac

        # To change the permissions, and pass a different permission parameter. The response will be a 204
        if ___x_cmd_gh_http_error 2>/dev/null; then
            if [ -n "$invitee" ]; then
                ___x_cmd_ui_tf  true "Send $owner_repo invitation to $invitee successfully:" \
                    "Invitation URL: https://github.com/${owner_repo}/invitations" \
                    ${__id:+"[Tip]: The $_avt_name user also can run cmd to accept 'x gh repo collaborator invitation accept ${__id}'"}
            else
                ___x_cmd_ui_tf  true "${_inf_msg}"  ${permissions:+"Permissions: $permissions"}
            fi
        else
            ___x_cmd_ui_tf false "${_err_msg}" >&2
            ___x_cmd_gh____handle_resp
            return 1
        fi
    )
}
# EndSection

