from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Products, Order, Ordered_Product, Order_Status
from django.contrib.auth.models import User, auth
import math
import ast, json
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from django.conf import settings
import emoji
from geekysid import cvEmailer

def my_view(request):
    
    # Let's assume that the visitor uses an iPhone...
    print(request.user_agent.is_mobile) # returns True
    print(request.user_agent.is_tablet) # returns False
    print(request.user_agent.is_touch_capable) # returns True
    print(request.user_agent.is_pc) # returns False
    print(request.user_agent.is_bot) # returns False

    # Accessing user agent's browser attributes
    print(request.user_agent.browser)  # returns Browser(family=u'Mobile Safari', version=(5, 1), version_string='5.1')
    print(request.user_agent.browser.family)  # returns 'Mobile Safari'
    print(request.user_agent.browser.version)  # returns (5, 1)
    print(request.user_agent.browser.version_string)   # returns '5.1'

    # Operating System properties
    print(request.user_agent.os)  # returns OperatingSystem(family=u'iOS', version=(5, 1), version_string='5.1')
    print(request.user_agent.os.family)  # returns 'iOS'
    print(request.user_agent.os.version)  # returns (5, 1)
    print(request.user_agent.os.version_string)  # returns '5.1'

    # Device properties
    print(request.user_agent.device)  # returns Device(family='iPhone')
    print(request.user_agent.device.family)  # returns 'iPhone'


def device_check(request):
    if (request.user_agent.is_mobile == True) or (request.user_agent.is_tablet == True):
        return 'true'
    else:
        return 'false'


def index(request):
    
    MOBILE_TABLET_FLAG = device_check(request)

    # fetching discounted item
    disc_product_list = Products.objects.filter(discount__gt=0.0).order_by("-discount")  # returns list of products that has dicount attribute > 0.0 and the the list is ordered DESC by by column discount
    
    for prod in disc_product_list:
        prod.discounted_price = (prod.price - (prod.discount * prod.price) / 100)  # setting a new attribute of the product that holds the discounted price
    
    slides_discountItems = math.ceil(len(disc_product_list) / 4)  # calculatimng total number of slides reqruired. here 4 is the number of product per side.
    range_slides_discountItems = range(slides_discountItems)  # creating a generator and storing in a variable.
    discounted_product = [disc_product_list, range_slides_discountItems]

    # CATEGORY WISE PRODUCTS
    categories = Products.objects.values("category")  # returns list of dictionary as[{'category': 'Programming'}, {'category': 'MBA'}, {'category': 'MBA'}, ...]
    category = {cat_dict["category"] for cat_dict in categories}  # returns set of category as[Programming', 'MBA', ...]
    all_products = []
    
    for cat in category:
        product_cat_list = Products.objects.filter(category=cat)  # returns list of all products with matching category.
        number_slide = len(product_cat_list) // 4 + math.ceil((len(product_cat_list) / 4) - (len(product_cat_list) // 4))  # calculating number of slices required for each category
        all_products.append([product_cat_list, range(number_slide)])  # appending list of list of categorised products along with generator

    # creating a dictioary to pass to the page when it is called.
    product_params = {
        'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG,
        "all_products": all_products,
        "disc_product_list": disc_product_list,
        "range_slides_discountItems": range_slides_discountItems,
    }
    return render(request, "bookstore/index.html", product_params)


def checkout(request):

    MOBILE_TABLET_FLAG = device_check(request)

    if request.method == 'POST':
        name = request.POST.get('inputName', '')
        email = request.POST.get('inputEmail', '')
        phone = request.POST.get('inputPhone', '')
        address = request.POST.get('inputAddress', '')
        landmark = request.POST.get('inputLandmark', '')
        city = request.POST.get('inputCity', '')
        state = request.POST.get('inputState', '')
        zipcode = request.POST.get('inputPinCode', '')
        message = request.POST.get('inputMessage', '')
        paymode = request.POST.get('paymentradio', '')
        cart = request.POST.get('cartitemhidden', '')
        
        # Creating an order in the Order Object
        try:
            order = Order(name=name, email=email, phone=phone, address=address, landmark=landmark, city=city, state=state, zipcode=zipcode, message=message, paymode=paymode)
            order.save()

            if order:
                try:
                    cart_dict = json.loads(cart)
                    # cart_dict = ast.literal_eval(cart)  # used this function to convert string to dictionary as json.loads() was not working for some reason

                    product_deatils = {}

                    # Adding all the proucts in a order to the Ordered_Product object
                    for item in cart_dict:
                        product = Products.objects.get(id=int(item[2:]))    # fetching product object for each item customer wants to save it in order_product table
                        order_product = Ordered_Product(order=order, product=product, quantity=cart_dict[item][1], discount=cart_dict[item][3], price=float(cart_dict[item][2]), image=cart_dict[item][4])
                        order_product.save()

                        # product_deatils[str(product)] =  [qnty, discount, price, img]
                        product_deatils[str(product)] =  [cart_dict[item][1], cart_dict[item][3], float(cart_dict[item][2]), cart_dict[item][4]]

                    # Setting status of the order as 'Order Placed' in Order_Status Table
                    order_status = Order_Status(order= order, status_desc = "Order successfully placed", remark="We will get back to your via mail about approximate date of delivery. Genarally Arrival time is between 5-8 workind days depending on the location.")
                    order_status.save()

                    # SENDING EMAIL CONFIRMATION TO THE CLIENT ABOUT ORDER PLACED
                    
                    prod_list = ""
                    for prod in product_deatils:
                        prod_list = prod_list + '<div><img src="' + product_deatils[prod][3] + '" width="70px" height="100px" /> <b>'+ prod +'</b>, Qnty: ' + str(product_deatils[prod][0]) + ' @ $' + str(product_deatils[prod][2]) + ' with ' + str(product_deatils[prod][1]) + '% discount.</div><br />'

                    body = '<strong>Your order has been placed successfully and should reach your doorstep in next 5-6 working days.</strong>' \
                            '<p>Below is the details of your order.<p>' + prod_list + ''

                    cvEmailer.bookStore_checkout_mail(email, body)

                    return redirect("orders?orderid="+str(order)+"&emailadd="+email+"&checkoutStatus=success")

                except Exception as e:
                    return render(request, "bookstore/checkout.html", {'errorMessage': "Exception occured: "+ str(e)})
                
            else:
                return render(request, "bookstore/checkout.html", {'errorMessage': "There was an error while placing your order. Please try again or contact admin."})

        except Exception as e:
            return render(request, "bookstore/checkout.html", {'errorMessage': "Exception occured: "+ str(e) +". There was an while placing your order. Please try again or contact admin."})
    else:
        return render(request, "bookstore/checkout.html", {'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})


def product(request):

    MOBILE_TABLET_FLAG = device_check(request)

    if request.method == "GET" and 'id' in request.GET:
        id = request.GET.get("id", '')
        
        if id.strip().isnumeric():
            try:
                product = Products.objects.get(id=id)
                if product != None:
                    return render(request, 'bookstore/product.html', {"product": product, "validity": "true", 'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})
                else:
                    return render(request, 'bookstore/product.html', {"error": "Invaild Product", "validity": "false", 'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})
            except Products.DoesNotExist:
                return render(request, 'bookstore/product.html', {"error": "Invaild Product", "validity": "false", 'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})

        else:
            return render(request, 'bookstore/product.html', {"error": "Invaild Product", "validity": "false", 'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})
    else:
        return render(request, 'bookstore/product.html', {"error": "Invaild Params", "validity": "false", 'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})


def orders(request):

    MOBILE_TABLET_FLAG = device_check(request)

    if request.method == "GET" and 'orderid' in request.GET and 'emailadd' in request.GET:
        print("="*50)
        email = request.GET.get("emailadd", "").strip()
        order_id = request.GET.get("orderid", "").strip()

        if email and order_id:
            params = orders_fetchData(order_id, email)

            if 'checkoutStatus' in request.GET:
                params['MOBILE_TABLET_FLAG']: MOBILE_TABLET_FLAG
                params['checkoutStatus'] = 'success'
                params['orderid'] = order_id
                params['emailadd'] = email

            return render(request, "bookstore/orders.html", params)
        else:
            return render(request, "bookstore/orders.html", {'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})

    elif request.method == "POST":
        email = request.POST.get("emailadd", "").strip()
        order_id = request.POST.get("orderid", "").strip()

        params = orders_fetchData(order_id, email)
        return render(request, "bookstore/orders.html", params)
    
    else:
        return render(request, "bookstore/orders.html", {'MOBILE_TABLET_FLAG': MOBILE_TABLET_FLAG})
        
        
def orders_fetchData(order_id, email):
    try:
        order_obj = Order.objects.get(email=email, order_id=int(order_id))
    except Order.DoesNotExist:
        order_obj = None

    if order_obj:
        try:
            ord_prod_obj = Ordered_Product.objects.filter(order=order_obj)
        except Ordered_Product.DoesNotExist:
            ord_prod_obj= None
        
        if ord_prod_obj:
            for prod_obj in ord_prod_obj:
                prod_obj.total = (prod_obj.price * prod_obj.quantity) - (prod_obj.price * prod_obj.quantity * prod_obj.discount) / 100
        else:
            prod_details_error = f"Unable to fetch order details. Please contact customer care. Order Number {order_obj.order_id}"
        
        try:    
            ord_stat_obj = Order_Status.objects.filter(order=order_obj)
        except Order_Status.DoesNotExist:
            ord_stat_obj= None

        if not ord_stat_obj:
            ord_status_error = f"Unable to fetch order status. Please contact customer care.  Order Number {order_obj.order_id}"
        
        if ord_stat_obj and ord_prod_obj:
            return {'order_obj': order_obj, 'ord_prod_obj': ord_prod_obj, 'ord_stat_obj': list(ord_stat_obj)}
        
        elif (not ord_stat_obj) and ord_prod_obj:
            return {'order_obj': order_obj, 'ord_status_error': ord_status_error, 'ord_stat_obj': list(ord_stat_obj), 'ord_prod_obj': ord_prod_obj}
        
        elif ord_stat_obj and not ord_prod_obj:
            return {'order_obj': order_obj, 'ord_prod_obj': ord_prod_obj, 'prod_details_error': prod_details_error, 'ord_stat_obj': list(ord_stat_obj)}

        else:
            return {'order_obj': order_obj, 'ord_status_error': ord_status_error, 'prod_details_error': prod_details_error}

    else:
        return {"order_error": "No order with the entered email and order id found. Please check again."}
