import requests


class Billplz():
    """
    Billplz Client

    Base class for interfacing Billplz API with convenience methods
    """

    def __init__(self, api_key, collection_id, test=False):
        """
        Initialize an instance of the Billplz Client

        :param api_key: Authorized API secret key to your billplz account
        :param collection_id: Collection ID that will contain the bills generated by this client
        :param test: Default False - Sets the base_url to live endpoint. True sets base_url to sandbox endpoint.

        Returns initialized instance of the Billplz Client
        """
        self.api_key = api_key
        self.collection_id = collection_id
        if test:
            self.base_url = self.__get_sandbox_endpoint()
        else:
            self.base_url = self.__get_live_endpoint()

    def create_bill_with_redirect(self, email, name, amount, description, callback_url, redirect_url, collection_id=None):
        """
        Method for creating a bill with a redirect_url on successful payment

        :param collection_id: Default will use client defined collection_id
        :param email: Required email address of the bill recepient
        :param name: Required name of the bill recepient
        :param amount: Required amount in cents i.e 100 = RM1.00
        :param callback_url: URL Endpoint to call on successful payment
        :param redirect_url: URL Endpoint to redirect user to upon successful or unsuccesful payment
        :param description: Bill description max 200chars, will be displayed on bill

        Returns success_status and redirect_url to bill as a Dictionary
        """

        if not collection_id:
            collection_id = self.collection_id

        try:
            params = {
                'collection_id': self.collection_id,
                'email': email,
                'name': name,
                'amount': amount,
                'callback_url': callback_url,
                'redirect_url': redirect_url,
                'description': description
            }

            response = requests.post(
                f'{self.base_url}/v3/bills',
                params=params,
                auth=self.__generate_authorization_headers()
            )

            return dict(
                is_success=True,
                redirect_url=response.json()['url']
            )

        except:
            return dict(
                is_success=False
            )

    def create_bill_without_redirect(self, email, name, amount, description, callback_url, collection_id=None):
        """
        Method for creating a bill with a redirect_url on successful payment

        :param collection_id: Default will use client defined collection_id
        :param email: Required email address of the bill recepient
        :param name: Required name of the bill recepient
        :param amount: Required amount in cents i.e 100 = RM1.00
        :param callback_url: URL Endpoint to call on successful payment
        :param description: Bill description max 200chars, will be displayed on bill

        Returns success_status and redirect_url to bill as a Dictionary
        """

        if not collection_id:
            collection_id = self.collection_id

        try:
            params = {
                'collection_id': self.collection_id,
                'email': email,
                'name': name,
                'amount': amount,
                'callback_url': callback_url,
                'description': description
            }

            response = requests.post(
                f'{self.base_url}/v3/bills',
                params=params,
                auth=self.__generate_authorization_headers()
            )

            return dict(
                is_success=True,
                redirect_url=response.json()['url']
            )

        except:
            return dict(
                is_success=False
            )

    def get_bill_status(self, bill_id):
        """
        Get the bill status

        :param bill_id: Existing Bill ID

        Returns tuple with success_status and dictionary of bill information
        """
        if not bill_id:
            return dict(
                is_success=False,
                reason='No Bill ID'
            )

        try:
            response = requests.get(
                f'{self.base_url}/v3/bills/{bill_id}',
                auth=self.__generate_authorization_headers()
            )

            return dict(
                is_success=True,
                bill=response.json()
            )
        except:
            return dict(
                is_success=False,
                reason='Client Error: Invalic Bill ID or API Key'
            )

    def get_collection(self, collection_id=None):
        """
        Get A Collection

        :param collection_id: Provide a collection_id to return or it will use default collection_id

        Returns dictionary of success_status and collection data
        """
        if not collection_id:
            collection_id = self.collection_id

        try:
            response = requests.get(
                f'{self.base_url}/v4/collections/{collection_id}',
                auth=self.__generate_authorization_headers()
            )

            data = response.json()

            return dict(
                is_success=True,
                collection=data
            )

        except:
            return dict(
                is_success=False,
                reason='Client Error: Invalid Collection ID or API Key')

    def __generate_authorization_headers(self):
        """
        Returns preset authorization headers
        """
        auth_key = requests.auth.HTTPBasicAuth(self.api_key, ':')
        return auth_key

    def __get_sandbox_endpoint(self):
        """
        Returns the sandbox API base URL
        """
        return "https://www.billplz-sandbox.com/api"

    def __get_live_endpoint(self):
        """
        Returns the live API base URL
        """
        return "https://www.billplz.com/api"
