from django import http
from django.conf.urls import url
from django.core.exceptions import ImproperlyConfigured
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

import requests
from mooch.base import BaseMoocher, csrf_exempt_m, require_POST_m
from mooch.signals import post_charge


class StripeMoocher(BaseMoocher):
    identifier = "stripe"
    title = _("Pay with Stripe")

    def __init__(self, *, publishable_key, secret_key, **kwargs):
        if any(x is None for x in (publishable_key, secret_key)):
            raise ImproperlyConfigured(
                "%s: None is not allowed in (%r, %r)"
                % (self.__class__.__name__, publishable_key, secret_key)
            )

        self.publishable_key = publishable_key
        self.secret_key = secret_key = secret_key
        super().__init__(**kwargs)

    def get_urls(self):
        return [url(r"^stripe_charge/$", self.charge_view, name="stripe_charge")]

    def payment_form(self, request, payment):
        return render_to_string(
            "mooch/stripe_payment_form.html",
            {
                "moocher": self,
                "payment": payment,
                "publishable_key": self.publishable_key,
                "charge_url": reverse("%s:stripe_charge" % self.app_name),
                "LANGUAGE_CODE": getattr(request, "LANGUAGE_CODE", "auto"),
            },
            request=request,
        )

    @csrf_exempt_m
    @require_POST_m
    def charge_view(self, request):
        instance = get_object_or_404(self.model, id=request.POST.get("id"))
        instance.payment_service_provider = self.identifier
        instance.transaction = repr(
            {key: values for key, values in request.POST.lists() if key != "token"}
        )
        instance.save()

        response = requests.post(
            "https://api.stripe.com/v1/charges",
            auth=(self.secret_key, ""),
            data={
                "amount": instance.amount_cents,
                "source": request.POST.get("token"),
                "currency": "CHF",
            },
            headers={"Idempotency-Key": instance.id.hex},
            timeout=5,
        )

        instance.charged_at = timezone.now()  # TODO handle 402 (card reject)
        instance.transaction = response.text
        instance.save()

        post_charge.send(sender=self, payment=instance, request=request)

        return http.HttpResponse("OK")
