import urllib

import requests
from django.contrib.auth import login
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.views import View
from django.conf import settings
from django.shortcuts import redirect, render
from django.http import JsonResponse
import stripe
import json
from backoffice.forms.signup import SignupForm
from tixsell import settings
from backoffice.models import *

from django.views.decorators.csrf import csrf_exempt

from rest_framework import status, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
import stripe 
from django.views import View
from django.urls import reverse
from django.shortcuts import redirect
from django.http import HttpResponse, HttpResponseRedirect
import stripe
stripe.api_key = settings.STRIPE_API_KEY
import logging 
import hmac
import hashlib
from django.core.exceptions import PermissionDenied 
import json
from types import SimpleNamespace 
from web3 import Web3
from django.template import loader
def is_valid_signature_for_string_body(
    body: str, signature: str, signing_key: str
) -> bool:
    digest = hmac.new(
        bytes(signing_key, "utf-8"),
        msg=bytes(body, "utf-8"),
        digestmod=hashlib.sha256,
    ).hexdigest()

    return signature == digest

logger = logging.getLogger('django')
logger_stripe = logging.getLogger('stripe')
"""
class StripeShifterOnboardView(APIView):
    #permission_classes = (permissions.IsAuthenticated,)

    # create account and send onboarding link
    def get(self, request, format='json'):
        seller_profile = Seller.objects.get(user_id=self.request.user)
        refresh_url = reverse('stripe-refresh-account-url')
        return_url = reverse('stripe-return-account-url')

        print(refresh_url)
        print(return_url)

        # if already exists then redirect to complete onboarding
        if ShifterStripeInformation.objects.filter(shifterProfile=shifter_profile).exists():
            return redirect(refresh_url)
        
        # create and store account info
        stripe.api_key = STRIPE_API_KEY
        acct = stripe.Account.create(type="express", business_type="individual")
        shifter_payment_info = ShifterStripeInformation(shifterProfile=shifter_profile, account_id=acct.id)
        shifter_payment_info.save()

        # create and send account link for connect onboarding
        acct_link = stripe.AccountLink.create(
        account=acct.id,
        refresh_url=refresh_url,
        return_url=return_url,
        type="account_onboarding",
        )

        return Response(acct_link, status=status.HTTP_201_CREATED)
"""
def StripeShifterAccountURLRefreshView(request,id):
	seller = Seller.objects.get(user__id=id)
	# redirect to account link to do onboarding
	acct_id = seller.stripe_user_id
	refresh_url = request.build_absolute_uri(reverse('stripe-refresh-account-url', kwargs={'uuid': seller.user.id} ))
	return_url = request.build_absolute_uri(reverse('stripe-return-account-url', kwargs={'uuid': seller.user.id} ))
	
	acct_link = stripe.AccountLink.create(
            account=acct_id,
            refresh_url=refresh_url,
            return_url=return_url,
            type="account_onboarding",
        )

	return HttpResponseRedirect(acct_link.url)


def home(request):
    return render(request, 'home.html', {})

def doChecks(fromAddress,toAddress,tokens,erc721TokenId,txHash):
    #si 1st mint on ignore
    if fromAddress=="0x0000000000000000000000000000000000000000":
        logger.info("==== Nouveau mint de NFT on stop")
        return HttpResponse(status=200)
    for ticket in tokens:
        #check tokenId 
        if ticket.ticketId==-1 and ticket.lastOwner==settings.SELLTIX_WALLET and ticket.hashedTicket=="TO_BE_SET":
            ticket.ticketId=str(erc721TokenId) 
            ticket.transactionHash = txHash
            ticket.save()
        else:
            if ticket.ticketId==erc721TokenId:
                doAssignement=True
                if ticket.refUser:
                    if ticket.refUser.walletAddress.lower()==toAddress.lower():
                        logger.info("[WebHook] Same owner do nothing")
                        doAssignement=False
                    else:
                        logger.info("[WebHook] Different owner")
                                    
                if doAssignement:                                    
                    #find a user with this wallet ?
                    userToAssign=None 
                    logger.info("[WebHook] ====Do assignement chercher un user dont walletAddress vaut %s"%toAddress.lower())
                    try:
                        user = User.objects.get(walletAddress__iexact=toAddress.lower())
                        logger.info("[WebHook]user trouve on change association %s"%user)
                        userToAssign = user
                    except Exception as e:
                        logger.info(e)
                        logger.info("[WebHook] ===Pas de user")
                                            
                    # Create an history
                    ticketHistory = TicketHistory()
                    ticketHistory.refUser = ticket.refUser
                    ticketHistory.wallet = ticket.lastOwner
                    ticketHistory.pricePaid = ticket.pricePaid
                    ticketHistory.save()
                    # Update ticket
                    ticket.refUser=userToAssign
                    ticket.lastOwner = toAddress
                    #NOTE: on ne connait pas le nouveau prix payé quand ça provient de la blockchain !!!
                    try:
                        api_key = settings.ALCHEMY_ACCESS_KEY
                        url = settings.ALCHEMY_API_ENDPOINT+api_key
                                          
                        payload = {
                            "id": 1,
                            "jsonrpc": "2.0",
                            "params": [txHash],
                            "method": "eth_getTransactionByHash"
                        }
                        headers = {
                            "accept": "application/json",
                            "content-type": "application/json"
                        }

                        response = requests.post(url, json=payload, headers=headers)
                        if response.status_code==200:
                            data = json.loads(response.text)
                            if data["result"]:                                        
                                valueHex = data["result"]["value"]
                                value = float.fromhex(valueHex)
                                finalPrice = Web3.from_wei( value,'ether')
                                ticket.pricePaid = finalPrice
                    except Exception as e:
                        logger.info(e)
                    #add history
                    ticket.owners.add(ticketHistory)
                    ticket.save()

@csrf_exempt
def webhookAlchemy(request):
    if request.method == 'POST':
        payload = str(request.body, request.encoding or "utf-8")
        logger.info("===On recoit webhook ")
        logger.info(payload)
        logger.info("===On recoit attend 5 secondes")
        import time
        time.sleep(5)
        logger.info("===On se reveille et on checke")
        data = json.loads(payload)
        # {"webhookId":"wh_wkv6n9i4f1sv3lu2","id":"whevt_dtp7wp4hy87vlr4r","createdAt":"2023-11-23T13:19:36.494101126Z","type":"NFT_ACTIVITY","event":{"eventDetails":"<EVENT_DETAILS>"}}
       
        # Si pas deja trouvé, on store sinon on ne fait rien et on sort
        canCheck = True
        webhookId = data["id"]
        type = data["type"]
        nbTrouve = WebHook.objects.filter(webhookId=webhookId).count()
        if nbTrouve > 0:
            canCheck=False 
        else:
            webhook = WebHook()
            webhook.webhookId = webhookId
            webhook.payload = data 
            webhook.save()

        
        if type=="NFT_ACTIVITY" and canCheck:
            event = data["event"]
            if "activity" in event:
                activity = event["activity"][0]
                if activity["category"]=="erc721":
                    fromAddress = activity["fromAddress"]
                    toAddress = activity["toAddress"]
                    erc721TokenId = int(activity["erc721TokenId"],0)
                    contractAddress = activity["contractAddress"]
                    txHash = activity["hash"]
                    logger.info("[WebHook] Doit trouver token "+str(erc721TokenId)+" pour contrat "+contractAddress+" newOwner "+toAddress)
                    # adapt ticket avec -1 doit Être assigné...
                    tokens = Ticket.objects.filter(refTicketType__refEvent__ticketContract__iexact=contractAddress)
                    if tokens.exists():
                       doChecks(fromAddress,toAddress,tokens,erc721TokenId,txHash)
                    else:
                        # Try for content 
                        tokens = Ticket.objects.filter(refContent__ticketContract__iexact=contractAddress)
                        if tokens.exists():
                            doChecks(fromAddress,toAddress,tokens,erc721TokenId,txHash)
                        else:
                            logger.info("==== Ticket non trouvé sur le backend !!!")
                            #:sauver info et prévenir SellTix
                            from backoffice.helpers import sendEmail
                            message="Billet minté sur blockchain non trouvé dans backend  contrat:<b>%s</b> Token: %d"%(contractAddress,erc721TokenId)
                            sendEmail("csurbier@idevotion.fr","[SellTix] Ticket miné mais creation backend failed",message)
                        
        return HttpResponse(status=200)
    else:
       return HttpResponse(status=404)
@csrf_exempt
def webhookStripe(request):
    import stripe
    stripe.api_key = settings.STRIPE_API_KEY
    if request.method == 'POST':
        payload = request.body
        sig_header = request.META['HTTP_STRIPE_SIGNATURE']
        event = None
        from tixsell.settings import STRIPE_ENDPOINT
        endpoint_secret = STRIPE_ENDPOINT
        try:
            event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
        except ValueError as e:
            # Invalid payload
            logger.error(e)
            return HttpResponse(status=400)
        except stripe.error.SignatureVerificationError as e:
            # Invalid signature
            logger.error(e)
            return HttpResponse(status=400)
        logger_stripe.info(event)
          

        return HttpResponse(status=200)
    else:
        return HttpResponse(status=404)


@csrf_exempt
def webhookStripeTest(request):
    import stripe
    stripe.api_key = settings.STRIPE_API_KEY
    
    if request.method == 'POST':
        payload = request.body
        sig_header = request.META['HTTP_STRIPE_SIGNATURE']
        event = None
        from tixsell.settings import STRIPE_ENDPOINT
        endpoint_secret = STRIPE_ENDPOINT
        try:
            event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
        except ValueError as e:
            # Invalid payload
            logger.error(e)
            return HttpResponse(status=400)
        except stripe.error.SignatureVerificationError as e:
            # Invalid signature
            logger.error(e)
            return HttpResponse(status=400)
        logger_stripe.info(event)
          

        return HttpResponse(status=200)
    else:
        return HttpResponse(status=404) 
def signup(request):
    if request.method == 'POST':
        form = SignupForm(request.POST)
        if form.is_valid():
            user = form.save()
            seller_profile = Seller()
            seller_profile.user = user
            #Create stripe user account
            account = stripe.Account.create(
                country="FR",
                type="express",
                capabilities={"card_payments": {"requested": True}, "transfers": {"requested": True}} 
            )
            logger.info("===On recoit de stripe ")
            logger.info(account)
            seller_profile.stripe_user_id = account["id"]
            seller_profile.stripe_account_json = json.dumps(account)
            seller_profile.save()
            refresh_url = request.build_absolute_uri(reverse('stripe-refresh-account-url',kwargs={'uuid': user.id} ))
            return_url = request.build_absolute_uri(reverse('stripe-return-account-url',kwargs={'uuid': user.id} ))
            logger.info("Return url %s"%return_url)
            logger.info("refresh_url url %s"%refresh_url)
            
            # on crée le lien de redirection
            accountLink = stripe.AccountLink.create(
                account=account["id"],
                refresh_url=refresh_url,
                return_url=return_url,
                type="account_onboarding",
            )
            logger.info(accountLink)
            urlToRedirect=accountLink["url"]
            return HttpResponseRedirect(urlToRedirect)
    else:
        form = SignupForm()
        
    return render(request, 'signup.html', {'form': form})


def StripeShifterAccountReturnURLView(request,id):
    if request.method == 'GET':
        merchantAccount = Seller.objects.get(user__id=id)

        acct = stripe.Account.retrieve(merchantAccount.stripe_user_id)

        if acct["details_submitted"] and acct["charges_enabled"]:
            merchantAccount.stripe_charges_enabled=True
            merchantAccount.save()

        return HttpResponseRedirect(reverse('home'))
    
class invoice(View):
    def get(self, request,*args, **kwargs):
        try:
            invoice = Invoice.objects.get(pk=kwargs['uuid'])
            if invoice:
                #check gas fees 
                paymentList = invoice.payments.all()
                firstPayment = paymentList[0]
                if firstPayment.isPackGasFees:
                    template  = loader.get_template('invoice/invoice_gas_fees.html')
                else:
                    template = loader.get_template('invoice/invoice.html')
            else:
                return HttpResponse(status=404)
            #today = datetime.now().date()
            context = {
                'invoice': invoice
            }
            html = HttpResponse(template.render(context, request))
            return html
        except Exception as e:
            logger.info(e)
            from backoffice.helpers import sendEmail
            message="Création de la facture <b>%s</b>   a échoué !"%(invoice.id)
            message+=str(e)
            sendEmail("csurbier@idevotion.fr","[SellTix] Facturation failed",message) 
            return HttpResponse(status=500)