# -*- coding: utf-8 -*-

import base64
import json
from xml.etree import ElementTree as eTree
import sysactions
from common import PrinterCommon
from fiscalpersistence import Tender
from msgbus import MBEasyContext
from typing import (
    List,
    Optional,
    Dict,
)

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

from printer import FiscalPrinter
from printer_wrapper import insert_space
from clichehelper import ClicheHelper
from _AposA8Helpers import (
    append_and_count_sale_items,
    append_coupon_fiscal_parameters,
    append_customer_name,
)
from _AposA8FiscalPrinter import AposA8FiscalPrinter


class SatAposA8FiscalPrinter(AposA8FiscalPrinter):
    def __init__(
        self,
        mb_context,                     # type: MBEasyContext
        print_customer_name,            # type: bool
        cliche_helper,                  # type: ClicheHelper
        customer_text_field,            # type: str
        printer_common,                 # type: PrinterCommon
        coupon_fiscal_parameters,       # type: Dict[str, bool]
        font_size_withdrawal_panel,     # type: str
    ):
        # type: (...) -> None

        super(SatAposA8FiscalPrinter, self).__init__(
            mb_context,
            print_customer_name,
            cliche_helper,
            customer_text_field,
            coupon_fiscal_parameters,
            font_size_withdrawal_panel,
        )

        self.customer_text_field = customer_text_field
        self.printer_common = printer_common
        self.cliche_helper = cliche_helper
        self.font_size_withdrawal_panel = font_size_withdrawal_panel

    def print_fiscal(self, posid, order, tenders, fiscal_request, fiscal_response, total_taxes, customer_name, url_sefaz=""):
        # type: (str, eTree.Element, list, eTree.Element, eTree.Element, dict, str, str) -> str
        xml = base64.b64decode(fiscal_request.text.strip())
        parsed_xml = eTree.XML(xml)
        n_c_fe = parsed_xml.find("infCFe/ide/nCFe").text
        model = sysactions.get_model(posid)

        report = self._fiscal_report(order, tenders, fiscal_response, n_c_fe, customer_name, model)

        qr_code = fiscal_response.find("QRCode").text.strip()
        sat_key = fiscal_response.find("satkey").text.strip()
        report.append(AposA8PrintLine(AposA8Align.CENTER, sat_key, AposA8CommandType.PRINT_BAR_CODE))
        report.append(AposA8PrintLine(AposA8Align.CENTER, '', AposA8CommandType.PRINT_BAR_CODE))
        report.append(AposA8PrintLine(AposA8Align.CENTER, qr_code, AposA8CommandType.PRINT_QR_CODE))

        text = "Consulte o QRCode pelo Aplicativo"
        report.append(AposA8PrintLine(AposA8Align.CENTER, text, AposA8CommandType.PRINT_TEXT))
        text = "De olho na nota disponivel"
        report.append(AposA8PrintLine(AposA8Align.CENTER, text, AposA8CommandType.PRINT_TEXT))
        text = "na AppStore (Apple) e Play Store (Android)"
        report.append(AposA8PrintLine(AposA8Align.CENTER, text, AposA8CommandType.PRINT_TEXT))

        report.append(AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

        tax_text = "%s %7.2f" % ("Valor aproximado dos tributos deste cupom", (
                    float(total_taxes['nacionalfederal']['value']) + float(total_taxes['estadual']['value'])))
        report.append(AposA8PrintLine(AposA8Align.CENTER,
                                      tax_text,
                                      AposA8CommandType.PRINT_TEXT))

        federal_tax = "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'])

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

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

        return json.dumps(report, default=lambda x: x.__dict__)

    def print_cancel(self, posid, data):
        return

    def _cancel_report(self, sat_fiscal_response, nCFe, total):
        return

    def _fiscal_report(self, order, tenders, sat_fiscal_response, nCFe, customer_name, model=None):
        # type: (eTree, List[Tender], eTree.Element, dict, str, str, Optional[eTree]) -> List[AposA8PrintLine]
        report = []

        for line in self.cliche_helper.get_cliche():
            report.append(AposA8PrintLine(AposA8Align.CENTER, line, AposA8CommandType.PRINT_TEXT))
        report.append(AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))
        report.append(AposA8PrintLine(AposA8Align.CENTER, "EXTRATO No. %s" % nCFe, AposA8CommandType.PRINT_TEXT))
        report.append(AposA8PrintLine(AposA8Align.CENTER, "CUPOM FISCAL ELETRONICO - SAT", AposA8CommandType.PRINT_TEXT))
        report.append(AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

        self._append_coupon_body(
            customer_name=customer_name,
            model=model,
            order=order,
            report=report,
            tenders=tenders,
            printer_common=self.printer_common,
        )

        report.append(AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

        # Campo de texto customizado exibido na área de informações adicionais
        if self.customer_text_field != "":
            for customer_text in self.customer_text_field.split('\\n'):
                report.append(AposA8PrintLine(AposA8Align.CENTER,
                                              customer_text.replace("\\n", ""),
                                              AposA8CommandType.PRINT_TEXT))
            report.append(
                AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

        satk = insert_space(sat_fiscal_response.find("satkey").text.strip(), 4)
        report.append(AposA8PrintLine(AposA8Align.CENTER,
                                      str(satk),
                                      AposA8CommandType.PRINT_TEXT))

        report.append(AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

        cpf_cnpj = sat_fiscal_response.find("CustomerCPF").text
        cpf_text = "Consumidor: %s" % ("Nao informado" if not cpf_cnpj else cpf_cnpj)
        report.append(AposA8PrintLine(AposA8Align.CENTER, cpf_text, AposA8CommandType.PRINT_TEXT))

        report.append(AposA8PrintLine(AposA8Align.CENTER,
                                      "SAT No. %s" % sat_fiscal_response.find("satno").text.strip(),
                                      AposA8CommandType.PRINT_TEXT))

        report.append(AposA8PrintLine(AposA8Align.CENTER,
                                      sat_fiscal_response.find("datetime").text.strip(),
                                      AposA8CommandType.PRINT_TEXT))

        return report
