from requests import Response

from mstrio.connection import Connection
from mstrio.utils.error_handlers import ErrorHandler


@ErrorHandler(err_msg="Error getting privileges.")
def get_privileges(connection, error_msg=None):
    """Get the set of available privileges for the platform.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/privileges',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error getting privilege categories.")
def get_privilege_categories(connection, error_msg=None):
    """Get the set of available privilege categories for the platform.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/privileges/categories',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error getting LDAP information.")
def get_ldap_info(connection, error_msg=None):
    """Get the existing LDAP configuration and attributes which are stored in
    the Intelligence Server metadata. You may update and save it back later
    based on the existing configuration.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/ldap/configuration',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error creating LDAP configuration.")
def create_ldap_config(connection, body, error_msg=None):
    """Create a new LDAP configuration and save it to the Intelligence Server.
    There is only one LDAP configuration in Intelligence Server metadata, so
    this operation will replace the old configuration if exists. The request
    body should include all configuration fields.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/iserver/ldap/configuration',
        headers={'X-MSTR-ProjectID': None},
        json=body,
    )


@ErrorHandler(err_msg="Error deleting LDAP configuration.")
def delete_ldap_config(connection, error_msg=None):
    """Delete the existing LDAP configuration from Intelligence Server
    metadata.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.delete(
        endpoint='/api/iserver/ldap/configuration',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error updating LDAP configuration.")
def update_ldap_config(connection, body, error_msg=None):
    """Update the existing LDAP configuration and save it to the Intelligence
    Server. There is only one LDAP configuration in Intelligence Server
    metadata, so this operation will replace the old configuration. The request
    body should only contain fields that will be updated.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.patch(
        endpoint='/api/iserver/ldap/configuration',
        headers={'X-MSTR-ProjectID': None},
        json=body,
    )


@ErrorHandler(err_msg="Error getting LDAP attributes.")
def get_ldap_attributes(connection, error_msg=None):
    """Get LDAP attributes list. You may want to import more attributes for
    users. The API will provides you the list of available LDAP attributes,
    from which you may choose some extra attributes to import.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/ldap/attributes',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error getting LDAP certificate information.")
def get_ldap_certificate_info(connection, error_msg=None):
    """Get LDAP server certificate info. The communication between the
    Intelligence Server and LDAP server can be encrypted by SSL (optional).
    This API will return basic information about the LDAP server certificate.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/ldap/certificate',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error updating LDAP certificate.")
def upload_ldap_certificate(connection, body, error_msg=None):
    """Upload LDAP server certificate for encrypted communication. The
    communication between the Intelligence Server and the LDAP server can be
    encrypted by SSL (optional). The certificate uploaded in this API will be
    added to the trust store of the Intelligence Server, and later used for the
    SSL communication between the Intelligence Server and the LDAP server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/iserver/ldap/certificate',
        headers={'X-MSTR-ProjectID': None},
        json=body,
    )


@ErrorHandler(err_msg="Error verifying LDAP binding.")
def verify_ldap_binding(connection, error_msg=None):
    """Verify the LDAP username and password binding.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/ldap/authuserbinds',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error getting LDAP batch import status.")
def get_ldap_batch_import_status(connection, error_msg=None):
    """Get LDAP batch import status. You can get the progress of LDAP batch
    import, including its status (e.g. failed, stopped, undergoing, and
    canceled). If there is LDAP batch import undergoing, you can also get the
    number of users and groups which have already been imported.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/ldap/import',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error stopping LDAP batch import.")
def stop_ldap_batch_import(connection, error_msg=None):
    """Stop the LDAP batch import if it exists. This operation will be ignored
    if there is no undergoing LDAP batch import.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/iserver/ldap/import',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error doing LDAP batch import.")
def do_ldap_batch_import(connection, error_msg=None):
    """Do LDAP batch import now. This API starts the LDAP batch import, which
    will import both groups and users from the LDAP server. No request body is
    needed.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/iserver/ldap/import',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error updating authentication configurations.")
def update_authentication_configs(connection, body, error_msg=None):
    """Update the authentication configuration settings for the current REST
    server. In the body parameter of the request, you specify the default
    authentication mode and the authentication modes that will be available to
    connect to an Intelligence Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling


    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/auth',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error updating collaboration server configurations.")
def update_collaboration_server_configs(connection, body, error_msg=None):
    """Update the Collaboration Server configuration settings. In the body
    parameter of the request, you specify the base URL for the Collaboration
    Server, whether the collaboration service is enabled, and whether TLS
    (Transport Layer Security) secure communication is enabled. Enabling TLS
    requires configuring trust store settings on the REST Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/collaboration',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error updating web configurations.")
def update_web_configs(connection, body, error_msg=None):
    """Update the Strategy One Web configuration settings. In the body
    parameter of the request, you specify the base URL for the Strategy One
    Web Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/microStrategyWeb',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error testing collaboration server connection.")
def test_collaboration_connection(connection, body, error_msg=None):
    """Test the connection between the REST Server and the Collaboration
    Server. In the body parameter of the request, you specify the base URL for
    the Collaboration Server and whether TLS (Transport Layer Security) secure
    communication is enabled. Enabling TLS requires configuring trust store
    settings on the REST Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/admin/restServerSettings/collaboration/connectionTest',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error updating intelligence server configurations.")
def update_iserver_configs(connection, body, error_msg=None):
    """Update the Intelligence Server configuration settings. In the body
    parameter of the request, you specify the default port and hostname, the
    initial and max connection pool size, the request timeout, the number of
    reports/documents and searches that can be kept in memory, whether a trust
    relationship has been set with the Intelligence Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/iServer',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error getting rest configurations.")
def get_rest_configs(connection, error_msg=None):
    """Get configuration settings for the current REST Server, including
    settings for authentication, the Collaboration Server, Google Analytics,
    and the Intelligence Server.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/admin/restServerSettings',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(
    err_msg="Error checking intelligence server - web server trust relationship."
)
def check_iserver_web_trust(connection, error_msg=None):
    """Check to see if there is a trust relationship between the Web Server and
    the Intelligence Server.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/admin/restServerSettings/iServer/trustRelationship',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(
    err_msg="Error setting intelligence server - web server trust relationship."
)
def set_iserver_web_trust(connection, body, error_msg=None):
    """Set up a trust relationship between the Web Server and the Intelligence
    Server. You obtain the authorization token needed to execute the request
    using POST /auth/login; you pass the authorization token in the request
    header. In the body parameter of the request, you specify the URL or other
    unique identifier for the Web Server.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/admin/restServerSettings/iServer/trustRelationship',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(
    err_msg="Error deleting intelligence server - web server trust relationship."
)
def delete_iserver_web_trust(connection, error_msg=None):
    """Delete a trust relationship between the Web Server and the Intelligence
    Server. You obtain the authorization token needed to execute the request
    using POST /auth/login; you pass the authorization token in the request
    header.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.delete(
        endpoint='/api/admin/restServerSettings/iServer/trustRelationship',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error testing intelligence server connection.")
def test_iserver_connection(connection, error_msg=None):
    """Test the connection between the Intelligence Server and the REST Server.
    Currently, only socket connectivity is tested. In the body parameter of the
    request, you specify the port and hostname of the Intelligence Server.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.post(
        endpoint='/api/admin/restServerSettings/iServer/connectionTest',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error getting security settings.")
def get_security_settings(connection, error_msg=None):
    """Get relevant information about security settings, such as whether the
    secret key used for signing the identity token was set in the configuration
    file. If it was not set properly, an exception will be triggered.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/admin/restServerSettings/security',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error updating security settings.")
def update_security_settings(connection, body, error_msg=None):
    """Update the security settings. In the body of the request you can specify
    the secret key that will be used in identity token generation, whether to
    enable Cross Origin Resource Sharing (CORS), and whether to disable URL
    validation when specifying domains for CORS configuration.

    Args:
        connection: Strategy One REST API connection object
        body: JSON-formatted definition of the dataset. Generated by
            `utils.formjson()`.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/security',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error fetching I-Server settings.")
def get_iserver_settings_config(connection, error_msg=None):
    """For each setting, we provide different basic information to help client
    to render the settings.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/v2/iserver/settings/config',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error fetching I-Server settings.")
def get_iserver_settings(connection, error_msg=None):
    """This resource will retire resource 'GET iserver/settings' in the future
    version. Current version just cover Governing rule settings.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/v2/iserver/settings',
        headers={'X-MSTR-ProjectID': None},
    )


@ErrorHandler(err_msg="Error updating I-Server settings.")
def create_iserver_settings(
    connection, body, error_msg=None, whitelist=('ERR001', 400)
):
    """Create some IServer governing settings.

    Example:
        body = {
            "maxUsedVirtualByte": {
                "value": 100
            },
            "workSetSwapPath": {
                "value": ".\\TmpPool"
            },
            "ignoreGovernorOnChild": {
                "value": true
            }
        }
    """
    return connection.put(
        endpoint='/api/v2/iserver/settings',
        headers={'X-MSTR-ProjectID': None},
        json=body,
    )


@ErrorHandler(err_msg="Error updating I-Server settings.")
def update_iserver_settings(
    connection, body, error_msg=None, whitelist=('ERR001', 400)
):
    """Update some IServer governing settings.

    Example:
        body = {
            "maxUsedVirtualByte": {
                "value": 100
            },
            "workSetSwapPath": {
                "value": ".\\TmpPool"
            },
            "ignoreGovernorOnChild": {
                "value": true
            }
        }
    """
    return connection.patch(
        endpoint='/api/v2/iserver/settings',
        headers={'X-MSTR-ProjectID': None},
        json=body,
    )


@ErrorHandler(err_msg="Error getting cluster membership information.")
def get_cluster_membership(connection, error_msg=None):
    """Get IServer cluster membership information.

    Args:
        connection: Strategy One REST API connection object
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/admin/iServer/clusterMembership',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error getting I-Server node {node} settings.")
def get_iserver_node_settings(connection, node, error_msg=None):
    """Get Intelligence Server configuration settings for a given server node
    within a cluster.

    Args:
        connection: Strategy One REST API connection object
        node: Intelligence Server host name
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint=f'/api/admin/restServerSettings/iServer/{node}',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error updating Intelligence Server configuration settings.")
def update_iserver_configuration_settings(connection, body, error_msg=None):
    """Update Intelligence Server configuration settings.

    Args:
        connection: Strategy One REST API connection object
        body: object with settings to set
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/admin/restServerSettings/iServer',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error updating I-Server node {node} settings.")
def update_iserver_node_settings(connection, body, node, error_msg=None):
    """Update Intelligence Server configuration settings for a given server
    node within a cluster.

    Args:
        connection: Strategy One REST API connection object
        node: Intelligence Server host name
        error_msg (string, optional): Custom Error Message for Error Handling
        body:{"loadBalanceFactor": int,
              "initialPoolSize": int,
              "maxPoolSize": int}

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint=f'/api/admin/restServerSettings/iServer/{node}',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
        json=body,
    )


@ErrorHandler(err_msg="Error deleting I-Server node {node} settings.")
def delete_iserver_node_settings(connection, node, error_msg=None):
    """Removes Intelligence Server configuration settings for a given server
    node within a cluster. This can be useful to clear out settings so that a
    default value is applied.

    Args:
        connection: Strategy One REST API connection object
        node: Intelligence Server host name
        error_msg (string, optional): Custom Error Message for Error Handling
    """
    return connection.delete(
        endpoint=f'/api/admin/restServerSettings/iServer/{node}',
        headers={
            'X-MSTR-ProjectID': None,
            'Authorization': connection._get_authorization(),
        },
    )


@ErrorHandler(err_msg="Error getting Library storage configuration.")
def storage_service_get_configs(
    connection: Connection,
    fields: str | None = None,
    error_msg: str | None = None,
):
    """Get the storage type, location, and cloud storage configurations.

    Args:
        connection (Connection): Strategy One REST API connection object
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object. 200 on success.
    """
    return connection.get(
        endpoint='/api/mstrServices/library/storage', params={'fields': fields}
    )


@ErrorHandler(err_msg="Error validating Library storage configuration.")
def storage_service_validate_configs(
    connection: Connection, body: dict, error_msg: str | None = None
):
    """Validate the storage type, location, and cloud storage configurations.
    Following privilege: DssXmlPrivilegesAdministerEnvironment is required to
    invoke this endpoint.

    Args:
        connection (Connection): Strategy One REST API connection object
        body (dict): {
            "sharedFileStore": {
                "type": str
                    ("unset", "unknown", "file_system", "S3", "Azure", "GCS"),
                "alias": str (optional),
                "location": str (optional),
                "s3Region": str (optional),
                "awsAccessId": str (optional),
                "awsSecretKey": str (optional),
                "azureStorageAccountName": str (optional),
                "azureSecretKey": str (optional),
                "gcsServiceAccountKey": str (optional)
            }
        }
            "sharedFileStore"/"type" supports:
            "file_system", "S3", "Azure", "GCS"
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object. 204 on success.
    """
    return connection.post(
        endpoint='/api/mstrServices/library/storage/validation',
        json=body,
    )


@ErrorHandler(err_msg="Error updating Library storage configuration.")
def storage_service_update_configs(
    connection: Connection, body: dict, error_msg: str | None = None
):
    """Update the storage type, location, and cloud storage configurations.
    Following privilege: DssXmlPrivilegesAdministerEnvironment is required to
    invoke this endpoint.

    Args:
        connection (Connection): Strategy One REST API connection object
        body (dict): {
            "sharedFileStore": {
                "type": str
                    ("unset", "unknown", "file_system", "S3", "Azure", "GCS"),
                "alias": str (optional),
                "location": str (optional),
                "s3Region": str (optional),
                "awsAccessId": str (optional),
                "awsSecretKey": str (optional),
                "azureStorageAccountName": str (optional),
                "azureSecretKey": str (optional),
                "gcsServiceAccountKey": str (optional)
            }
        }
            "sharedFileStore"/"type" supports:
            "file_system", "S3", "Azure", "GCS"
        error_msg (string, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object. 204 on success.
    """
    return connection.patch(
        endpoint='/api/mstrServices/library/storage',
        json=body,
    )


@ErrorHandler(err_msg="Error getting fences list.")
def list_fences(
    connection: Connection, fields: str | None = None, error_msg: str | None = None
) -> Response:
    """Get the list of fences.

    Args:
        connection (Connection): Strategy One REST API connection object
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(endpoint='/api/v2/iserver/fences', params={'fields': fields})


@ErrorHandler(err_msg="Error creating a new fence.")
def create_fence(
    connection: Connection,
    body: dict,
    fields: str | None = None,
    error_msg: str | None = None,
) -> Response:
    """Create a new fence.

    Args:
        connection (Connection): Strategy One REST API connection object
        body (dict): Fence creation data
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.

    """
    return connection.post(
        endpoint='/api/v2/iserver/fences',
        params={'fields': fields},
        json=body,
    )


@ErrorHandler(err_msg="Error getting fence with ID: {id}")
def get_fence(
    connection: Connection,
    id: str,
    fields: str | None = None,
    error_msg: str | None = None,
) -> Response:
    """Get a fence by ID.

    Args:
        connection (Connection): Strategy One REST API connection object
        id (str): Fence ID
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint=f'/api/v2/iserver/fences/{id}',
        params={'fields': fields},
    )


@ErrorHandler(err_msg="Error deleting fence with ID: {id}")
def delete_fence(
    connection: Connection, id: str, error_msg: str | None = None
) -> Response:
    """Delete a fence by ID.

    Args:
        connection (Connection): Strategy One REST API connection object
        id (str): Fence ID
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.delete(endpoint=f'/api/v2/iserver/fences/{id}')


@ErrorHandler(err_msg="Error updating fence with ID: {id}")
def update_fence(
    connection: Connection,
    id: str,
    body: dict,
    fields: str | None = None,
    error_msg: str | None = None,
) -> Response:
    """Update a fence by ID.

    Args:
        connection (Connection): Strategy One REST API connection object
        id (str): Fence ID
        body (dict): Fence update data
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.patch(
        endpoint=f'/api/v2/iserver/fences/{id}',
        params={'fields': fields},
        json=body,
    )


@ErrorHandler(err_msg="Error getting cluster startup membership information.")
def get_cluster_startup_membership(
    connection: Connection, fields: str | None = None, error_msg: str | None = None
) -> Response:
    """Get the cluster startup membership information.

    Args:
        connection (Connection): Strategy One REST API connection object
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.get(
        endpoint='/api/iserver/clusterStartupMembership',
        params={'fields': fields},
    )


@ErrorHandler(err_msg="Error updating cluster startup membership information.")
def update_cluster_startup_membership(
    connection: Connection,
    body: dict,
    fields: str | None = None,
    error_msg: str | None = None,
) -> Response:
    """Update the cluster startup membership information.

    Args:
        connection (Connection): Strategy One REST API connection object
        body (dict): Cluster startup membership update data
        fields (str, optional): A comma-separated list of fields to include
                in the response. By default, all fields are returned.
        error_msg (str, optional): Custom Error Message for Error Handling

    Returns:
        Complete HTTP response object.
    """
    return connection.put(
        endpoint='/api/iserver/clusterStartupMembership',
        json=body,
        params={'fields': fields},
    )
