from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.http import HttpResponse, JsonResponse
from django.forms import modelformset_factory, inlineformset_factory
from django.db import transaction
from django.core import serializers
from .models import SalesOrder, SalesOrderItemLine
from Item.models import Item, PriceLevel, PriceLevelItem
from Customer.models import Customer
from .forms import SalesOrderForm, SalesOrderItemLineForm
import json
from django.core.serializers.json import DjangoJSONEncoder
from django.contrib import messages

def index(request):
    print("index SO")
    context = {}
    context['objects'] = SalesOrder.objects.order_by('-TimeCreated')
    context['addurl'] = reverse('SalesOrder:add_so')
    return render(request, "SalesOrder/index_salesorder.html", context=context)

def add_so(request, pk=None):
    print("create SO")
    context = {}
    obj=None
    plname = None
    if pk:
        obj = get_object_or_404(SalesOrder.objects.select_related(), pk=pk)
        # obj = get_object_or_404(SalesOrder, pk=pk)
        plname = obj.CustomerRefFullName.PriceLevelRefFullName.Name
        # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}")
    form = SalesOrderForm(request.POST or None, instance=obj)
    # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below
    SalesOrderItemLineFormset = inlineformset_factory(SalesOrder, SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below
    # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1)
    # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1)
    qs=None
    formset = SalesOrderItemLineFormset(request.POST or None)
    if pk:
        print("got ID")
        qs = obj.salesorderitemline_set.all().order_by('id').select_related('ItemRefFullName')
        # formset = SalesOrderItemLineFormset(request.POST or None, queryset=qs)
        formset = SalesOrderItemLineFormset(request.POST or None, instance=obj)
    print(request.POST)
    # print(formset)
    # print(len(formset))
    # print(f"queryset={qs}")
    # print(f"queryset={qs[0].ItemRefFullName}")
    # qsItemList = list(x.ItemRefFullName for x in qs)
    # print(qsItemList)
    print(f'plname:{plname}')
    qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price')
    qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull")
    # print(qsIn)
    # print("qsEx")
    # print(qsEx)
    context['itemdatalist'] = qsIn.union(qsEx)

    context['object'] = obj
    context['qsformset'] = None
    if pk:
        context['qsformset'] = list(zip(qs, formset))
    if request.method == "POST":
        with transaction.atomic():
            if form.is_valid():
                # print(form.cleaned_data)
                # with transaction.atomic():
                # print(formset)
                if formset.is_valid():
                    for delform in formset.deleted_forms:
                        pass
                    totalamount=form.cleaned_data['TotalAmount']
                    print(totalamount, type(totalamount))
                    totalamountChildren=0
                    for fm in formset:
                        # print(fm)
                        print(fm['DELETE'].value())
                        if not fm['DELETE'].value() and 'Amount' in fm.cleaned_data:
                            print(f"fm.cleaced_data: {fm.cleaned_data['Amount']}")
                            amount=fm.cleaned_data['Amount']
                            # print(amount)
                            print(fm['DELETE'].value())
                            totalamountChildren+=amount
                    print(totalamountChildren)
                    if totalamount==totalamountChildren:
                        print("correct total amount")
                    else:
                        print(f"not correct total amount:{totalamount} supposed={totalamountChildren}")
                    # form.cleaned_data['TotalAmount'] = totalamountChildren
                    parentobj = form.save(commit=False)
                    parentobj.TotalAmount = totalamountChildren
                    parentobj.save()
                    # print(parentobj)
                    print("formset valid")
                    instances = formset.save(commit=False)
                    for obj in formset.deleted_objects:
                        print("deelted object")
                        print(obj)
                        obj.delete()
                    for instance in instances:
                        # print(instance.ItemRefFullName)
                        # print(instance.pk)
                        # print(parentobj.id)
                        instance.SalesOrder = parentobj
                        instance.save()
                    context['message'] = "All Data Saved"
                    print("all formset saved")
                    print(parentobj.pk, type(parentobj.pk))
                    print(reverse('SalesOrder:edit_so', args=[parentobj.pk]))
                    messages.success(request, "All Data is Saved")
                    return redirect(reverse('SalesOrder:edit_so', args=[parentobj.pk]))
                else:
                    print("formset error")
                    print(formset.errors)
            else:
                print("form error")
                print(form.errors)
    context['form'] = form
    context['formset'] = formset
    return render(request, "SalesOrder/create-update.html", context=context)

# def add_so(request):
#     print("create SO")
#     context = {}
#     # obj = get_object_or_404(SalesOrder, pk=id)
#     obj=None
#     form = SalesOrderForm(request.POST or None, )
#     SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=1)
#     # qs = obj.salesorderitemline_set.all()
#     qs=None
#     formset = SalesOrderItemLineFormset(request.POST or None, )
#     context['form'] = form
#     context['formset'] = formset
#     context['object'] = obj

#     if all([form.is_valid(),   formset.is_valid()]):
#         print(form.cleaned_data)
#         for form in formset:
#             print(form.clean_data)
#         context['message'] = "All Data saved"
#     return render(request, "SalesOrder/create-update.html", context=context)


def getpricelist_so(request, pk=None):
    print(f"getpricelist SO; pk={pk}")
    context = {}
    obj=None
    plname = None
    if pk:
        # obj = get_object_or_404(SalesOrder.objects.select_related(), pk=pk)
        obj = get_object_or_404(Customer.objects.select_related(), pk=pk)
        plname = obj.PriceLevelRefFullName.Name
        # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}")
    # form = SalesOrderForm(request.POST or None, instance=obj)
    # SalesOrderItemLineFormset = inlineformset_factory(SalesOrder, SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below
    print(obj)
    qs=None
    # formset = SalesOrderItemLineFormset(request.POST or None)
    # if pk:
    #     print("got ID")
    #     qs = obj.salesorderitemline_set.all().order_by('id').select_related('ItemRefFullName')
    #     # formset = SalesOrderItemLineFormset(request.POST or None, queryset=qs)
    #     formset = SalesOrderItemLineFormset(request.POST or None, instance=obj)
    print(request.GET)
    # print(len(formset))
    # print(f"queryset={qs}")
    # print(f"queryset={qs[0].ItemRefFullName}")
    # qsItemList = list(x.ItemRefFullName for x in qs)
    # print(qsItemList)
    print(f'plname:{plname}')
    qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price')
    qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull")
    context['itemdatalist'] = qsIn.union(qsEx)
    serialized_q = json.dumps(list( context['itemdatalist']), cls=DjangoJSONEncoder)
    # p=json.loads(serialized_q)
    # print(serialized_q)    
    serialized_obj = serializers.serialize('json', [ obj, ])
    context['obj'] = serialized_obj
    context['itemdatalist'] = serialized_q
    # serialized_q = serialized_q + serialized_obj
    # print(serialized_obj)
    data = json.dumps(context, indent=4, sort_keys=True, default=str)
    # print(data)
    # print(serialized_q)
    return JsonResponse(data, safe=False)

def edit_so(request):
    print("Edit SO")
    context = {}
    obj = get_object_or_404(SalesOrder, pk=id)
    form = SalesOrderForm(request.POST or None, instance=obj)
    SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=1)
    qs = obj.salesorderitemline_set.all()
    formset = SalesOrderItemLineFormset(request.POST or None, isinstance=qs)
    context['form'] = form
    context['formset'] = formset
    context['object'] = obj

    if all([form.is_valid(),   formset.is_valid()]):
        print(form.cleaned_data)
        for form in formset:
            print(form.clean_data)
        context['message'] = "All Data saved"
    return render(request, "SalesOrder/create-update.html", context=context)

def delete_so(request):
    pass


