import json
import logging
import sysactions

from bustoken import TK_ELECTRONIC_PAYMENT_CACHE
from msgbus import (
    FM_PARAM,
    TK_SYS_ACK,
    MBMessage,
)
from sysactions import mbcontext
from typing import (
    Dict,
    Optional,
    List,
)

from actions.eft import get_electronic_payment_component_name
from tef import PrintReceipt

logger = logging.getLogger("PosActions")


def set_eft_cache(
    pos_id,             # type: str
    payment_data,       # type: Dict
    tender_id,          # type: int
    order_id,           # type: int
):
    # type: (...) -> None

    try:
        receipt_customer = payment_data.get("ReceiptCustomer", None)
        if receipt_customer is None:
            return

        receipt_data = {
            "order_id": order_id,
            "tender_id": tender_id,
            "receipt_customer": receipt_customer,
        }
        receipt_data = json.dumps(receipt_data)

        data = json.dumps(
            {
                "posId": pos_id,
                "eftProcessor": payment_data.get("TransactionProcessor"),
                "receiptCustomer": receipt_data,
             }
        )
        response = _send_message(
            pos_id=pos_id,
            data=data,
        )
        if response.token != TK_SYS_ACK:
            message = "NACK reprint last eft receipt. {} - {} - {}"
            logger.info(message.format(pos_id, response.token, response.data))

    except Exception as _:
        logger.info("Error set last eft receipt")


@sysactions.action
def reprint_last_eft_receipt(
    pos_id,                     # type: str
    eft_processor="",           # type: Optional[str]
    fiscalization_type="",      # type: Optional[str]
    error_title="$EFT",         # type: Optional[str]
):
    # type: (...) -> Dict

    error_message = "$ERROR_REPRINT_TEF_RECEIPT"
    eft_check = _check_eft_value(
        pos_id=pos_id,
        eft_value=eft_processor,
        error_message=error_message,
        error_title=error_title,
    )
    if not eft_check:
        return {}

    try:
        data = json.dumps(
            {
                "posId": pos_id,
                "eftProcessor": eft_processor,
            }
        )
        response = _send_message(
            pos_id=pos_id,
            data=data,
        )
        if response.token != TK_SYS_ACK or response.data in ['', None]:
            message = "NACK reprint last eft receipt. {} - {} - {}"
            logger.info(message.format(pos_id, response.token, response.data))
            sysactions.show_messagebox(
                posid=pos_id,
                message=error_message,
                title="$EFT",
                buttons="$OK",
            )
            return {}

        response_dict = json.loads(response.data)
        if response_dict.get('receipt_customer', {}) in [None, '']:
            return response_dict

        logger.info("Success reprint last eft receipt. {}".format(pos_id))
        reprint_receipt(
            pos_id=pos_id,
            receipts=[response_dict.get('receipt_customer')],
            fiscalization_type=fiscalization_type,
            error_title=error_title,
        )
        return response_dict
    except Exception as _:
        logger.info("Error reprint last eft receipt")


def _send_message(
    pos_id,     # type: str
    data,       # type: str
):
    # type: (...) -> MBMessage

    sitef_comp_name = get_electronic_payment_component_name(pos_id=pos_id)
    return mbcontext.MB_EasySendMessage(
        dest_name=sitef_comp_name,
        token=TK_ELECTRONIC_PAYMENT_CACHE,
        format=FM_PARAM,
        data=data,
        timeout=600000000,
    )


def reprint_receipt(
    pos_id,                     # type: str
    receipts,                   # type: List[str]
    fiscalization_type="",      # type: Optional[str]
    error_title="$EFT",         # type: Optional[str]
):
    # type: (...) -> bool

    reprinted = True
    for receipt in receipts:
        eft_check = _check_eft_value(
            pos_id=pos_id,
            eft_value=receipt,
            error_message="$PAYMENT_HAS_NO_TEF",
            error_title=error_title,
        )
        if not eft_check:
            reprinted = False
            continue

        printer_receipt = PrintReceipt(
            mb_context=mbcontext,
            logger=logger,
        )

        reprinted &= printer_receipt.reprint_receipt(
            pos_id=pos_id,
            receipts=[receipt],
            fiscalization_type=fiscalization_type,
        )

    return reprinted


def _check_eft_value(
    pos_id,                 # type: str
    eft_value,              # type: str
    error_message,          # type: str
    error_title="#$EFT",    # type: Optional[str]
):
    # type (...) -> bool

    if eft_value in ['', None]:
        sysactions.show_messagebox(
            posid=pos_id,
            message=error_message,
            title=error_title,
            buttons="$OK",
        )
        return False

    return True
