import sysactions
from helper import (
    remove_accents,
    translate_pos_label,
)
from pos_model import Order
from typing import (
    Any,
    Dict,
    List,
    Optional,
)
from xml.etree import cElementTree as eTree


class InfAdicBuilderCommon(object):

    def __init__(
        self,                       # type: InfAdicBuilderCommon
        order,                      # type: Order
        customer_text_field,        # type: unicode
        tax_builder,                # type: Any
        coupon_fiscal_parameters,   # type: Dict[str, bool]
    ):
        # type: (...) -> None

        self.customer_text_field = customer_text_field
        self.tax_builder = tax_builder
        self.order = order
        self.coupon_fiscal_parameters = coupon_fiscal_parameters

    def build_common(self):
        # type: () -> unicode

        return u"<infAdic><infCpl>{0}</infCpl></infAdic>".format(self.get_inf_cpl())

    def get_inf_cpl(
        self,   # type: InfAdicBuilderCommon
    ):
        # type: (...) -> unicode

        tax_data = self._get_tax_data(order=self.order.order_picture_xml)
        order_identifier = self._get_order_identifier(order=self.order.order_picture_xml)
        delivery_info = self._get_delivery_partner_and_short_reference(order=self.order.order_picture_xml)
        customer_text_field = remove_accents(text=self.customer_text_field).replace("\n", "///")

        inf_cpl = [tax_data, order_identifier, delivery_info, customer_text_field]
        xml = "///".join([x.strip() for x in inf_cpl if x.strip()])

        return xml

    def _get_tax_data(self, order):
        # type: (Order) -> unicode

        total_taxes = self.tax_builder.ibpt_tax_calculator(order)
        total_tax_amount = float(total_taxes['nacionalfederal']['value']) + float(total_taxes['estadual']['value'])
        xml = "%-44s R$%7.2f - " % ("Valor aproximado dos tributos deste cupom", total_tax_amount)
        xml += "Fed. R$%7.2f (%.2f%%) Est. R$%7.2f (%.2f%%)" % (total_taxes['nacionalfederal']['value'],
                                                                total_taxes['nacionalfederal']['percent'],
                                                                total_taxes['estadual']['value'],
                                                                total_taxes['estadual']['percent'])
        xml += " (Conforme Lei Fed. 12.741/2012)"

        return remove_accents(xml)

    def _get_order_identifier(
        self,   # type: InfAdicBuilderCommon
        order,  # type: eTree.Element
    ):
        # type: (...) -> unicode

        coupon_fiscal_text = []
        if self.coupon_fiscal_parameters["operator"]:
            self._read_operator_info(
                coupon_fiscal_text=coupon_fiscal_text,
                order=order,
            )

        if self.coupon_fiscal_parameters["order_or_table"]:
            self._read_order_or_table_info(
                coupon_fiscal_text=coupon_fiscal_text,
                order=order,
            )

        if self.coupon_fiscal_parameters["pos_id"]:
            self._read_pos_id_info(
                coupon_fiscal_text=coupon_fiscal_text,
                order=order,
            )

        order_identification = ""
        if len(coupon_fiscal_text) > 0:
            order_identification = " / ".join(coupon_fiscal_text)

        return remove_accents(text=order_identification)

    @staticmethod
    def _read_pos_id_info(
        coupon_fiscal_text,     # type: List[str]
        order,                  # type: eTree.Element
    ):
        # type: (...) -> None

        pos_id = order.get("posId")
        model = sysactions.get_model(posid=pos_id)
        pos = translate_pos_label(model=model)
        coupon_fiscal_text.append("{} ID: {}".format(pos, pos_id))

    @staticmethod
    def _read_order_or_table_info(
        coupon_fiscal_text,     # type: List[str]
        order,                  # type: eTree.Element
    ):
        # type: (...) -> None

        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:
            coupon_fiscal_text.append("Pedido/Mesa: {}/{}".format(order_id[-4:], table_name))
        else:
            coupon_fiscal_text.append("Pedido: {}".format(order_id[-4:]))

    def _read_operator_info(
        self,                   # type: InfAdicBuilderCommon
        coupon_fiscal_text,     # type: List[str]
        order,                  # type: eTree.Element
    ):
        # type: (...) -> None

        user_id = self._get_user_id_from_session_id(session_id=order.get("sessionId"))
        if not user_id:
            return

        operator_name = user_id
        user_info = sysactions.get_user_information(user_number=user_id)
        if user_info:
            user = eTree.XML(user_info).find(".//user")
            operator_name = user.get("LongName")[:15] if user is not None else user_id

        coupon_fiscal_text.append("Operador: {}".format(operator_name))

    @staticmethod
    def _get_delivery_partner_and_short_reference(
        order,  # type: eTree.Element
    ):
        # type: (...) -> str

        delivery_partner = order.find("CustomOrderProperties/OrderProperty[@key='PARTNER']")
        if delivery_partner is not None:
            short_reference = order.find("CustomOrderProperties/OrderProperty[@key='SHORT_REFERENCE']")
            if short_reference is not None:
                return "{}: {} ".format(delivery_partner.get("value").upper(), short_reference.get("value").upper())

        return " "

    @staticmethod
    def _get_user_id_from_session_id(
        session_id,     # type: str
    ):
        # type: (...) -> Optional[str]

        for data in session_id.split(","):
            if data.startswith("user="):
                return data.split("=")[1]

        return None
