from typing import (
    Any,
    Dict,
    List,
)
from xml.etree import cElementTree as eTree

from common import FiscalOrderTotals
from common.builder_functions import get_optional_customer_doc
from model import FiscalPaymentTypes
from nreports.utils import get_logo_image_str
from nreports_api.shared import JSON
from .._BaseFiscalSat import BaseFiscalSat


class FiscalCouponSatBuilder(BaseFiscalSat):

    def build_data(
        self,
        data_to_build: JSON,
        **kwargs: Any,
    ) -> Dict[str, JSON]:

        fiscal_xml = kwargs["fiscalXml"]

        fiscal_order_totals = FiscalOrderTotals(fiscal_xml=fiscal_xml)
        customer_document = get_optional_customer_doc(fiscal_xml=fiscal_xml)

        self._build_header(
            data_to_build=data_to_build,
            fiscal_xml=fiscal_xml,
        )
        data_to_build["STORE_IMG_LOGO"] = get_logo_image_str(image_path=self.images_path["STORE_IMG_LOGO"])

        self._build_body(
            data_to_build=data_to_build,
            fiscal_xml=fiscal_xml,
            fiscal_order_totals=fiscal_order_totals,
            customer_document=customer_document,
            products=self._get_item_products(fiscal_xml=fiscal_xml),
            tenders=self._get_item_tenders(fiscal_xml=fiscal_xml),
        )
        self._build_footer(
            data_to_build=data_to_build,
            fiscal_xml=fiscal_xml,
            customer_document=customer_document,
        )

        return data_to_build

    @staticmethod
    def _get_item_products(
        fiscal_xml: eTree.Element,
    ) -> List[Dict[str, str]]:

        item_products: List[Dict[str, str]] = []
        for item_product in fiscal_xml.findall(".//det/prod"):
            item_products.append(
                {
                    "ITEM_PRODUCT_CODE": item_product.find("cProd").text,
                    "ITEM_PRODUCT_NAME": item_product.find("xProd").text,
                    "ITEM_PRODUCT_QUANTITY": f"{float(item_product.find('qCom').text):.3f}",
                    "ITEM_PRODUCT_UNIT": item_product.find("uCom").text.upper(),
                    "ITEM_PRODUCT_PRICE": f"{float(item_product.find('vUnCom').text):.2f}",
                    "ITEM_PRODUCT_TOTAL_PRICE": f"{float(item_product.find('vProd').text):.2f}",
                }
            )

        return item_products

    @staticmethod
    def _get_item_tenders(
        fiscal_xml: eTree.Element,
    ) -> List[Dict[str, str]]:

        tender_types_by_id = {x[0]: x[1] for x in FiscalPaymentTypes.list_values()}
        tenders: List[Dict[str, str]] = []
        for item_product in fiscal_xml.findall(".//pgto/MP"):
            tender_name_type = tender_types_by_id.get(
                item_product.find("cMP").text,
                FiscalPaymentTypes.OUTROS.value[1],
            )

            tenders.append({
                "TENDER_TYPE": tender_name_type.upper(),
                "TENDER_VALUE": item_product.find("vMP").text,
            })

        return tenders
