import sysactions

from xml.etree import cElementTree as eTree

from typing import (
    Dict,
    List,
    Union,
)

from _AposA8PrintLine import AposA8PrintLine
from _AposA8Align import AposA8Align
from _AposA8CommandType import AposA8CommandType
from _AposA8Constants import AposA8Constants

from common import PrinterCommon
from old_helper import F, get_sale_line_priced_items, round_half_away_from_zero

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 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,             # type: []
    order,              # type: eTree
    printer_common      # type: PrinterCommon
):
    # type: (...) -> int

    items_amount = 0
    sale_lines = get_sale_line_priced_items(order.findall("SaleLine"))

    for line in sale_lines:
        line_params = _get_line_params(line)
        item_price, multiplied_qty, name, part_code, level = line_params
        measure_unit = line.get("measureUnit") if "measureUnit" in line.attrib else "un"
        items_amount += 1
        quantity = F(multiplied_qty)
        item_value = round_half_away_from_zero(F(item_price) / quantity, 2)
        line = "%-7.7s %-14.14s%6.3f%-3.2s%9.2f" % (part_code, name, quantity, measure_unit, item_value)
        string = ("%-5.40s %7.02f" % (line, F(item_price)))

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

    if float(order.get("tip", 0)) > 0:
        tips_lines = printer_common.get_tip_order(order, is_mobile=True)
        report.append(AposA8PrintLine(AposA8Align.CENTER, tips_lines, AposA8CommandType.PRINT_TEXT))

    return items_amount


def _get_line_params(
        line    # type: eTree
):
    # type: (...) -> Union[list, List[str]]

    return map(
                line.get,
                (
                    "itemPrice",
                    "multipliedQty",
                    "productName",
                    "partCode",
                    "level"
                )
        )

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_coupon_fiscal_parameters(
    coupon_fiscal_parameters,   # type: Dict[str, bool]
    report,                     # type: List
    order,                      # type: eTree.Element
):
    # type: (...) -> None

    if not any(coupon_fiscal_parameters.values()):
        return

    if coupon_fiscal_parameters["operator"]:
        user_id = order.get("sessionId").split("user=")[1].split(",")[0]
        operator_name = eTree.XML(sysactions.get_user_information(user_id)).find(".//user").get("LongName")[:15]
        text = AposA8PrintLine(
            align=AposA8Align.CENTER,
            text="Operador: {}".format(operator_name),
            command_type=AposA8CommandType.PRINT_TEXT,
        )
        report.append(text)

    if coupon_fiscal_parameters["order_or_table"]:
        order_id = order.get("orderId")
        table_property = order.find("CustomOrderProperties/OrderProperty[@key='TABLE_NAME']")
        table_name = table_property.get("value") if table_property is not None else ''
        table_name = table_name[:15] + "..." if len(table_name) > 15 else table_name
        if table_name:
            report.append(
                AposA8PrintLine(
                    align=AposA8Align.CENTER,
                    text="Pedido/Mesa: {}/{}".format(order_id[-4:], table_name),
                    command_type=AposA8CommandType.PRINT_TEXT,
                )
            )
        else:
            report.append(
                AposA8PrintLine(
                    align=AposA8Align.CENTER,
                    text="Pedido: {}".format(order_id[-4:]),
                    command_type=AposA8CommandType.PRINT_TEXT,
                )
            )

    if coupon_fiscal_parameters["pos_id"]:
        pos_id = order.get("posId")
        report.append(
            AposA8PrintLine(
                align=AposA8Align.CENTER,
                text="POS ID: {}".format(pos_id),
                command_type=AposA8CommandType.PRINT_TEXT,
            )
        )

    report.append(
        AposA8PrintLine(
            align=AposA8Align.CENTER,
            text=AposA8Constants.SEPARATOR_HASH,
            command_type=AposA8CommandType.PRINT_TEXT
        )
    )
