# -*- 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 printer_wrapper import insert_space
from clichehelper import ClicheHelper
from _AposA8FiscalPrinter import AposA8FiscalPrinter
from _AposA8Helpers import (
    append_tax_data,
    APOS_DASH,
    split_lines,
    build_call_id,
)


class SatAposA8FiscalPrinter(AposA8FiscalPrinter):
    def __init__(
        self,
        mb_context,                     # type: MBEasyContext
        order_ref_ids,                  # type: list
        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
        danfe_font_size_mobile,         # type: str
        order_ref_position,             # type: str
    ):
        # type: (...) -> None

        super(SatAposA8FiscalPrinter, self).__init__(
            mb_context=mb_context,
            order_ref_ids=order_ref_ids,
            cliche_helper=cliche_helper,
            customer_text_field=customer_text_field,
            coupon_fiscal_parameters=coupon_fiscal_parameters,
            font_size_withdrawal_panel=font_size_withdrawal_panel,
            danfe_font_size_mobile=danfe_font_size_mobile,
            order_ref_position=order_ref_position,
        )

        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
        self.danfe_font_size_mobile = danfe_font_size_mobile

    def print_fiscal(
        self,
        pos_id,             # type: str
        order,              # type: eTree.Element
        tenders,            # type: list
        fiscal_request,     # type: eTree.Element
        fiscal_response,    # type: eTree.Element
        total_taxes,        # type: dict
        url_sefaz="",       # type: str
        is_reprint=False,   # type: Optional[bool]
    ):
        # type: (...) -> 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(pos_id)

        report = self._fiscal_report(
            order=order,
            tenders=tenders,
            sat_fiscal_response=fiscal_response,
            n_c_fe=n_c_fe,
            model=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 De olho na nota disponivel na AppStore (Apple)"
        split_lines(
            report=report,
            text=text,
            font_size=self.danfe_font_size_mobile,
        )

        text = "e Play Store (Android)"
        report.append(self._get_text_line(text=text))

        report.append(APOS_DASH)
        append_tax_data(
            report=report,
            total_taxes=total_taxes,
            font_size=self.danfe_font_size_mobile,
        )

        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,                  # type: eTree.Element
        tenders,                # type: List[Tender]
        sat_fiscal_response,    # type: eTree.Element
        n_c_fe,                 # type: str
        model=None,             # type: Optional[eTree]
    ):
        # type: (...) -> List[AposA8PrintLine]

        report = []

        if self.order_ref_position == "BEFORE_FISCAL_DATA":
            build_call_id(
                model=model,
                report=report,
                order=order,
                font_size_withdrawal_panel=self.font_size_withdrawal_panel,
                printer_common=self.printer_common,
                order_ref_ids=self.order_ref_ids,
                position="before",
            )

        self._append_cliche(report=report)

        self._append_header(
            report=report,
            n_c_fe=n_c_fe,
        )

        report.append(APOS_DASH)

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

        report.append(APOS_DASH)

        if self.customer_text_field != "":
            for customer_text in self.customer_text_field.split('\\n'):
                report.append(self._get_text_line(text=customer_text.replace("\\n", "")))

            report.append(APOS_DASH)

        self._append_danfe_key(
            report=report,
            key=sat_fiscal_response.find("satkey").text.strip(),
        )
        report.append(APOS_DASH)

        cpf_cnpj = sat_fiscal_response.find("CustomerCPF").text
        cpf_text = "Consumidor: %s" % ("Nao informado" if not cpf_cnpj else cpf_cnpj)
        report.append(self._get_text_line(text=cpf_text))

        sat_number = "SAT No. %s" % sat_fiscal_response.find("satno").text.strip()
        report.append(self._get_text_line(text=sat_number))

        report.append(self._get_text_line(text=sat_fiscal_response.find("datetime").text.strip()))

        return report

    def _append_header(
        self,
        n_c_fe,     # type: str
        report,     # type: List[AposA8PrintLine]
    ):
        # type: (...) -> None

        report.append(
            self._get_text_line(
                text="EXTRATO No. %s" % n_c_fe,
            )
        )

        report.append(
            self._get_text_line(
                text="CUPOM FISCAL ELETRONICO - SAT",
            )
        )

