import json
from ast import literal_eval
from xml.etree import cElementTree as eTree

import sysactions
from _AposA8PrintLine import AposA8PrintLine
from _AposA8Align import AposA8Align
from _AposA8CommandType import AposA8CommandType
from _AposA8Constants import AposA8Constants
from bustoken import create_token
from comp_exceptions import VoidOrderException
from old_helper import F, get_sale_line_priced_items
from msgbus import TK_SYS_NAK
from helper import remove_accents

APOS_DASH = AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT)
APOS_NEWLINE = AposA8PrintLine(AposA8Align.CENTER, "", AposA8CommandType.PRINT_TEXT)
APOS_HASH = AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_HASH, AposA8CommandType.PRINT_TEXT)


def add_loyalty_custom_text(report, order, custom_text):
    # type: (list, eTree.Element, dict) -> None
    loyalty_user_name = order.find("CustomOrderProperties/OrderProperty[@key='CUSTOMER_NAME']")
    loyalty_user_cpf = order.find("CustomOrderProperties/OrderProperty[@key='LOYALTY_SYSTEM_USER_CPF']")

    if loyalty_user_name is not None and loyalty_user_cpf is not None:
        name_and_cpf = custom_text["name_cpf"].format(nome_cliente=loyalty_user_name.get("value"),
                                                      cpf_cliente=loyalty_user_cpf.get("value"))
        report.append(AposA8PrintLine(AposA8Align.CENTER, name_and_cpf, AposA8CommandType.PRINT_TEXT))
    elif loyalty_user_cpf is not None:
        cpf = custom_text["cpf"].format(cpf_cliente=loyalty_user_cpf.get("value"))
        report.append(AposA8PrintLine(AposA8Align.CENTER, cpf, AposA8CommandType.PRINT_TEXT))
    else:
        non_participating = custom_text["non_participating"]
        report.append(AposA8PrintLine(AposA8Align.CENTER, non_participating, AposA8CommandType.PRINT_TEXT))

    report.append(APOS_NEWLINE)
    report.append(APOS_DASH)
    report.append(APOS_NEWLINE)


def get_whopper_wifi_data(order):
    whopper_wifi_property = order.find("CustomOrderProperties/OrderProperty[@key='WHOPPER_WIFI_CODE']")
    if whopper_wifi_property is not None:
        whopper_wifi_code = whopper_wifi_property.get("value")[0:4] + " " + whopper_wifi_property.get("value")[4:8]
    else:
        whopper_wifi_code = None
    return whopper_wifi_code


def append_items_header(report):
    product_header = "COD     DESCR          QTD UN    VL UNIT   TOTAL"
    report.append(AposA8PrintLine(AposA8Align.CENTER, product_header, AposA8CommandType.PRINT_TEXT))


def append_and_count_sale_items(report, order, model, tip_config):
    items_amount = 0
    sale_lines = get_sale_line_priced_items(order.findall("SaleLine"))
    un = "un"
    for line in sale_lines:
        item_price, unit_price, item_qty, name, part_code = map(line.get, (
            "correctItemPrice",
            "correctUnitPrice",
            "correctQty",
            "productName",
            "partCode"
        ))
        items_amount += 1
        line = "%-7.7s %-14.14s%5.3f%2.2s%9.02f" % (part_code, name, F(item_qty), un, F(unit_price))
        string = ("%-38.38s %9.02f" % (line, F(item_price)))

        report.append(AposA8PrintLine(AposA8Align.CENTER, string, AposA8CommandType.PRINT_TEXT))

    if order.get("tip", 0) and float(order.get("tip")) > 0:
        order_tip = F(order.get("tip"))
        tip_line = "%-7.7s %-14.14s%5.3f%2.2s%9.02f" % (tip_config['TipCode'],
                                                        sysactions.translate_message(model, "TIP_GIVEN").upper(),
                                                        F(1),
                                                        "un",
                                                        order_tip)
        tip_text = ("%-38.38s %9.02f" % (tip_line, order_tip))
        report.append(AposA8PrintLine(AposA8Align.CENTER, tip_text, AposA8CommandType.PRINT_TEXT))

    return items_amount


def append_whopper_wifi_code(report, model, whopper_wifi_code):
    if whopper_wifi_code is None or model is None:
        return

    whopper_wifi_code_text = sysactions.translate_message(model, "WIFI_PRINTER_MESSAGE")
    report.append(AposA8PrintLine(AposA8Align.CENTER, whopper_wifi_code_text, AposA8CommandType.PRINT_TEXT))

    wifi_access_code = sysactions.translate_message(model, "WIFI_ACCESS_CODE", "%s" % whopper_wifi_code)
    report.append(AposA8PrintLine(AposA8Align.CENTER, wifi_access_code, AposA8CommandType.PRINT_TEXT))


def append_tax_data(report, total_taxes):
    approx_value_text = "Valor aproximado dos tributos deste cupom"
    report.append(AposA8PrintLine(AposA8Align.LEFT, approx_value_text, AposA8CommandType.PRINT_TEXT))

    nacional_federal_value = total_taxes['nacionalfederal']['value']
    estadual_value = total_taxes['estadual']['value']

    total_tax_value = float(nacional_federal_value) + float(estadual_value)
    report.append(AposA8PrintLine(AposA8Align.RIGHT, "R$%7.2f" % total_tax_value, AposA8CommandType.PRINT_TEXT))

    nacional_federal_percent = total_taxes['nacionalfederal']['percent']
    estadual_percent = total_taxes['estadual']['percent']

    federal_tax = "Fed = R$%7.2f (%.2f%%), Est = R$%7.2f (%.2f%%)" % (
        nacional_federal_value,
        nacional_federal_percent,
        estadual_value,
        estadual_percent
    )
    report.append(AposA8PrintLine(AposA8Align.CENTER, federal_tax, AposA8CommandType.PRINT_TEXT))

    law_cite = "(Conforme Lei Fed. 12.741/2012)"
    report.append(AposA8PrintLine(AposA8Align.CENTER, law_cite, AposA8CommandType.PRINT_TEXT))

    report.append(APOS_DASH)


def append_garena_coupons(mb_context, order, report):
    TK_DECRYPT_GARENA_COUPON = create_token("F", "99", "2")

    garena_custom_property = order.find("CustomOrderProperties/OrderProperty[@key='GARENA_COUPONS']")
    garena_coupons = None
    if garena_custom_property is not None:
        garena_coupons = garena_custom_property.get("value").split("|")
    if not garena_coupons:
        return

    request_data = []
    for coupon in garena_coupons:
        coupon_obj = literal_eval(coupon)
        coupon_id = coupon_obj['couponId']
        request_data.append(coupon_id)

    try:
        ret = mb_context.MB_EasySendMessage(
            "Garena",
            TK_DECRYPT_GARENA_COUPON,
            data="|".join(request_data),
            timeout=5000000
        )
        if ret.token == TK_SYS_NAK or not ret.data:
            raise VoidOrderException("Error decrypting garena coupon")
    except:
        return report

    garena_coupon_data = {}
    decrypted_coupons = json.loads(ret.data)
    for coupon in decrypted_coupons:
        coupon_data = json.loads(coupon['coupon_data'])
        garena_coupon_data.setdefault(coupon_data['promo']['description'], []).append(coupon['decrypted_data'])

    for promo in garena_coupon_data:
        promo_without_accents = remove_accents(promo)
        report.append(AposA8PrintLine(AposA8Align.CENTER, promo_without_accents, AposA8CommandType.PRINT_TEXT))

        for decrypted_coupon in garena_coupon_data[promo]:
            report.append(AposA8PrintLine(AposA8Align.CENTER, decrypted_coupon, AposA8CommandType.PRINT_TEXT))

        report.append(APOS_DASH)
