from .exc import MissingKeyError
from .sending import Send
from .gcore.queries import GetPrices
from .orders import BuyCoins, SellCoins
from .naira_token_account import NairaTokenAccount
from .receive import Receive
from base64 import b64encode
from typing import Optional, List
import requests


class BuyCoinsClient:
    """
    Executor class that handles all queries to the buycoins API.

    Args:
        public_key (str): generated public key from buycoins developer account

        secret_key (str): generated secret key from buycoins developer account
    
    Returns:
        <class 'BuycoinsClient'> object which can be used to execute requests.
    Raises:
        MissingKeyError: raised if either or none of the keys are provided when instantiating the class.
    """

    _URL = "https://backend.buycoins.tech/api/graphql"

    def __init__(self, public_key=None, secret_key=None):
        if not public_key:
            raise MissingKeyError("Missing Public_key")
        if not secret_key:
            raise MissingKeyError("Missing secret_key")
        api_key = b64encode(f"{public_key}:{secret_key}".encode('utf-8'))
        self.API_KEY = api_key.decode('utf-8')


    def set_headers(self):
        """
        sets headers for all HTTP requests sent by the client

        Args: None

        Returns: <class 'str'> representation of the header object.
        """
        return {
            "Authorization": f"Basic {self.API_KEY}"
        }

    def execute(self, query):
        """
        Executes any graphql query passed to it.

        Args:
            query (str): A string representation of the GraphQL query to be sent.
            This is usually generated by some helper classes and methods available in the library,
            however you may write raw queries in string format and pass them in. As an example:

            query = '''
                query{
                    getPrice(cryptocurrency: bitcoin)
                    {
                        id
                        side
                        status
                    }
                }
            '''
            resp = client.execute(query=query)
            print(resp)
        
        Returns: JSON formatted data from the buycoins server, but can be interfaced,
        as a dictionary <class 'Dict'> object. As such, with 'resp' from the previous
        example, we can do:
            print(resp['data'])
        """
        headers = self.set_headers()
        _req = requests.post(
            json={"query": query},
            url=BuyCoinsClient._URL,
            headers=headers
        )
         
        if _req.status_code == 200:
            return _req.json()
        else:
            print(_req)
    
    def get_active_price_id(
        self, response_fields: List,
        cryptocurrency=None
    ) -> str:
        """
        Helper method to fetch an active price ID for the purposes of making orders
        on the platform.

        Args:
            cryptocurrency (Optional[str]): a string value to indicate the crypto that's to
            be purchased, or that which its price ID is being sought after. 

        Returns: <class 'str'> an active ID if the cryptocurrency argument is specified
        otherwise it returns a generic list of dictionaries containing info about each 
        crypto-currency on the buycoins platform.
        """
        if cryptocurrency is None:
            query = GetPrices().queryObject(
                cryptocurrency=cryptocurrency
            )
            _req = requests.post(
                json={"query": query},
                url=BuyCoinsClient._URL,
                headers=self.set_headers()
            )
            if _req.status_code == 200:
                return _req.json()['data']['getPrices']
            else:
                return (_req.json(), _req.status_code)
        elif cryptocurrency is not None:
            query = GetPrices().queryObject(
                response_fields=response_fields
            )
            _req = requests.post(
                json={"query": query},
                url=BuyCoinsClient._URL,
                headers=self.set_headers()
            )
        if _req.status_code == 200:
            return _req.json()['data']['getPrices'][0]['id']
        else:
            return (_req.json(), _req.status_code)


client = BuyCoinsClient(public_key="I_8roV2FBaA",secret_key="n3n0CA3Zf3z1ADhAwUMv0CkeXt-xQqYP5Z31i0iGxA4")