# from django.shortcuts import render, redirect, get_object_or_404
from inventories .models import Category, Size, Product, Issued_Item
from inventories .forms import JerseyForm, IssueItemForm, ReceiptSearchForm, searchStock
from datetime import datetime, date
import random
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse, HttpResponse
from django.urls import reverse
import urllib.parse
from django.core.paginator import Paginator
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.decorators import login_required



def user_login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get("username")
            password = form.cleaned_data.get("password")
            print(username, password)
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                messages.info(request, f"You are now loged in as {username}")
                return redirect('index')
            else:
                messages.error(request, 'Invalid username or password') 
                return redirect('login')  

        else:
            messages.error(request, 'Invalid username or password') 
            return redirect('login')

    else:
        form = AuthenticationForm()


    context = {
        'form' : form,
    }
    return render(request, 'login.html', context)

def user_logout(request):
    logout(request)
    messages.info(request, "You have successfully logged out.")
    return redirect('login')
  


def get_sizes(request):
    try:
        category_id = request.GET.get('category_id')
        sizes = Size.objects.filter(category_id=category_id).values('id', 'name')
        return JsonResponse(list(sizes), safe=False)
    except:
        messages.info(request, "You have successfully logged out.")


def display_LowStock(remaining_jersey_girls, remaining_jersey_boys, remaining_arm_cuts, remaining_ties, remaining_icecaps, remaining_bags, remianing_eca_kits): 
    low_stock_list = []
    try:
        for qty in remaining_jersey_girls:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            jersey_girls = {
                size : quantity
            }     
            for key, value in jersey_girls.items():
                if value <= 10:
                    size = key,
                    qty = value,
                    girls_jersys_low_stock = f" Girls Jersys - size {key} is low ({value}) in stock "
                    low_stock_list.append(girls_jersys_low_stock)
                
        for qty in remaining_jersey_boys:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            jersey_boys = {
                size : quantity
            }     
            for key, value in jersey_boys.items():
                if value <= 10:
                    size = key,
                    qty = value,               

                    boys_jersys_low_stock = f" Boys Jersys - size {key} is low ({value}) in stock "          
                
                    low_stock_list.append(boys_jersys_low_stock)

        for qty in remaining_arm_cuts:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            armCuts = {
                size : quantity
            }     
            for key, value in armCuts.items():
                if value <= 10:
                    size = key,
                    qty = value, 
                    arm_cuts_low_stock = f" Arm Cuts - size {key} is low ({value}) in stock "
                    low_stock_list.append(arm_cuts_low_stock)


        for qty in remaining_ties:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            ties_lowStock = {
                size : quantity
            }     
            for key, value in ties_lowStock.items():
                if value <= 10:
                    size = key,
                    qty = value, 
                    ties_low_stock = f" Ties - size {key} is low ({value}) in stock "
                    low_stock_list.append(ties_low_stock)


        for qty in remaining_icecaps:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            icecaps_lowStock = {
                size : quantity
            }     
            for key, value in icecaps_lowStock.items():
                if value <= 10:
                    size = key,
                    qty = value, 
                    icecaps_low_stock = f" Ice Caps - size {key} is low ({value}) in stock "
                    low_stock_list.append(icecaps_low_stock)

        for qty in remaining_bags:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            bags_lowStock = {
                size : quantity
            }     
            for key, value in bags_lowStock.items():
                if value <= 10:
                    size = key,
                    qty = value, 
                    bags_low_stock = f" Bags - size {key} is low ({value}) in stock "
                    low_stock_list.append(bags_low_stock)

        for qty in remianing_eca_kits:
            category = qty.category
            size = qty.size
            quantity = qty.quantity        
            ecaKits_lowStock = {
                size : quantity
            }     
            for key, value in  ecaKits_lowStock.items():
                if value <= 10:
                    size = key,
                    qty = value, 
                    ecaKits_low_stock = f" ECA Kits - size {key} is low ({value}) in stock "
                    low_stock_list.append(ecaKits_low_stock)
        return low_stock_list
    except:
        return low_stock_list


       



@login_required
def index(request):
    try:
        jersey_girl = Category.objects.filter(name='JerseyGirls').first()
        jersey_boy = Category.objects.filter(name='JerseyBoys').first()
        arm_cuts = Category.objects.filter(name='ArmCutBoys').first()
        ties = Category.objects.filter(name='Tie').first()
        iceCaps = Category.objects.filter(name='IceCap').first()
        bags = Category.objects.filter(name="Bags").first()
        eca_kits = Category.objects.filter(name='ECAKits').first()

        remaining_jersey_girls = Product.objects.filter(category=jersey_girl)
        remaining_jersey_boys = Product.objects.filter(category=jersey_boy)
        remaining_arm_cuts = Product.objects.filter(category=arm_cuts)
        remaining_ties = Product.objects.filter(category=ties)
        remaining_icecaps = Product.objects.filter(category=iceCaps)
        remaining_bags = Product.objects.filter(category=bags)
        remianing_eca_kits = Product.objects.filter(category=eca_kits)
        
        jersey_girls_remaining_qty_list = []
        jersey_boys_remaining_qty_list = []
        arm_cuts_remaining_qty_list = []
        ties_remaining_qty_list = []
        icecaps_remaining_qty_list = []
        bags_remaining_qty_list = []
        eca_kits_remaining_qty_list = []
        for item in remaining_jersey_girls:
            jersey_girls_remaining_qty_list.append(item.quantity) 
        for item in remaining_jersey_boys:
            jersey_boys_remaining_qty_list.append(item.quantity)
        for item in remaining_arm_cuts:
            arm_cuts_remaining_qty_list.append(item.quantity)
        for item in remaining_ties:
            ties_remaining_qty_list.append(item.quantity)
        for item in remaining_icecaps:
            icecaps_remaining_qty_list.append(item.quantity)
        for item in remaining_bags:
            bags_remaining_qty_list.append(item.quantity)
        for item in remianing_eca_kits:
            eca_kits_remaining_qty_list.append(item.quantity)
        
        rev_jersey_girls_remaining_qty_list = jersey_girls_remaining_qty_list[::-1]
        rev_jersey_boys_remaining_qty_list = jersey_boys_remaining_qty_list[::-1]
        rev_arm_cuts_remaining_qty_list = arm_cuts_remaining_qty_list[::-1]
        rev_ties_remaining_qty_list = ties_remaining_qty_list[::-1]
        rev_icecaps_remaining_qty_list = icecaps_remaining_qty_list[::-1]
        rev_bags_remaining_qty_list = bags_remaining_qty_list[::-1]
        rev_eca_kits_remaining_qty_list = eca_kits_remaining_qty_list[::-1]

        low_stock_alert = display_LowStock(remaining_jersey_girls, remaining_jersey_boys, remaining_arm_cuts, remaining_ties, remaining_icecaps, remaining_bags, remianing_eca_kits )
    except:
        messages.error(request, "Unknown Error. Please contact System Administrator")
    context = {
        'rev_jersey_girls_remaining_qty_list': rev_jersey_girls_remaining_qty_list,
        'rev_jersey_boys_remaining_qty_list' : jersey_boys_remaining_qty_list,
        'rev_arm_cuts_remaining_qty_list': rev_arm_cuts_remaining_qty_list,
        'rev_ties_remaining_qty_list' : rev_ties_remaining_qty_list,
        'rev_icecaps_remaining_qty_list': icecaps_remaining_qty_list,
        'rev_bags_remaining_qty_list' : bags_remaining_qty_list,
        'rev_eca_kits_remaining_qty_list': eca_kits_remaining_qty_list,
        'low_stock_alert' : low_stock_alert,
    }   

  
    return render(request, 'index.html', context)

@login_required
def add_jerseys(request):
    try:
        if request.method == "POST":
            jerseyAddForm = JerseyForm(request.POST)
            if jerseyAddForm.is_valid():
                category = jerseyAddForm.cleaned_data['category']
                size = jerseyAddForm.cleaned_data['size']
                color = jerseyAddForm.cleaned_data['color']
                quantity = jerseyAddForm.cleaned_data['quantity']
                price = jerseyAddForm.cleaned_data['price']

                # Check if the product already exists
                if Product.objects.filter(size=size, color=color).exists():
                    messages.error(request, 'Product Exists.')
                else:
                    # Create a new product
                    Product.objects.create(
                        category=category,
                        size=size,
                        color=color,
                        quantity=quantity,
                        price=price
                    )
                    messages.success(request, 'Product Added Successfully.')
                    return redirect('add_jerseys')
        else:
            jerseyAddForm = JerseyForm()
    except:
        messages.error(request, 'Unknown Add Product Issue.  Please contact System Administrator for support')


    context = {
        'form': jerseyAddForm
    }
    return render(request, 'add_jerseys.html', context)

@login_required
def update_product(request):
    try:
        products = Product.objects.all()
    except:
        messages.error(request, 'No Product found.  Please contact System Adminisrator for support')


    context = {
        'products' : products,
    }
    
    return render(request, 'update_products.html', context)

@login_required
def single_product_update(request, pk):
    product = get_object_or_404(Product, pk=pk)    
    try:
        if request.method=='POST':
            productUpdateForm = JerseyForm(request.POST, instance=product)
            if productUpdateForm.is_valid():
                productUpdateForm.save()
                messages.success(request, 'Producted updated successfully')
                return redirect('update_product')
            else:
                messages.error(request, 'Producted update failed. Please try again.')
        else:
            productUpdateForm = JerseyForm(instance=product)
    except:
        messages.error(request, 'Producted update failed. Please try again.')

    context = {
        'product':product,
        'form' : productUpdateForm,
    }
    return render(request, 'single_product_update.html', context)

@login_required
def restock_products_list(request):
    try:
        products = Product.objects.all()
    except:
        messages.error(request, 'Producted restock failed. Please try again.')

    context = {
        'products' : products,
    }
    return render(request, 'restock_products_list.html', context)

@login_required
def single_product_restock(request, pk):
    product = get_object_or_404(Product, pk=pk)
    if request.method == 'POST':
        productRestockForm=JerseyForm(request.POST, instance=product)
        try:
            category_id = request.POST.get('category')
            size = request.POST.get('size')
            new_qty = request.POST.get('add_new_qty')
            final_qty = request.POST.get('final_qty')
            category_instance = Category.objects.get(id=category_id)
            Product.objects.filter(category=category_instance, size=size).update(quantity=final_qty)
            messages.success(request, f'New Quantity Updated Successfully.  Available {category_instance} quantity is {final_qty}') 
            return redirect('restock_products_list')
        except:
            productRestockForm = JerseyForm(instance=product)
            messages.error(request, f'New Quantity Update Failed.  Please Check Again ')
    else:
        productRestockForm = JerseyForm(instance=product)
        # messages.error(request, f'New Quantity Update Failed.  Please Check Again ')

    context = {
        'product':product,
        'form': productRestockForm,
    }
    return render(request, 'single_product_restock.html', context)




@login_required
def add_ties(request):

    return render(request, 'add_ties.html')



# This is the function to calucluate the stock balance
def calculate_remaining_stock(request, category_name, size_name, quantity):
        # product_category = Category.objects.get(name=type)
        # product_size = Size.objects.get(name=size)
        
        get_issued_product = Product.objects.filter(category=category_name, size=size_name)
        quantity = int(quantity)        

        try:
            for product in get_issued_product:                
                remaining_product_qty = product.quantity             
                if remaining_product_qty >= quantity:
                    remaining_product_quantity = remaining_product_qty - quantity
                    print(remaining_product_quantity)
                    product.quantity = remaining_product_quantity
                    product.save()
                    messages.success(
                        request, f"{quantity} {category_name} from size {size_name} was successfully issued")
                else:
                    messages.error(
                        request, f"Entered issue quantity is larger than the remaining stock quantity.  Please lower the quantity")

        except:
            messages.error(request, f"Something went wrong. Please recheck the issuing quantity you enetered")

        return(remaining_product_quantity)


def generate_bill_number(bill):
    # Generate a random number with five digits
    random_number = random.randint(10000, 99999)
    return int(bill) + int(random_number)  


def printReceipt(request, bill_number):
    bill = Issued_Item.objects.filter(bill_number=bill_number)
    bill_details = []
    for item in bill:
        details = {
        'bill_number' : item.bill_number,
        'category_name' : item.category,
        'size' : item.size,
        'student_name' :item.student_name,
        'student_admission' : item.admission_number,
        'qty' : item.quantity,
        'amount' : item.price,
        'issue_date' : item.date_time
        }
    bill_details.append(details)
    return bill_details


def printb(request):
    remaining_stock = request.GET.get('remaining_stock')
    category_name = request.GET.get('category_name')
    size_name = request.GET.get('size_name')
    bill = request.GET.get('bill')
    receipt_number = request.GET.get('receipt_number')
    category_type  = request.GET.get('category_type')
    product_size = request.GET.get('product_size')
    student_name = request.GET.get('student_name')
    admission_number = request.GET.get('admission_number')
    qty = request.GET.get('qty')
    price = request.GET.get('price')
    date_time = request.GET.get('date_time')

    context = {
        'remaining_stock': remaining_stock,
        'category_name': category_name,
        'size_name': size_name,
        'bill': bill,
        'receipt_number' : receipt_number,
        'category_type' : category_type,
        'product_size' : product_size,
        'student_name' : student_name,
        'admission_number' : admission_number,
        'qty' : qty,
        'price' : price,
        'date_time' : date_time,
    }
    return render(request, 'print_receipt.html', context)

@login_required
def issue_products(request):
    try:
        if request.method == "POST":        
            if 'check_availability' in request.POST:
                productIssueForm =  IssueItemForm(request.POST)           
                category_id = request.POST.get('category')
                size = request.POST.get('size') 
                category_name = Category.objects.get(id=category_id)
                size_name = Size.objects.get(id=size)         
                try:
                    check_product_exists = Product.objects.get(category=category_name, size=size_name)
                    if check_product_exists:
                        quantity = check_product_exists.quantity
                        price = check_product_exists.price
                    context = {
                            'quantity': quantity,
                            'price' : price,
                            'form': productIssueForm,
                        }

                    return render(request, 'issue_products.html', context)
                
                except Product.DoesNotExist:
                    productIssueForm = IssueItemForm()
                    messages.error( request, "Requested Product Not Found.  Please Check Again")

            elif 'issue_items' in request.POST:
                try:
                    productIssueForm =  IssueItemForm(request.POST)           
                    category_id = request.POST.get('category')
                    size = request.POST.get('size') 
                    category_name = Category.objects.get(id=category_id)
                    size_name = Size.objects.get(id=size)
                    student_name = request.POST.get('studentName')
                    admission_number = request.POST.get('admissionNumber')
                    quantity = request.POST.get('quantity')
                    price = request.POST.get('amount')
                    Issued_date = datetime.now()
                    Issued_date = Issued_date.date()  
                    bill = 0          
                    bill_number = generate_bill_number(bill)

                    products = Product.objects.filter(category=category_name, size=size_name)

                    Issued_Item.objects.create(category=category_name, size=size_name, student_name=student_name, admission_number=admission_number,
                                            quantity=quantity, price=price, date_time=Issued_date, bill_number=bill_number  )          
                    
                    # bill = Issued_Item.objects.filter(bill_number=bill_number)  

                    remaining_stock = calculate_remaining_stock(request, category_name, size_name, quantity)
                    remaining_stock = remaining_stock   

                    bill = printReceipt(request, bill_number) 
                    for item in bill:
                        receipt_number = item['bill_number']
                        category_type  = item['category_name']
                        product_size = item['size']
                        student_name = item['student_name']
                        admission_number = item['student_admission']
                        qty = item['qty']
                        price = item['amount']
                        date_time = item['issue_date']

                    query_params = {
                        'remaining_stock': remaining_stock,
                        'category_name': category_name.name,
                        'size_name': size_name.name,
                        'bill' : bill,
                        'receipt_number': receipt_number,
                        'category_type' : category_type,
                        'product_size' : product_size,
                        'student_name' : student_name,
                        'admission_number':admission_number,
                        'qty':qty,
                        'price' : price,
                        'date_time' : date_time,
                    }

                    url = reverse('printb') + '?' + urllib.parse.urlencode(query_params)

                    return redirect(url) 
                except:     
                    messages.error( request, "Unknown Erro Occured in Issue Items. Please contact system Admin for support")      

            else:  
                productIssueForm = IssueItemForm()
                messages.error( request, "Requested Product Not Found.  Please Check Again")
            
            return redirect('print_receipt')  # Redirect to some page after successful submission 
        else:
            productIssueForm = IssueItemForm()
    except:
        messages.error( request, "Unknown Error.  Please Contact System Admin for support")


    context = {
        'form': productIssueForm,
    }
    return render(request, 'issue_products.html', context)






@login_required
def submit_category_and_size(request):
    try:
        if request.method == 'POST':
            category = request.POST.get('category')
            size = request.POST.get('size')
            cate = Category.objects.get(id=category)
            size = Size.objects.get(id=size)
            print(cate, size)
            # Handle the category and size values as needed
            print(f"Category: {category}, Size: {size}")  # For example, print the values
            # return HttpResponse('Category and size submitted successfully')
        # return HttpResponse('Invalid request', status=400)
    except:
        pass
    context = {
        'category': category,
        'size' : size,
    }
    return render(request, 'issue_products.html', context)

@login_required
def print_receipt(request):
    context = {}
    return render(request, 'print_receipt.html', context)


@login_required
def search_reciept(request):
    form = ReceiptSearchForm(request.GET or None)
    
    all_receipts = Issued_Item.objects.all()
    try:
        if form.is_valid():
            student_name = form.cleaned_data.get('student_name')
            admission_number = form.cleaned_data.get('admission_number')
            bill_number = form.cleaned_data.get('bill_number')
            date_from = form.cleaned_data.get('date_from')
            date_to = form.cleaned_data.get('date_to')
            category = form.cleaned_data.get('category')
            size = form.cleaned_data.get('size')

            if student_name:
                all_receipts = all_receipts.filter(student_name__icontains=student_name)
            if admission_number:
                all_receipts = all_receipts.filter(admission_number=admission_number)
            if bill_number:
                all_receipts = all_receipts.filter(bill_number=bill_number)
            if date_from:
                all_receipts = all_receipts.filter(date_time__gte=date_from)
            if date_to:
                all_receipts = all_receipts.filter(date_time__lte=date_to)
            if category:
                all_receipts = all_receipts.filter(category=category)
            if size:
                all_receipts = all_receipts.filter(size=size)

        paginator = Paginator(all_receipts, 10)  # Show 10 receipts per page
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
    except:
        messages.error(request, 'Receipt not found. Please try again.')

    context = {
        'form': form, 
        'all_receipts': all_receipts,
        'page_obj': page_obj}
    return render (request, 'search_reciept.html', context)


@login_required
def search_stocks(request):
    form = searchStock(request.GET or None)
    stocks = Product.objects.all()   
    try:
        if form.is_valid():
            category = form.cleaned_data.get('category')
            size = form.cleaned_data.get('size') 
            if category and size:
                stocks = stocks.filter(category=category, size=size)
        paginator = Paginator(stocks, 20)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
    except:
        messages.error(request, 'Stock not found. Please try again.')

    context ={
        'form': form,
        'stocks': stocks,
        'page_obj' : page_obj,
    }

    return render (request, 'search_stocks.html', context)

