import requests
import pandas as pd 


def get_airtable_request_headers(access_token: str)->str:
    """Constructs a request header for airtable.

    :param access_token: str: An Airtable access token.

    :returns: airtable_request_headers: str: The airtable request header.
    """
    airtable_request_headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }
    return airtable_request_headers


def fetch_airtable_workspace_metadata(access_token: str, airtable_workspace_id: str)->dict:
    """Retrieves all the metadatas associated with an airtable workspace/base.
    
    :param access_token: str: An Airtable access token.
    :param airtable_workspace_id: str: The ID of the airtable workspace/base.

    :returns: workspace_metadata: dict: The airtable workspace/base metadata.
    """
    endpoint = f"https://api.airtable.com/v0/meta/bases/{airtable_workspace_id}/tables"
    headers = get_airtable_request_headers(access_token)
    response = requests.get(endpoint, headers=headers)
    if response.status_code == 200:
        workspace_metadata = response.json()
    else:
        response.raise_for_status()
        workspace_metadata = {}
    return workspace_metadata


def fetch_airtable_records(access_token: str, airtable_workspace_id: str, table_name: str)->list:
    """Fetches records from an Airtable table.

    :param access_token: str: An Airtable access token.
    :param airtable_workspace_id: str: The ID of the airtable workspace/base.
    :param table_name: str: The name of the Airtable.

    :returns: airtable_records: list: A list of records from the specified table.
    """
    endpoint = f"https://api.airtable.com/v0/{airtable_workspace_id}/{table_name}"
    headers = get_airtable_request_headers(access_token)
    airtable_records = []
    offset = None
    while True:
        params = {}
        if offset:
            params['offset'] = offset
        response = requests.get(endpoint, headers=headers, params=params)
        if response.status_code == 200:
            data = response.json()
            airtable_records.extend(data.get('records', []))
            offset = data.get('offset')
            if not offset:
                break
        else:
            response.raise_for_status()
    return airtable_records


def from_airtable_to_dataframe(access_token: str, airtable_workspace_id: str, table_name: str)->pd.core.frame.DataFrame:
    """Downloads an Airtable data into a pandas dataframe.

    :param access_token: str: An Airtable access token.
    :param airtable_workspace_id: str: The ID of the airtable workspace/base.
    :param table_name: str: The name of the Airtable.

    :returns: airtable_dataframe: pd.core.frame.DataFrame: The dataframe containing the Airtable data.
    """
    airtable_records = fetch_airtable_records(access_token, airtable_workspace_id, table_name)
    airtable_data = [record['fields'] for record in airtable_records]
    airtable_dataframe = pd.DataFrame(airtable_data)
    return airtable_dataframe
