"""

    AUTHOR:

        Khushal P Soonderji

    DATE:

        Tuesday, 3rd Dec., 2024

    OBJECTIVE:

        To list e-mails by their token identifier. Remember that the 'token identifier' is the '_id' of the document in
        MongoDB that holds the tokens to authorize the e-mail id whose mails are being accessed.

    REFERENCES:

        N/A

    DOWNLOADS:

        N/A

    NOTES:

        N/A

"""


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


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

# For using Quart:
from quart import Blueprint, current_app, g, request

# My utils:
from utils_v2.string import json
from utils_v2.database.async_mongo_v2 import AsyncMongo
from utils_v2.api.codes import StatusCodes, HttpCodes
from utils_v2.api.response import ResponseModel
from utils_v2.api.async_quart import (
    make_ordered_json,
    set_api_version,
    read_input,
    get_session_info,
    log_request_to_mongo,
    log_chain_to_mongo,
    should_not_be_under_maintenance,
    only_whitelisted_ips,
    limit_rate,
    validate_input,
    handle_cancelled_request
)

# GMail-related utils:
from utils_v2.goog.gmail.gmail_client import SCOPES_GMAIL_MAIL_MANAGEMENT
from utils_v2.goog.models.auth_tokens import GoogleAuthTokens

# Common:
from shared import constants

# Data Models:
from models.api.mail.list import MailListRequestHeaders, MailListRequestData

# To work with datatypes:
from typing import Literal

# For asynchronous activities:
import asyncio

# To work with date and time:
import datetime

# Helpers:
from api.helpers.user import token_check


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


# Related to Quart:
mail_list_bp = Blueprint("mail_list", __name__)


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


# --- Nothing Yet


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


@mail_list_bp.record_once
def init(blueprint_setup_state):

    # This gets called when the blueprint is registered.
    # Consider this to be a one-time setup for the whole blueprint:
    pass


# ---------------------------------------------------------------------------------------------------------------------


@mail_list_bp.route("/list", methods = ["GET"])
@mail_list_bp.route("/list/id/token", methods = ["GET", "POST"])
@mail_list_bp.route("/list/tags", methods = ["GET", "POST"])
@set_api_version(api_version = "1.0.0")
@read_input(sanitize_headers = False, sanitize_data = False)
@get_session_info(key = "X-Session-Token", session_coro = "get_session")
@log_request_to_mongo(
    attr_name = "logs_mongo",
    project = constants.PROJECT_NAME,
    log_type = constants.MODULE_NAME,
    operation = "mailListByTokIdApi",
    log_input = True,
    log_output = 1,
    sensitive_keys = ["sessionToken", "X-Session-Token"]
)
@log_chain_to_mongo(attr_name = "logs_mongo")
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
@validate_input(
    header_validator = lambda x: MailListRequestHeaders(**x).model_dump(),
    data_validator = lambda x: MailListRequestData(**x)
)
@handle_cancelled_request()
async def list_mails(
        inbound_headers: dict | MailListRequestHeaders = None,
        inbound_data: dict | MailListRequestData = None,
        inbound_files: dict = None,
        **kwargs
):

    """
    Use this endpoint when the user wants to fetch the list of mails. The shortlisting here will be done by way of the
    token identifier. Any no. of 'tokenId' objects will be given by the client.
    :param inbound_headers: auto-extracted by the decorators.
    :param inbound_data: auto-extracted by the decorators.
    :param inbound_files: auto-extracted by the decorators.
    :param kwargs: Any number of extra inputs supplied by the decorators.
    :return: A standard response structure.
    """

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

    # If the session token is invalid/expired:
    if kwargs.get("session_info") is None:
        return ResponseModel(
            status_code = StatusCodes.FAILED,
            http_code = HttpCodes.UNAUTHORIZED,
            message = "invalid session"
        )

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

    # Get the token ids from the token keys:
    auth_tokens = await current_app.mail_controller.get_tokens(
        mongo_conn = current_app.data_mongo,
        token_keys = inbound_data.tokenKeys
    )
    token_ids = [t.authTokenId for t in auth_tokens]

    # Build the additional filter:
    additional_filter = {}
    if inbound_data.tags: additional_filter["tags"] = {"$in": inbound_data.tags}
    additional_filter = additional_filter or None

    # Get the mails:
    mails_list = await current_app.mail_controller.list_mails(
        mongo_conn = current_app.data_mongo,
        token_ids = token_ids,
        limit = inbound_data.count,
        skip = inbound_data.fromCount,
        additional_filter = additional_filter
    )

    # Done here:
    return ResponseModel(
        status_code = StatusCodes.OK if mails_list else StatusCodes.FAILED,
        http_code = HttpCodes.SUCCESS if mails_list else HttpCodes.NOT_FOUND,
        data = [mail.preview for mail in mails_list],
        message = f"{len(mails_list) if mails_list else 0} mail(s) found"
    )


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


if __name__ == "__main__":

    pass
