"""

    AUTHOR:

        Khushal P Soonderji

    DATE:

        Saturday, 28th Dec., 2024

    OBJECTIVE:

        To handle all common actions related to payments from one place. This includes cases where you don't yet know
        the third-party client or it doesn't matter who the third-party client is. For example, take those cases when
        you just need to fetch one record about a payment.

    REFERENCES:

        N/A

    DOWNLOADS:

        N/A

"""


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                   IMPORT                                                      ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")

# My async utils:
from utils_v2.database.async_mysql_v2 import AsyncMySQL
from utils_v2.database.async_mongo_v2 import AsyncMongo
from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache

# Controllers:
from controllers_v2.finstitutions.payments.base import PaymentsController

# Models:
from models.core.user import CoreUserInfoModel
from models.core.auth_token import CoreAuthTokenModel
from models.api.finstitutions.payments.request import PGPaymentRequestData, PaymentRequestOneResult

# To work with datatypes:
from typing import List, Any

# To make HTTP requests:
import httpx


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                           MACROS / ONE-TIME INIT                                              ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# --- Nothing Yet


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                VARIABLES                                                      ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# --- Nothing Yet


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                  FUNCTIONS                                                    ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# --- Nothing Yet


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                   CLASSES                                                     ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


class AllPaymentsController(PaymentsController):

    # ┏┓
    # ┃ ┏┓┏┓┏╋┏┓┓┏┏╋┏┓┏┓
    # ┗┛┗┛┛┗┛┗┛ ┗┻┗┗┗┛┛

    def __init__(
            self,
            cache: AsyncRedisCache = None,
            http_client: httpx.AsyncClient = None,
            alert_url: str = None,
            debug: bool = True,
            debug_prefix: str = "All Payments (C) | ",
            debug_only_errors: bool = True
    ):

        """
        This is the foundational controller for all trading services. Use this for any smaller common tasks where you
        may not know the exact client beforehand.
        :param cache: The object to use for caching results from database calls.
        :param http_client: The HTTP client
        :param debug: Whether, or not, you would like to print debugging messages:
        :param debug_prefix: The prefix to print with the debugging messages.
        :param debug_only_errors: Whether you would like to print only error messages or all messages.
        :return: None.
        """

        # Invoke the parent's constructor:
        super().__init__(
            cache = cache,
            alert_url = alert_url,
            http_client = http_client,
            base_filter = None,
            debug = debug,
            debug_prefix = debug_prefix,
            debug_only_errors = debug_only_errors
        )

    # ┳┓            ┏┓
    # ┣┫┏┓┏┓┓┏┏┓┏╋  ┃┃┏┓┓┏┏┳┓┏┓┏┓╋┏
    # ┛┗┗ ┗┫┗┻┗ ┛┗  ┣┛┗┻┗┫┛┗┗┗ ┛┗┗┛
    #      ┗             ┛

    async def request_payment(
            self,
            sql_conn: AsyncMySQL,
            mongo_data_conn: AsyncMongo,
            auth_token: CoreAuthTokenModel,
            user_info: CoreUserInfoModel,
            payment_request: PGPaymentRequestData,
    ) -> PaymentRequestOneResult:

        """
        To request payment from someone through a payment gateway.
        :param sql_conn: Only needed when a payment gateway says that the credentials are invalid and the account needs
            to be disabled.
        :param mongo_data_conn: The database connection to use to perform this activity.
        :param auth_token: The token that has to be used to fetch the data.
        :param user_info: The info. of your user, so that you can identify who requested the payment.
        :param payment_request: The data that came in with the APi call.
        :return: The structured response form the payment gateway.
        """

        raise NotImplementedError

    async def handle_payment_callback(
            self,
            sql_conn: AsyncMySQL,
            mongo_data_conn: AsyncMongo,
            inbound_data: dict,
            inbound_headers: dict
    ) -> PaymentRequestOneResult:

        """
        Whenever the payment gateway sends an update about a requested payment, we use this method to update our records
        as per the specification of the third-party payment gateway.
        :param sql_conn: Only needed when a payment gateway says that the credentials are invalid and the account needs
            to be disabled.
        :param mongo_data_conn: The database connection to use to perform this activity.
        :param inbound_data: The data sent by the payment gateway in their update.
        :param inbound_headers: The headers sent by the payment gateway in their update.
        :return: A structured response about the process of updating the payment event.
        """

        # There are 3 main steps here:
        # 01. Add the payment's update event to the main record,
        # 02. Add the receipt (if payment successful),
        # 03. Disable the payment auth-token if the gateway says that the credentials are invalid.

        raise NotImplementedError


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                               MAIN PROGRAM                                                    ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


if __name__ == "__main__":

    pass
