"""python functions wrapping address-to-uprn matching api calls"""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_api_calls.ipynb.

# %% auto 0
__all__ = ['address_search', 'upload', 'download']

# %% ../nbs/01_api_calls.ipynb 5
def _get_env_var(
    var_name: str, # name of expected environment variable
    dotenv_path: str = '.env' # location of .env file
    ) -> str:# value of var, or throw a ValueError if not found
    """
    Get environment variable or raise an error if not found.
    Tries: 1. Existing env var, 2. .env file, 3. Raise error.
    """
    import os

    # Try to get from existing environment
    value = os.getenv(var_name)
    if value is not None:
        return value

    # If not found, try to load from .env
    if dotenv_path:
        from dotenv import load_dotenv
        load_dotenv(dotenv_path)
        value = os.getenv(var_name)
        if value is not None:
            return value

    # If still not found, raise error
    raise ValueError(f"Environment variable '{var_name}' not found in environment or {dotenv_path} file.")

# %% ../nbs/01_api_calls.ipynb 6
def _secrets(
    dotenv_path = '.env' # path to .env file, default to ../.env
    ) -> tuple: # tuple of environment variables
    """get environment variables from a local file 
    outside version control, uses the python-dotenv package
    """
    # take environment variables from .env
    ASSIGN_ENDPOINT = _get_env_var("ASSIGN_ENDPOINT", dotenv_path)
    ASSIGN_USER = _get_env_var("ASSIGN_USER", dotenv_path)
    ASSIGN_PASS = _get_env_var("ASSIGN_PASS", dotenv_path)
    return ASSIGN_ENDPOINT, ASSIGN_USER, ASSIGN_PASS



# %% ../nbs/01_api_calls.ipynb 7
import requests

def address_search(
    address: str # An address on a single line, each element separated with a comma
    ) -> str: # json representation of the matching AddressBase Premium record
    """
    Search for a UPRN by address

    Example:

        > response = address_search('10 Downing St,Westminster,London,SW1A2AA')
        > response.json()
        {'Address_format': 'good',
         'Postcode_quality': 'good',
         'Matched': True,
         'BestMatch': {'UPRN': '100023336956',
         'Qualifier': 'Property',
         'LogicalStatus': '1',
         'Classification': 'RD04',
         'ClassTerm': 'Terraced',
         'Algorithm': '10-match1',
         'ABPAddress': {'Number': '10',
         'Street': 'Downing Street',
         'Town': 'City Of Westminster',
         'Postcode': 'SW1A 2AA'},
         'Match_pattern': {'Postcode': 'equivalent',
         'Street': 'equivalent',
         'Number': 'equivalent',
         'Building': 'equivalent',
         'Flat': 'equivalent'}}}
    """

    # GET AUTHENTICATION DETAIL FROM .ENV
    ASSIGN_ENDPOINT, ASSIGN_USER, ASSIGN_PASS = _secrets()

    response = requests.get(
        f"{ASSIGN_ENDPOINT}/getinfo?adrec={address}", auth=(ASSIGN_USER, ASSIGN_PASS)
    )
    return response

# %% ../nbs/01_api_calls.ipynb 8
import requests
import os

def upload(
    infilepath: str, # filepath containing multiple addresses to upload
    debugLevel: int = 0 # optional, used during development
) -> requests.models.Response: # API response confirming whether upload OK
    """
    Upload text file of TSV address records to the ASSIGN API, OR upload an encrypted salt
    
    For address uploads, format is two columns: id and address, e.g.:
    1	10 Downing St,Westminster,London,SW1A2AA
    1	11 Downing St,Westminster,London,SW1A2AA

    Example:

        > infilepath='../data/external/test-addresses.txt'
        > upload(infilepath=infilepath).json()
        {'upload': {'status': 'OK'}}

        OR FOR SALT

        > infilepath='../data/external/test.EncryptedSalt'
        > upload(infilepath=infilepath).json()
        {"upload": { "status": "SALTOK"}}

    """

    # useful for debugging http activity
    if debugLevel == 1:
        _logger()

    # GET AUTHENTICATION DETAIL FROM .ENV
    ASSIGN_ENDPOINT, ASSIGN_USER, ASSIGN_PASS = _secrets()

    # HTTP POST request
    url = f"{ASSIGN_ENDPOINT}/fileupload2"

    files = {
        "file": (os.path.basename(infilepath), open(infilepath, "rb"), "text/plain")
    }
    response = requests.post(url, files=files, auth=(ASSIGN_USER, ASSIGN_PASS))

    return response

# %% ../nbs/01_api_calls.ipynb 9
import requests
import os

def download(
    infilepath: str, # filename of the previously uploaded file
    outfilepath: str = '../data/processed/assign-uprn.tsv', # filepath to store the response in
) -> requests.models.Response: # API response containing content to output to TSV file
    """
    Download TSV data matching previously upload txt file of TSV addresses
    
    Example:
    
        > infilepath = '../data/external/test-addresses.txt'
        > download(infilepath=infilepath).status_code
        200

    """

    # GET AUTHENTICATION DETAIL FROM .ENV
    ASSIGN_ENDPOINT, ASSIGN_USER, ASSIGN_PASS = _secrets()

    # HTTP GET request
    url = f"{ASSIGN_ENDPOINT}/download3"

    # TRIM PATH TO FILENAME ONLY (FOR IDENTIFICATION BY ASSIGN)
    params = {
        "filename": os.path.basename(infilepath),
    }

    response = requests.get(
        url, params=params, auth=(f"{ASSIGN_USER}", f"{ASSIGN_PASS}")
    )

    with open(outfilepath, "wb") as f:
        f.write(response.content)
        print(f"written to {outfilepath}")

    return response
