# -*- coding: utf-8 -*-
# © 2017 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import os
import hashlib
import base64
import requests
from pytrustnfe.xml import render_xml, sanitize_response
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
from pytrustnfe.nfse.assinatura import Assinatura

URLS = {
    "producao": {
        "processar_nota": "https://nfps-e.pmf.sc.gov.br/api/v1/processamento/notas/processa",
        "cancelar_nota": "https://nfps-e.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela",
    },
    "homologacao": {
        "processar_nota": "https://nfps-e-hml.pmf.sc.gov.br/api/v1/processamento/notas/processa",
        "cancelar_nota": "https://nfps-e-hml.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela",
    },
}


def _render(certificado, method, **kwargs):
    path = os.path.join(os.path.dirname(__file__), "templates")
    xml_send = render_xml(path, "%s.xml" % method, False, **kwargs)

    cert, key = extract_cert_and_key_from_pfx(certificado.pfx, certificado.password)
    cert, key = save_cert_key(cert, key)
    signer = Assinatura(cert, key, certificado.password)
    xml_send = signer.assina_xml(xml_send, "")
    return xml_send


def _get_oauth_token(**kwargs):
    if kwargs["ambiente"] == "producao":
        url = "https://nfps-e.pmf.sc.gov.br/api/v1/autenticacao/oauth/token"
    else:
        url = "https://nfps-e-hml.pmf.sc.gov.br/api/v1/autenticacao/oauth/token"

    m = hashlib.md5()
    secret = "%s:%s" % (kwargs["client_id"], kwargs["secret_id"])
    auth = base64.b64encode(secret.encode("utf-8"))
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": "Basic %s" % auth.decode("utf-8").replace("\n", ""),
    }
    m.update(kwargs["password"].encode("utf-8"))
    password = m.hexdigest().upper()

    dados = (
        "grant_type=password&username=%s&password=%s&client_id=%s&client_secret=%s"
        % (kwargs["username"], password, kwargs["client_id"], kwargs["secret_id"])
    )
    r = requests.post(url, data=dados, headers=headers)
    if r.status_code == 200:
        return r.json()
    else:
        return r.json()


def _send(certificado, method, **kwargs):
    url = URLS[kwargs["ambiente"]][method]
    xml_send = kwargs["xml"]

    token = _get_oauth_token(**kwargs)
    if "access_token" not in token:
        raise Exception(
            "%s - %s: %s" % (token["status"], token["error"], token["message"])
        )
    kwargs.update({"numero": 1, "access_token": token["access_token"]})

    headers = {
        "Accept": "application/xml;charset=UTF-8",
        "Content-Type": "application/xml",
        "Authorization": "Bearer %s" % kwargs["access_token"],
    }
    r = requests.post(url, headers=headers, data=xml_send)

    response, obj = sanitize_response(r.text.strip())
    return {
        "sent_xml": xml_send,
        "received_xml": response.encode("utf-8"),
        "object": obj,
        "status_code": r.status_code,
    }


def xml_processar_nota(certificado, **kwargs):
    return _render(certificado, "processar_nota", **kwargs)


def processar_nota(certificado, **kwargs):
    if "xml" not in kwargs:
        kwargs["xml"] = xml_processar_nota(certificado, **kwargs)
    return _send(certificado, "processar_nota", **kwargs)


def xml_cancelar_nota(certificado, **kwargs):
    return _render(certificado, "cancelar_nota", **kwargs)


def cancelar_nota(certificado, **kwargs):
    if "xml" not in kwargs:
        kwargs["xml"] = xml_cancelar_nota(certificado, **kwargs)
    return _send(certificado, "cancelar_nota", **kwargs)


def consultar_nota(certificado, **kwargs):
    if kwargs["ambiente"] == "producao":
        url = "https://nfps-e.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (
            kwargs["numero"]
        )
    else:
        url = "https://nfps-e-hml.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (
            kwargs["numero"]
        )

    headers = {
        "Accept": "application/json",
        "Authorization": "Bearer %s" % kwargs["access_token"],
    }
    r = requests.get(url, headers=headers)
    if r.status_code == 200:
        return r.text
    else:
        return r.text
