# -*- coding: utf-8 -*-
import base64
import json
import logging
import requests
import datetime

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

from model import (
    CancelPaymentOrderData,
    PaymentResponseData,
    PaymentResponseMessage
)
from paymentprocessor import PaymentProcessor

logger = logging.getLogger("ElectronicPayment")


class ConectCarPaymentProcessor(PaymentProcessor):

    def connection_status(self, test_connection_data):
        try:
            init_url = self.config.find_value("URL")
            requests.get(init_url, timeout=7.0)
            return True
        except requests.RequestException:
            return False

    def add_payment(self, start_payment_data):
        try:
            pos_id = start_payment_data.pos_id

            status, placa_json = self.get_placa_conectcar(pos_id)
            if status != 200:
                ret = self.dialog_manager.show_question(pos_id, "$ERROR_CONECTCAR_2",
                                                  buttons="$TRY_AGAIN|$CANCEL")
                if ret == '0':
                    status, placa_json = self.get_placa_conectcar(pos_id)
                else:
                    return PaymentResponseMessage("ConectCar: Pagamento cancelado")

            if status == 200:
                placa = json.loads(placa_json).get('placa')
                without_error, message = self.do_conectcar_payment(placa, start_payment_data.amount,
                                                                       start_payment_data.order_id, pos_id)
                if without_error:
                    return PaymentResponseData(
                        media='',
                        result='0',
                        card_number='4111XXXXXXXXXXXX',
                        auth_code='1302',
                        approved_amount=start_payment_data.amount,
                        id_auth='08496898000142',
                        cnpj_auth="68536379000192",
                        bandeira='4',
                        receipt_merchant=base64.b64encode("Recibo ConectCar"),
                        receipt_customer=base64.b64encode("Recibo ConectCar"),
                        expiration_date='05/2050',
                        nsu='1234',
                        transaction_processor="00051",
                        last_digits="1111",
                        sat_acquirer="012",
                        t_pag="",
                        t_band="01",
                        nsu_host="4321",
                        electronic_type=start_payment_data.electronic_type,
                        transaction_identifier="9876"
                    )
                else:
                    logger.error("Erro no pagamento com ConectCar")
                    return PaymentResponseMessage(message)
            else:
                return PaymentResponseMessage(placa_json)

        except Exception as ex:
            return PaymentResponseMessage("Erro pagamento ConectCar:{}".format(ex.message))

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

        # TODO: Add implementation
        pass

    def cancel_payment(self):
        return ""

    def finish_payment(self, finish_payment_data):
        if finish_payment_data.status == 0:
            logger.error("Erro ao finalizar pagamento com ConectCar - {}".format(finish_payment_data.pos_id))
        return ""

    def get_name(self):
        return "ConectCarElectronicPayment"

    def get_placa_conectcar(self, pos_id):
        try:
            auth, init_url, timeout = self.get_config_values()
            headers = {'Content-type': 'application/json', 'Authorization': auth}
            logger.info('get_placa_conectcar')
            url = "{}api/consultarleitura/idPdv/{}".format(init_url, pos_id)
            response = requests.get(
                url,
                headers=headers,
                timeout=timeout
            )
            if response.status_code == 200:
                return response.status_code, response.content
            else:
                return response.status_code, "$ERROR_CONECTCAR_3"
        except requests.RequestException:
            return 400, "$ERROR_CONECTCAR_1"

    def get_config_values(self):
        init_url = self.config.find_value("URL")
        auth = self.config.find_value("Auth")
        timeout = int(self.config.find_value("Timeout"))
        return auth, init_url, timeout

    def do_conectcar_payment(self, placa, amount, order_id, pos_id):
        try:
            auth, init_url, timeout = self.get_config_values()
            headers = {'Content-type': 'application/json', 'Authorization': auth}
            logger.info("Pagamento com conectcar: {}".format(order_id))
            float_amount = float(amount)
            payment_request = {
                'idPdv': "{}".format(pos_id),
                'meioPagamento': 'ConectCar',
                'placa': placa,
                'valor': float_amount,
                'data': datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
                'identificador': "{}".format(order_id)
            }
            url = "{}api/pagamento".format(init_url)
            response = requests.post(
                url,
                json=payment_request,
                headers=headers,
                timeout=15
            )
            if response.status_code == 200:
                logger.info("Código transação pagamento com conectcar: {}".format(response.status_code))
                return True, response
            return False, "$ERROR_CONECTCAR_4"
        except Exception:
            logger.error("ConectCar: Pagamento indisponivel. Ofereca outra opcao de pagamento")
            return False, "$ERROR_CONECTCAR_5"
