from typing import Tuple
import requests


def run_query(
    query: str,
    token: str,
    variables: dict | None = None,
    headers: dict | None = None
) -> Tuple[dict, str]:
    """
    Runs a Github GraphQL query and returns the result

    :param query: str
        GraphQL query
    :param token: str
        The users Github Personal Access Token
    :param variables: dict
        GraphQL Variables
    :param headers: dict
        Request headers
    :return: tuple
        The response and rate limit
    """
    if not headers:
        headers = {"Authorization": f"Bearer {token}"}

    request = requests.post(
        'https://api.github.com/graphql',
        json={'query': query, 'variables': variables},
        headers=headers
    )
    if request.status_code == 200:
        return request.json(), request.headers["X-RateLimit-Remaining"]
    else:
        raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))