from django.shortcuts import render, redirect
from timedelta import datetime
from asgiref.sync import sync_to_async
from django.contrib import messages
from django.contrib.auth.models import User
import requests
import time
from django.http import JsonResponse
import json
import routeros_api
import sys
import random
import string
from django.http import HttpResponseRedirect
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
import asyncio
import aiohttp
import os
import platform
import urllib.request, json
import datetime
import base64
import threading
from customer.models import Payment
from customer.models import Registration
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
###################################### data json ################################################
status_code= {}
username="hello-hello"
def getthread(request):
    return JsonResponse({'status_code':status_code})

def dologin(request):
    return render(request,"dologin.html",{"username":username})
async def Getdata():
    try:
        data=Payment.objects.all()
        for customer_data in data:
            msisdn=customer_data.notes
            transamount=customer_data.amount
            return msisdn,transamount,data
    except Exception:
        print("something happen")
    except urllib.error.URLError:
        print("urlopen error [Errno 11001] getaddrinfo failed")

async def loop(request):
    try:
        global status_code
        msisdn, transamount,data = await Getdata()
        timeout = 200000  # [seconds]
        timeout_start = time.time()
        number = "254000000000"
        ans = int(phone) + int(number)
        while time.time() < timeout_start + timeout:
            #print("hello",msisdn)
            await asyncio.sleep(0.5)
            if msisdn == 254708562799:
                print("done")
                break
            else:
                data = Payment.objects.all()
                id = Registration.objects.all()
                for customer_data in data:
                    msisdn_db = customer_data.notes
                    transamount = customer_data.amount
                    g=f"{ans}"
                    if ((msisdn_db == g) and (transamount > 0)):
                        timeout = 1  # [seconds]
                        timeout_start = time.time()
                        while time.time() < timeout_start + timeout:
                            await asyncio.sleep(1)
                            if f"{plans}"=="5":
                               balance =int(transamount) - int(plans)
                               if balance < 0:
                                   new_balance=0
                                   Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                               else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))
                                    response = requests.post('https://helios-radius.co.ke/user-create/', json={
                                        "id": '3',
                                        "username": username,
                                        "attribute": "Cleartext-Password",
                                        "op": ":=",
                                        "value": "12345678wp"
                                    })
                                    groups="2hrs"
                                    current_date_and_time = datetime.datetime.now()
                                    hours = 1
                                    hours_added = datetime.timedelta(hours=hours)
                                    future_date_and_time = current_date_and_time + hours_added
                                    Expiration = future_date_and_time.strftime("%d %B %Y %H:%M:%S")
                                    if Expiration:
                                        response = requests.post('https://helios-radius.co.ke/user-create/', json={
                                            "id": '3',
                                            "username": username,
                                            "attribute": "Expiration",
                                            "op": ":=",
                                            "value": Expiration
                                        })
                                    if groups:
                                        response = requests.post('https://helios-radius.co.ke/Radusergroup/', json={
                                            "username": username,
                                            "groupname": groups,
                                            "priority": '1',
                                        })

                                    if response.status_code==200:
                                        status_code=response.status_code
                                        return username,status_code

                            elif f"{plans}"=="10":
                                balance = int(transamount) - int(plans)
                                if balance < 0:
                                    new_balance = 0
                                    Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                                else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))
                                    hotspot.add(server="comcast", name=username, password="1234678wp", profile="DATA",
                                                limit_uptime="00:03:00")
                                    notify = "Dear customer your successfuly purchased 1hr "
                            elif f"{plans}"=="20":
                                balance = int(transamount) - int(plans)
                                if balance < 0:
                                    new_balance = 0
                                    Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                                else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))

                                    notify = "Dear customer your successfuly purchased 1hr "
                            elif f"{plans}"=="30":
                                balance = int(transamount) - int(plans)
                                if balance < 0:
                                    new_balance = 0
                                    Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                                else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))

                                    notify = "Dear customer your successfuly purchased 1hr "
                            elif f"{plans}"=="250":
                                balance = int(transamount) - int(plans)
                                if balance < 0:
                                    new_balance = 0
                                    Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                                else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))

                                    notify = "Dear customer your successfuly purchased 1hr "
                            elif f"{plans}"=="900":
                                balance = int(transamount) - int(plans)
                                if balance < 0:
                                    new_balance = 0
                                    Payment.objects.filter(pk=customer_data.id).update(amount=new_balance)
                                else:
                                    Payment.objects.filter(pk=customer_data.id).update(amount=balance)
                                    letters = string.digits
                                    username = ''.join(random.choice(letters) for i in range(8))

                                    notify = "Dear customer your successfuly purchased 1hr "
                            elif f"{transamount}" < "0":
                                print("no balance")


    except TypeError:
        print("cannot unpack non-iterable NoneType object")
    except ValueError:
        print("NameError: name 'MyModel' is not defined")



ans=''
context={}

async def processing(request):
    global ans
    global context
    try:
        msisdn ,transamount,data=await Getdata()
        number = "254000000000"
        if phone:
            ans = int(phone) + int(number)
        context={
            "transamount":transamount,
            "msisdn":msisdn,
            "phone":ans,
            "plans":plans,
            "status_code":status_code,
        }
    except TypeError:
        print("cannot unpack non-iterable NoneType object")

    return render(request, 'processing.html', context)
phone=""
plans=""

def helios(request):
    global phone
    global plans
    if request.method == 'POST':
        plans = request.POST.get('plans')
        phone = request.POST.get('phone')
        live_url = "https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"
        app_key = "up863hWneHvgTzQHTAKTRUPFmJOmx9GB"
        app_secret = "3HYLLjkSnTRBn2N5"
        ######## get access token ################
        async def main():
            global access_token
            task1 =await asyncio.create_task(get_token())
            task2 =await asyncio.create_task(express())
            task3 =await asyncio.create_task(Getdata())
            t1 = threading.Thread(target=asyncio.run, args=(get_token(),))
            t2 = threading.Thread(target=asyncio.run, args=(express(),))
            t3 = threading.Thread(target=asyncio.run, args=(Getdata(),))
            t5 = threading.Thread(target=asyncio.run, args=(loop(request),))
            t1.start()
            t2.start()
            t3.start()
            t5.start()

            if t5.is_alive():
                t1.join()
                t2.join()
                t3.join()

        async def get_token():
            try:
                global access_token
                async with aiohttp.ClientSession() as sessions:
                    url_response = await sessions.get(live_url.format(), auth=aiohttp.BasicAuth(app_key, app_secret))
                    token = await url_response.json()
                    access_token = token['access_token']
                    #print(access_token)
                    return access_token
            except Exception:
                print("opps! something happen")

        ####################### stk push ######################
        async def express():
            access_token=await get_token()
            #print("this is a token", access_token)
            business_shortcode = "7302281"
            passcode = "5359d4ee9b66f9acb2df4c31370d675de045d53c457f498b87af930df478d98c"
            amount = plans
            live_url = "https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest"
            callback_url = "https://comcast.co.ke/pay/callback_url.php"
            reference_code = "ComcastLtd"
            number = "254000000000"
            ans = int(phone) + int(number)
            phone_number = ans
            description = "Public hotspot service"
            time = str(datetime.datetime.now()).split(".")[0].replace("-", "").replace(" ", "").replace(":", "")
            password = "{0}{1}{2}".format(str(business_shortcode), str(passcode), time)
            encoded = base64.b64encode(bytes(password, encoding='utf8'))
            payload = {
                "BusinessShortCode": business_shortcode,
                "Password": encoded.decode("utf-8"),
                "Timestamp": time,
                "TransactionType": "CustomerBuyGoodsOnline",
                "Amount": amount,
                "PartyA": int(phone_number),
                "PartyB": "5299403",
                "PhoneNumber": int(phone_number),
                "CallBackURL": callback_url,
                "AccountReference": reference_code,
                "TransactionDesc": description
            }

            async with aiohttp.ClientSession() as sessions:
                try:
                    headers = {'Authorization': 'Bearer {0}'.format(access_token), 'Content-Type': "application/json"}
                    url = "{0}{1}".format(live_url, "/mpesa/stkpush/v1/processrequest")
                    response_url = await sessions.post(live_url, headers=headers, json=payload)
                    time = str(datetime.datetime.now()).split(".")[0].replace("-", "").replace(" ", "").replace(":", "")
                    password = "{0}{1}{2}".format(str(business_shortcode), str(passcode), time)
                    encoded = base64.b64encode(bytes(password, encoding='utf8'))
                    payload = {
                        "BusinessShortCode": business_shortcode,
                        "Password": encoded.decode("utf-8"),
                        "Timestamp": time,
                        "CheckoutRequestID": ''
                    }
                    headers = {'Authorization': 'Bearer {0}'.format(access_token), 'Content-Type': "application/json"}

                    saf_url = "{0}{1}".format(live_url, "/mpesa/stkpushquery/v1/query")
                    data_response = await sessions.post(saf_url, headers=headers, json=payload)
                    response = await response_url.json()

                except urllib.error.URLError:
                    print("urlopen error [Errno 11001] getaddrinfo failed")

        if platform.system() == 'Windows':
            asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
        asyncio.new_event_loop().run_until_complete(main())

        return redirect('processing')
    return render(request, 'mpesa.html')
