from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import *
from management.models import Term
from .filters import *
from django.core.paginator import Paginator
from .forms import *
from django.contrib import messages
from decimal import Decimal
from datetime import datetime
from django.http import JsonResponse
# from django.http import HttpResponseRedirect, HttpResponse
# import csv
from django.db.models import Sum

@login_required
def showFinances(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = NotificationFilter3(
            request.GET,
            queryset = Notification.objects.filter(review="Approved")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        total_invoices = filtered_notifications.qs.aggregate(Sum('category__amount'))['category__amount__sum']
        if total_invoices == None:
            context['total_invoices'] = 0
        else:
            context['total_invoices'] = total_invoices
        total_received = filtered_notifications.qs.aggregate(Sum('amount_paid'))['amount_paid__sum']
        if total_received == None:
            context['total_received'] = 0
        else:
            context['total_received'] = total_received
        if total_invoices == None or total_received == None:
            context['total_balance'] = 0
        else:
            context['total_balance'] = total_invoices - total_received

        filtered_notifications2 = NotificationFilter3(
            request.GET,
            queryset = Notification.objects.filter(review="Pending")
        )
        pending_notifications = filtered_notifications2.qs.count()
        context['pending_notifications'] = pending_notifications

        created_list = [""]
        sales = Notification.objects.filter(review="Approved").order_by('created')
        amount_paid_list = [0]
        # total = 0.00
        for each in sales:
            if each.created.strftime('%d, %b %Y') in created_list:
                total = amount_paid_list[-1]
                try:
                    total = Decimal(total) + Decimal(each.amount_paid)
                    amount_paid_list.pop()
                    amount_paid_list.append(int(total))
                except:
                    each.amount_paid = 0
                    total = Decimal(total) + Decimal(each.amount_paid)
                    amount_paid_list.pop()
                    amount_paid_list.append(int(total))
            else:
                created_list.append(each.created.strftime('%d, %b %Y'))
                try:
                    amount_paid_list.append(int(each.amount_paid))
                except:
                    each.amount_paid = 0
                    amount_paid_list.append(int(each.amount_paid))

        context['created_list'] = created_list
        context['amount_paid_list'] = amount_paid_list

        regis = dict()
        for i in Notification.objects.filter(review="Approved"):
            if i.category.category in regis:
                regis[i.category.category] += 1
            else:
                regis[i.category.category] = 1
        context['regis'] = regis
        return render(request, 'payment/finances.html', context=context)
    else:
        return redirect('index')



@login_required
def showNotifications(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = NotificationFilter(
            request.GET,
            queryset = Notification.objects.filter(review="Pending")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/notifications.html', context=context)
    else:
        return redirect('index')

@login_required
def showNotificationsBursar(request):
    if request.user.role == "Bursar":
        context = {}
        filtered_notifications = NotificationFilter(
            request.GET,
            queryset = Notification.objects.filter(recorder=request.user, review="Pending")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/notifications_bursar.html', context=context)
    else:
        return redirect('index')

@login_required
def showApproveds(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = NotificationFilter2(
            request.GET,
            queryset = Notification.objects.filter(review="Approved")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/approveds.html', context=context)
    else:
        return redirect('index')

@login_required
def showReports(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = NotificationFilter3(
            request.GET,
            queryset = Notification.objects.filter(review="Approved")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        total_invoices = filtered_notifications.qs.aggregate(Sum('category__amount'))['category__amount__sum']
        context['total_invoices'] = total_invoices
        total_received = filtered_notifications.qs.aggregate(Sum('amount_paid'))['amount_paid__sum']
        context['total_received'] = total_received
        context['total_balance'] = total_invoices - total_received
        return render(request, 'payment/reports.html', context=context)
    else:
        return redirect('index')

@login_required
def showDebtors(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = NotificationFilter4(
            request.GET,
            queryset = Notification.objects.filter(review="Approved", completed=False)
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/debtors.html', context=context)
    else:
        return redirect('index')

@login_required
def showApprovedsBursar(request):
    if request.user.role == "Bursar":
        context = {}
        filtered_notifications = NotificationFilter2(
            request.GET,
            queryset = Notification.objects.filter(recorder=request.user, review="Approved")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/approveds_bursar.html', context=context)
    else:
        return redirect('index')

@login_required
def showApprovedsStudent(request):
    if request.user.role == "Student":
        context = {}
        filtered_notifications = NotificationFilter3(
            request.GET,
            queryset = Notification.objects.filter(student=request.user, review="Approved")
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications
        return render(request, 'payment/approveds_student.html', context=context)
    else:
        return redirect('index')

@login_required
def showCategorys(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = CategoryFilter(
            request.GET,
            queryset = Category.objects.all()
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications

        form = CategoryForm()
        if request.method == 'POST':
            form = CategoryForm(request.POST, request.FILES, None)
            if form.is_valid():
                form.save()

                messages.success(request, "The category has been added successfully")
                return redirect('categorys')
            else:
                messages.error(request, "Please review form input fields below")
        context['form'] = form

        return render(request, 'payment/categorys.html', context=context)
    else:
        return redirect('index')

@login_required
def showAccounts(request):
    if request.user.role == "Admin":
        context = {}
        filtered_notifications = AccountFilter(
            request.GET,
            queryset = Account.objects.all()
        )
        context['filtered_notifications'] = filtered_notifications
        paginated_filtered_notifications = Paginator(filtered_notifications.qs, 20)
        page_number = request.GET.get('page')
        notifications_page_obj = paginated_filtered_notifications.get_page(page_number)
        context['notifications_page_obj'] = notifications_page_obj
        total_notifications = filtered_notifications.qs.count()
        context['total_notifications'] = total_notifications

        form = AccountForm()
        if request.method == 'POST':
            form = AccountForm(request.POST, request.FILES, None)
            if form.is_valid():
                form.save()

                messages.success(request, "The account has been added successfully")
                return redirect('accounts')
            else:
                messages.error(request, "Please review form input fields below")
        context['form'] = form

        return render(request, 'payment/accounts.html', context=context)
    else:
        return redirect('index')

@login_required
def updateCategorys(request, id):
    if request.user.role == "Admin":
        category = Category.objects.get(id=id)
        form = CategoryForm(instance=category)
        if request.method=='POST':
            form = CategoryForm(request.POST, request.FILES, instance=category)
            if form.is_valid():
                form.save()
                messages.success(request, "The category has been modified successfully")
                return redirect('categorys')
        return render(request, 'payment/categorys_update.html', {'form': form, 'category': category})
    else:
        return redirect('index')

@login_required
def updateAccounts(request, id):
    if request.user.role == "Admin":
        account = Account.objects.get(id=id)
        form = AccountForm(instance=account)
        if request.method=='POST':
            form = AccountForm(request.POST, request.FILES, instance=account)
            if form.is_valid():
                form.save()
                messages.success(request, "The account has been modified successfully")
                return redirect('accounts')
        return render(request, 'payment/accounts_update.html', {'form': form, 'account': account})
    else:
        return redirect('index')

@login_required
def approve(request, id):
    if request.user.role == "Admin":
        noti = Notification.objects.get(id=id)

        noti.review = "Approved"
        x = datetime.now().year + datetime.now().month + datetime.now().day + datetime.now().hour + datetime.now().minute + datetime.now().second + 99999*datetime.now().microsecond
        y = "SPS" + str(x)
        noti.receipt_id = y
        noti.save()

        # reg = Notification.objects.get(recorder=request.user)[0]
        all_paid = Notification.objects.filter(review="Approved", term=noti.term, category=noti.category, student=noti.student).aggregate(Sum('amount_paid'))['amount_paid__sum']
        noti.balance = noti.category.amount - all_paid
        if noti.balance <= 0:
            noti.completed = True
        noti.save()

        messages.success(request, "Approved successfully")
        return redirect('notifications')
    else:
        return redirect('index')

@login_required
def addNotification(request):
    if request.user.role == "Bursar":
        if request.method == "POST":
            form = NotificationForm(request.POST, request=request)
            if form.is_valid():
                form.save(commit=False).recorder = request.user
                form.save()
                messages.success(request, "The notification has been added successfully")
                return redirect('notification')
            else:
                messages.error(request, "Please review and correct form input fields")
        else:
            form = NotificationForm(request=request)
        return render(request, 'payment/notification.html', {'form': form})
    else:
        return redirect('index')

@login_required
def showReceipt(request, id):
    if request.user.role=="Admin":
        noti = Notification.objects.get(id=id)
        term = noti.term
        student = noti.student
        categorys = Category.objects.filter(classe=student.classe)
        notifications = Notification.objects.filter(term=term, student=student)
        total_invoice = Decimal(0)
        for each in categorys:
            total_invoice += each.amount
        total_paid = Decimal(0)
        for each in notifications:
            total_paid += each.amount_paid
        balance = total_invoice - total_paid

        return render(request, 'payment/receipt.html', {'noti':noti, 'notifications':notifications, 'categorys':categorys, 'total_invoice':total_invoice,
        'total_paid':total_paid, 'balance':balance})
    elif request.user.role == "Bursar":
        noti = Notification.objects.get(id=id)
        term = noti.term
        student = noti.student
        categorys = Category.objects.filter(classe=student.classe)
        notifications = Notification.objects.filter(term=term, student=student)
        total_invoice = Decimal(0)
        for each in categorys:
            total_invoice += each.amount
        total_paid = Decimal(0)
        for each in notifications:
            total_paid += each.amount_paid
        balance = total_invoice - total_paid

        return render(request, 'payment/receipt_bursar.html', {'noti':noti, 'notifications':notifications, 'categorys':categorys, 'total_invoice':total_invoice,
        'total_paid':total_paid, 'balance':balance})
    elif request.user.role == "Student":
        noti = Notification.objects.get(id=id)
        term = noti.term
        student = noti.student
        categorys = Category.objects.filter(classe=student.classe)
        notifications = Notification.objects.filter(term=term, student=student)
        total_invoice = Decimal(0)
        for each in categorys:
            total_invoice += each.amount
        total_paid = Decimal(0)
        for each in notifications:
            total_paid += each.amount_paid
        balance = total_invoice - total_paid

        return render(request, 'payment/receipt_student.html', {'noti':noti, 'notifications':notifications, 'categorys':categorys, 'total_invoice':total_invoice,
        'total_paid':total_paid, 'balance':balance})
    else:
        return redirect('index')

@login_required
def load_categories(request):
    student_id = request.GET.get('student_id')
    categories = []

    if student_id:
        student = Person.objects.get(id=student_id)
        categories = Category.objects.filter(classe=student.classe)

    return JsonResponse(list(categories.values('id', 'category', 'classe__classe')), safe=False)

@login_required
def showInvoice(request, id):
    if request.user.role=="Student":
        term = Term.objects.get(id=id)
        student = request.user
        notifications = Notification.objects.filter(term=term, student=student)
        try:
            noti = notifications[0]
        except:
            noti = request.user

        categorys = Category.objects.filter(classe=student.classe)
        total_invoice = Decimal(0)
        for each in categorys:
            total_invoice += each.amount
        total_paid = Decimal(0)
        for each in notifications:
            total_paid += each.amount_paid
        balance = total_invoice - total_paid

        return render(request, 'payment/invoice_student.html', {'term':term, 'notifications':notifications, 'noti':noti, 'categorys':categorys, 'total_invoice':total_invoice,
        'total_paid':total_paid, 'balance':balance})
    else:
        return redirect('index')


@login_required
def showInvoiceAdmin(request, id, id2):
    if request.user.role == "Admin":
        term = Term.objects.get(id=id)
        student = Person.objects.get(id=id2)

        notifications = Notification.objects.filter(term=term, student=student)
        try:
            noti = notifications[0]
        except:
            noti = student

        categorys = Category.objects.filter(classe=student.classe)
        total_invoice = Decimal(0)
        for each in categorys:
            total_invoice += each.amount
        total_paid = Decimal(0)
        for each in notifications:
            total_paid += each.amount_paid
        balance = total_invoice - total_paid

        return render(request, 'payment/invoice_admin.html', {'term':term, 'student':student, 'notifications':notifications, 'noti':noti, 'categorys':categorys, 'total_invoice':total_invoice,
        'total_paid':total_paid, 'balance':balance})
    else:
        return redirect('index')
