# Canonical Data Proxy cluster metadata helpers.
# Requires: clinic-auth.sh (CLINIC_ENDPOINT, CLINIC_API_BASE, _ensure_clinic_auth).

_clinic_path_segment() {
    python3 - "$1" <<'PY'
import sys
import urllib.parse

print(urllib.parse.quote(sys.argv[1], safe=""))
PY
}

clinic_get_cluster_by_id() {
    local cluster_id="$1"

    if [ -z "$cluster_id" ]; then
        echo "usage: clinic_get_cluster_by_id <cluster_id>" >&2
        return 2
    fi

    _ensure_clinic_auth || return 1

    local encoded_cluster_id
    encoded_cluster_id=$(_clinic_path_segment "$cluster_id") || return 1
    curl -s "${CLINIC_ENDPOINT}/data-proxy/api/v1/clusters/${encoded_cluster_id}" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}"
}

_clinic_canonical_org_id_from_cluster_id() {
    local cluster_id="$1"
    local metadata org_id

    metadata=$(clinic_get_cluster_by_id "$cluster_id") || return 1
    org_id=$(printf '%s' "$metadata" | jq -r '.orgId // empty')
    if [ -z "$org_id" ]; then
        echo "Could not resolve DBAAS org ID for cluster ${cluster_id}" >&2
        return 1
    fi
    printf '%s' "$org_id"
}

clinic_list_clusters() {
    if [ $# -lt 1 ]; then
        echo "usage: clinic_list_clusters <dbaas_org_id> [query] [show_deleted] [page_size] [page]" >&2
        return 2
    fi

    local org_id="$1"
    local query="${2:-}"
    local show_deleted="${3:-false}"
    local page_size="${4:-50}"
    local page="${5:-1}"

    _ensure_clinic_auth || return 1

    curl -s -G "${CLINIC_ENDPOINT}/data-proxy/api/v1/orgs/${org_id}/clusters" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}" \
        --data-urlencode "query=${query}" \
        --data-urlencode "showDeleted=${show_deleted}" \
        --data-urlencode "pageSize=${page_size}" \
        --data-urlencode "page=${page}"
}

clinic_get_cluster() {
    if [ $# -lt 2 ]; then
        echo "usage: clinic_get_cluster <dbaas_org_id> <cluster_id>" >&2
        return 2
    fi

    local org_id="$1"
    local cluster_id="$2"
    local encoded_cluster_id

    _ensure_clinic_auth || return 1
    encoded_cluster_id=$(_clinic_path_segment "$cluster_id") || return 1

    curl -s "${CLINIC_ENDPOINT}/data-proxy/api/v1/orgs/${org_id}/clusters/${encoded_cluster_id}" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}"
}

clinic_get_components() {
    if [ $# -lt 2 ]; then
        echo "usage: clinic_get_components <dbaas_org_id> <cluster_id>" >&2
        return 2
    fi

    local org_id="$1"
    local cluster_id="$2"
    local encoded_cluster_id

    _ensure_clinic_auth || return 1
    encoded_cluster_id=$(_clinic_path_segment "$cluster_id") || return 1

    curl -s "${CLINIC_ENDPOINT}/data-proxy/api/v1/orgs/${org_id}/clusters/${encoded_cluster_id}/components" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}"
}

# Compatibility name; the preferred implementation now uses canonical /components.
clinic_get_resource_pool_components() {
    clinic_get_components "$@"
}

clinic_get_topology() {
    local cluster_id="$1"
    local metadata org_id deploy_type

    if [ -z "$cluster_id" ]; then
        echo "usage: clinic_get_topology <cluster_id>" >&2
        return 2
    fi

    metadata=$(clinic_get_cluster_by_id "$cluster_id") || return 1
    org_id=$(printf '%s' "$metadata" | jq -r '.orgId // empty')
    deploy_type=$(printf '%s' "$metadata" | jq -r '
        (.deployType // .deployTypeV2 // empty)
        | ascii_downcase
        | gsub("[ -]+"; "_")
    ')
    if [ -z "$org_id" ]; then
        echo "Cluster not found: $cluster_id" >&2
        return 1
    fi

    case "$deploy_type" in
        dedicated|resource_pool|byoc_resource_pool|premium_resource_pool|premium|byoc)
            clinic_get_components "$org_id" "$cluster_id"
            ;;
        shared|starter|essential)
            echo "Topology is not supported for shared clusters (starter/essential); use cluster list/detail APIs only." >&2
            return 1
            ;;
        *)
            echo "Cluster type '$deploy_type' has no topology" >&2
            return 1
            ;;
    esac
}

# Global discovery uses the Dashboard search contract because the org-scoped
# canonical list intentionally exposes only query/showDeleted/pagination.
# Keep this implementation behind the route-neutral clinic_search_clusters
# helper so callers choose capabilities, not transport generations.
clinic_legacy_search_clusters() {
    local query=""
    local show_deleted="false"
    local limit="10"
    local page="1"
    local sort=""
    local order=""
    local include_total="false"
    local request_args=()

    # Preserve the historical positional form:
    # clinic_search_clusters <query> [show_deleted] [limit] [page]
    case "${1:-}" in
        --*) ;;
        *)
            query="${1:-}"
            show_deleted="${2:-false}"
            limit="${3:-10}"
            page="${4:-1}"
            if [ $# -gt 4 ]; then
                echo "usage: clinic_search_clusters [--query value] [filters...]" >&2
                return 2
            fi
            set --
            ;;
    esac

    while [ $# -gt 0 ] && [ "${1#--}" != "$1" ]; do
        if [ $# -lt 2 ]; then
            echo "clinic_search_clusters: missing value for $1" >&2
            return 2
        fi
        case "$1" in
            --query) query="$2" ;;
            --show-deleted) show_deleted="$2" ;;
            --limit) limit="$2" ;;
            --page) page="$2" ;;
            --sort) sort="$2" ;;
            --order) order="$2" ;;
            --include-total) include_total="$2" ;;
            --cluster-id) request_args+=(--data-urlencode "cluster_id=$2") ;;
            --cluster-status) request_args+=(--data-urlencode "cluster_status=$2") ;;
            --cluster-version) request_args+=(--data-urlencode "cluster_version=$2") ;;
            --deploy-type) request_args+=(--data-urlencode "deploy_type=$2") ;;
            --deploy-type-v2) request_args+=(--data-urlencode "deploy_type_v2=$2") ;;
            --tenant-plan) request_args+=(--data-urlencode "tenant_plan=$2") ;;
            --control-plane) request_args+=(--data-urlencode "control_plane=$2") ;;
            --provider) request_args+=(--data-urlencode "provider=$2") ;;
            --region) request_args+=(--data-urlencode "region=$2") ;;
            *)
                echo "clinic_search_clusters: unsupported option $1" >&2
                return 2
                ;;
        esac
        shift 2
    done

    if [ $# -gt 0 ]; then
        echo "clinic_search_clusters: positional arguments cannot follow options" >&2
        return 2
    fi
    case "$show_deleted" in
        true|false) ;;
        *)
            echo "clinic_search_clusters: --show-deleted must be true or false" >&2
            return 2
            ;;
    esac
    case "$include_total" in
        true|false) ;;
        *)
            echo "clinic_search_clusters: --include-total must be true or false" >&2
            return 2
            ;;
    esac
    case "$limit" in
        ''|*[!0-9]*)
            echo "clinic_search_clusters: --limit must be a positive integer" >&2
            return 2
            ;;
    esac
    case "$page" in
        ''|*[!0-9]*)
            echo "clinic_search_clusters: --page must be a positive integer" >&2
            return 2
            ;;
    esac
    if [ "$limit" -lt 1 ] || [ "$page" -lt 1 ]; then
        echo "clinic_search_clusters: --limit and --page must be positive integers" >&2
        return 2
    fi

    if [ -n "$sort" ]; then
        request_args+=(--data-urlencode "sort=$sort")
    fi
    if [ -n "$order" ]; then
        request_args+=(--data-urlencode "order=$order")
    fi

    _ensure_clinic_auth || return 1

    # clusters2 is a filter-compatible superset of clusters and is also allowed
    # for the historical internal-user API-key contract.
    if [ ${#request_args[@]} -eq 0 ]; then
        curl -s "${CLINIC_API_BASE}/dashboard/clusters2" \
            -H "Authorization: Bearer ${CLINIC_API_KEY}" \
            -G \
            --data-urlencode "query=${query}" \
            --data-urlencode "show_deleted=${show_deleted}" \
            --data-urlencode "limit=${limit}" \
            --data-urlencode "page=${page}" \
            --data-urlencode "include_total=${include_total}"
        return
    fi

    curl -s "${CLINIC_API_BASE}/dashboard/clusters2" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}" \
        -G \
        --data-urlencode "query=${query}" \
        --data-urlencode "show_deleted=${show_deleted}" \
        --data-urlencode "limit=${limit}" \
        --data-urlencode "page=${page}" \
        --data-urlencode "include_total=${include_total}" \
        "${request_args[@]}"
}

clinic_legacy_search_cluster_by_id() {
    local cluster_id="$1"
    local show_deleted="${2:-false}"
    local limit="${3:-10}"

    _ensure_clinic_auth || return 1

    curl -s "${CLINIC_API_BASE}/dashboard/clusters2" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}" \
        -G \
        --data-urlencode "cluster_id=${cluster_id}" \
        --data-urlencode "show_deleted=${show_deleted}" \
        --data-urlencode "limit=${limit}" \
        --data-urlencode "page=1" \
        --data-urlencode "include_total=false"
}

clinic_legacy_get_cluster() {
    local clinic_internal_org_id="$1"
    local cluster_id="$2"

    _ensure_clinic_auth || return 1

    curl -s "${CLINIC_API_BASE}/orgs/${clinic_internal_org_id}/clusters/${cluster_id}" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}"
}

clinic_legacy_get_cluster_by_id() {
    local cluster_id="$1"
    local search_result clinic_internal_org_id

    search_result=$(clinic_legacy_search_cluster_by_id "$cluster_id" "true") || return 1
    clinic_internal_org_id=$(printf '%s' "$search_result" | jq -r --arg cluster_id "$cluster_id" '[.items[] | select(.clusterID == $cluster_id)][0].orgID // empty')
    if [ -z "$clinic_internal_org_id" ]; then
        echo "Cluster not found: $cluster_id" >&2
        return 1
    fi
    clinic_legacy_get_cluster "$clinic_internal_org_id" "$cluster_id"
}

clinic_legacy_get_resource_pool_components() {
    local clinic_internal_org_id="$1"
    local cluster_id="$2"

    _ensure_clinic_auth || return 1

    curl -s "${CLINIC_API_BASE}/orgs/${clinic_internal_org_id}/clusters/${cluster_id}/resource-pool/components" \
        -H "Authorization: Bearer ${CLINIC_API_KEY}"
}

clinic_legacy_get_topology() {
    local cluster_id="$1"
    local search_result clinic_internal_org_id deploy_type

    search_result=$(clinic_legacy_search_cluster_by_id "$cluster_id" "true") || return 1
    clinic_internal_org_id=$(printf '%s' "$search_result" | jq -r --arg cluster_id "$cluster_id" '[.items[] | select(.clusterID == $cluster_id)][0].orgID // empty')
    deploy_type=$(printf '%s' "$search_result" | jq -r --arg cluster_id "$cluster_id" '
        [.items[] | select(.clusterID == $cluster_id)][0]
        | (.clusterDeployType // .clusterDeployTypeV2 // .deployType // empty)
        | ascii_downcase
        | gsub("[ -]+"; "_")
    ')
    if [ -z "$clinic_internal_org_id" ]; then
        echo "Cluster not found: $cluster_id" >&2
        return 1
    fi

    case "$deploy_type" in
        dedicated|resource_pool|byoc_resource_pool|premium_resource_pool|premium|byoc)
            clinic_legacy_get_resource_pool_components "$clinic_internal_org_id" "$cluster_id"
            ;;
        shared|starter|essential)
            echo "Topology is not supported for shared clusters (starter/essential); use cluster list/detail APIs only." >&2
            return 1
            ;;
        *)
            echo "Cluster type '$deploy_type' has no topology" >&2
            return 1
            ;;
    esac
}

# Route-neutral discovery helper. It deliberately hides the compatibility
# transport needed for global and advanced server-side filters.
clinic_search_clusters() {
    clinic_legacy_search_clusters "$@"
}

clinic_search_cluster_by_id() {
    clinic_legacy_search_cluster_by_id "$@"
}
