# coding=utf-8
import base64

from modelcommon.electronicpayment import TransactionProcessors
from modelcommon.model import SitefResponse
from typing import (
    Any,
    Union,
    Optional,
)

from model import (
    CancelPaymentOrderData,
    ConfirmFinishPaymentData,
    PaymentResponseData,
)
from paymentprocessor import PaymentProcessor
from util import get_transaction_identifier


class FakePaymentProcessor(PaymentProcessor):
    def __init__(
        self,
        message_bus,        # type: MbContextMessageBus
        dialog_manager,     # type: DialogManager
        config,             # type: Group
        logger,             # type: Logger
        cache,              # type: Cache
    ):
        # type: (...) -> None

        super(FakePaymentProcessor, self).__init__(
            message_bus,
            dialog_manager,
            config,
            logger,
            cache,
        )

        self.pdv_tef = int(config.find_value("PdvTef") or config.find_value("PosId"))
        self.pos_id = int(config.find_value("PosId"))
        self.cache = cache

    def get_last_receipt(
        self,
        eft_processor,      # type: str
    ):
        # type: (...) -> str

        return self.cache.get_last_receipt(eft_processor=eft_processor)

    def connection_status(self, test_connection_data):
        return True

    def add_payment(self, start_payment_data):
        pos_id = start_payment_data.pos_id
        transaction_identifier = get_transaction_identifier(
            order_id=start_payment_data.order_id,
            tender_id=start_payment_data.electronic_type
        )

        card_brand = {
            1: "01",
            2: "02",
        }.get(start_payment_data.electronic_type, "99")

        self.dialog_manager.close_dialogs(pos_id)
        return PaymentResponseData(
            media="",
            result="0",
            card_number="4111XXXXXXXXXXXX",
            auth_code="1302",
            approved_amount=start_payment_data.amount,
            id_auth="08496898000142",
            cnpj_auth="68536379000192",
            bandeira=card_brand,
            receipt_merchant=base64.b64encode("Recibo de teste.\n MERCHANT\nSitef FAKE"),
            receipt_customer=base64.b64encode("Recibo de teste.\n CUSTOMER\nSitef FAKE"),
            expiration_date="05/2029",
            nsu="1234",
            transaction_processor=TransactionProcessors.FAKE,
            last_digits="1111",
            sat_acquirer="012",
            t_pag="03",
            t_band="01",
            nsu_host="4321",
            electronic_type=start_payment_data.electronic_type,
            transaction_identifier=transaction_identifier
        )

    def cancel_payment_order(
        self,
        cancel_payment_order_data,  # type: CancelPaymentOrderData
        additional_params="",       # type: Optional[str]
    ):
        # type: (...) -> Any[Union[SitefResponse, str]]

        response = SitefResponse()
        response.nsu = "123"
        response.nsu_host = "321"
        response.nsu_origin = "555"
        response.transaction_value = "10"
        response.customer_receipt = base64.b64encode("Recibo de teste CANCELAMENTO.\n CUSTOMER\nSitef FAKE")
        response.merchant_receipt = base64.b64encode("Recibo de teste CANCELAMENTO.\n MERCHANT\nSitef FAKE")
        response.transaction_identifier = get_transaction_identifier(
            order_id=cancel_payment_order_data.order_id,
            tender_id=cancel_payment_order_data.tender_id
        )
        return response

    def cancel_payment(self):
        return ""

    def finish_payment(self, finish_payment_data):
        return True

    def confirm_finish_payment(
        self,
        confirm_finish_payment_data     # type: ConfirmFinishPaymentData
    ):
        # type: (...) -> None

        pass

    def get_name(
        self,
    ):
        # type: (...) -> str

        self.register_eft_processor(
            pos_id=self.pos_id,
            processor_name=TransactionProcessors.FAKE,
        )

        return TransactionProcessors.FAKE

    def get_document(
        self,
        pos_id      # type: str
    ):
        # type: (...) -> str

        return "68536379000192"
