from helper import remove_accents
from pos_model import Order, XmlTenderTypeFromPOSMapper, TenderType, OrderTender

from _SatXmlPartBuilder import SatXmlPartBuilder
from satbuilder import ContextKeys
from typing import Dict


class PgtoBuilder(SatXmlPartBuilder):
    def __init__(self, tenders_type):
        # type: (Dict) -> None

        self.tenders_type = tenders_type
        self.tenders = self._get_tenders()

    def _get_tenders(
        self
    ):
        # type: (...) -> Dict[int, Dict]

        tenders = {}
        for tender in self.tenders_type.values():
            tenders[int(tender["tenderId"])] = tender

        return tenders

    def build_xml(self, order, context):
        # type: (Order, ContextKeys) -> unicode

        xml = "<pgto>"
        tag = "<MP><cMP>{0:>02}</cMP><vMP>{1:>0.2f}</vMP><cAdmC>{2}</cAdmC></MP>"

        max_order_tenders = 10

        if len(order.tenders) <= max_order_tenders:
            for tender in order.tenders:
                tender_type = XmlTenderTypeFromPOSMapper.get(tender.type)
                if tender.type in self.tenders:
                    t_pag = self.tenders[tender.type].get("tPag")
                    if t_pag is not None:
                        tender_type = int(self.tenders[tender.type].get("tPag"))

                cad_mc = self._get_cad_mc(tender)
                xml += tag.format(tender_type, tender.amount, cad_mc)
        else:
            tenders_amount = {}
            for tender in order.tenders:
                cad_mc = self._get_cad_mc(tender)
                tender_type = XmlTenderTypeFromPOSMapper.get(tender.type)

                if cad_mc not in tenders_amount:
                    tenders_amount[cad_mc] = {}
                if tender_type not in tenders_amount[cad_mc]:
                    tenders_amount[cad_mc][tender_type] = 0

                tenders_amount[cad_mc][tender_type] += tender.amount

            payment_groups = 0
            for cad_mc, tenders in tenders_amount.items():
                for tender_type in tenders:
                    amount = tenders[tender_type]
                    xml += tag.format(tender_type, amount, cad_mc)
                    payment_groups += 1

            if payment_groups > max_order_tenders:
                raise Exception(
                    "$ORDER_NOT_FINALIZED_DUE_TO_MAX_SAT_PAYMENT_GROUPS_REACHED|{}".format(max_order_tenders)
                )

        xml += "</pgto>"

        return xml

    def _get_cad_mc(
            self,
            tender  # type: OrderTender
    ):
        # type: (...) -> str

        if tender.type in [TenderType.credit, TenderType.debit] and tender.accreditor_sat not in ['', None]:
            return str(tender.accreditor_sat)

        others = "999"
        tender_description = str(remove_accents(tender.descr)).upper()
        if tender_description in self.tenders_type:
            tender_type_data_base = self.tenders_type[tender_description]
            cad_mc = str(tender_type_data_base.get("cAdmC", ""))
            return cad_mc if cad_mc.strip() else others

        return others
