from django.shortcuts import render, redirect, get_object_or_404
from django.core.paginator import Paginator
from django.db.models import Sum, Q
from datetime import datetime

from products.models import StockMovement
from .models import Supplier, Customer, Transporter, Company
from .forms import SupplierForm, CustomerForm, TransporterForm, CompanyForm
from accounting.models import PurchaseOrder, Transaction, JournalEntry, Account

# Create your views here.
# Add Supplier
def add_supplier(request):
    if request.method == 'POST':
        form = SupplierForm(request.POST, request.FILES)
        if form.is_valid():
            form = form.save(commit=False)
            form.created_by = request.user
            form.save()
            return redirect('supplier_list')
    else:
        form = SupplierForm()
    return render(request, 'partners/add_supplier.html', {'form': form})

def supplier_list(request):
    query = request.GET.get("q")  # Get search query from URL parameter
    suppliers = Supplier.objects.all()

    # Apply search filter if a query exists
    if query:
        suppliers = suppliers.filter(
            Q(name__icontains=query) | 
            Q(phone__icontains=query) | 
            Q(email__icontains=query)
        )

    # Add Pagination (Show 10 suppliers per page)
    paginator = Paginator(suppliers, 10)
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    return render(request, "partners/supplier_list.html", {"page_obj": page_obj, "query": query})


def edit_supplier(request, pk):
    supplier = get_object_or_404(Supplier, pk=pk)
    if request.method == "POST":
        form = SupplierForm(request.POST, request.FILES, instance=supplier)
        if form.is_valid():
            form.save()
            return redirect("supplier_list")  # Redirect back to list after saving
    else:
        form = SupplierForm(instance=supplier)
    
    return render(request, "partners/edit_supplier.html", {"form": form, "supplier": supplier})

def delete_supplier(request, pk):
    supplier = get_object_or_404(Supplier, pk=pk)
    if request.method == "POST":
        supplier.delete()
        return redirect("supplier_list")  # Redirect after deleting
    
    return render(request, "partners/delete_supplier.html", {"supplier": supplier})

# Add Customer
def add_customer(request):
    if request.method == 'POST':
        form = CustomerForm(request.POST, request.FILES)
        if form.is_valid():
            form = form.save(commit=False)
            form.created_by = request.user
            form.save()
            return redirect('customer_list')
    else:
        form = CustomerForm()
    return render(request, 'partners/add_customer.html', {'form': form})

def customer_list(request):
    query = request.GET.get("q")  # Get search query from URL parameter
    customers = Customer.objects.all()

    # Apply search filter if a query exists
    if query:
        customers = customers.filter(
            Q(name__icontains=query) | 
            Q(phone__icontains=query) | 
            Q(email__icontains=query)
        )

    # Add Pagination (Show 10 customers per page)
    paginator = Paginator(customers, 10)
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    return render(request, "partners/customer_list.html", {"page_obj": page_obj, "query": query})

# Edit Customer View
def edit_customer(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    if request.method == "POST":
        form = CustomerForm(request.POST, request.FILES, instance=customer)
        if form.is_valid():
            form.save()
            return redirect("customer_list")  # Redirect back to list
    else:
        form = CustomerForm(instance=customer)

    return render(request, "partners/edit_customer.html", {"form": form, "customer": customer})

# Delete Customer View
def delete_customer(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    if request.method == "POST":
        customer.delete()
        return redirect("customer_list")  # Redirect after deleting

    return render(request, "partners/delete_customer.html", {"customer": customer})


# Add Transporter
def add_transporter(request):
    if request.method == 'POST':
        form = TransporterForm(request.POST, request.FILES)
        if form.is_valid():
            transporter = form.save(commit=False)
            transporter.created_by = request.user
            transporter.save()
            return redirect('transporter_list')
    else:
        form = TransporterForm()
    return render(request, 'partners/add_transporter.html', {'form': form})

def transporter_list(request):
    query = request.GET.get("q")  # Get search query from URL parameter
    transporter = Transporter.objects.all()

    # Apply search filter if a query exists
    if query:
        transporter = transporter.filter(
            Q(name__icontains=query) | 
            Q(phone__icontains=query) | 
            Q(email__icontains=query)
        )

    # Add Pagination (Show 10 customers per page)
    paginator = Paginator(transporter, 10)
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    return render(request, "partners/transporter_list.html", {"page_obj": page_obj, "query": query})


def edit_transporter(request, pk):
    transporter = get_object_or_404(Transporter, pk=pk)
    
    if request.method == "POST":
        form = TransporterForm(request.POST , request.FILES, instance=transporter)
        if form.is_valid():
            form.save()
            return redirect("transporter_list")  # Redirect back to list
    else:
        form = TransporterForm(instance=transporter)

    return render(request, "partners/edit_transporter.html", {"form": form, "transporter": transporter})

def delete_transporter(request, pk):
    transporter = get_object_or_404(Transporter, pk=pk)
    if request.method == "POST":
        transporter.delete()
        return redirect("transporter_list")  # Redirect after deleting

    return render(request, "partners/delete_transporter.html", {"transporter": transporter})


# Add Company
def add_company(request):
    if request.method == 'POST':
        form = CompanyForm(request.POST, request.FILES)
        if form.is_valid():
            company = form.save(commit=False)
            company.created_by = request.user
            company.save()
            return redirect('company_list')
    else:
        form = CompanyForm()
    return render(request, 'partners/add_company.html', {'form': form})

def company_list(request):
    query = request.GET.get("q")  # Get search query from URL parameter
    company = Company.objects.all()

    # Apply search filter if a query exists
    if query:
        company = company.filter(
            Q(company_name__icontains=query) | 
            Q(phone__icontains=query) | 
            Q(email__icontains=query)
        )

    # Add Pagination (Show 10 customers per page)
    paginator = Paginator(company, 10)
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    return render(request, "partners/company_list.html", {"page_obj": page_obj, "query": query})


def edit_company(request, pk):
    company = get_object_or_404(Company, pk=pk)
    if request.method == "POST":
        form = CompanyForm(request.POST, request.FILES, instance=company)
        if form.is_valid():
            form.save()
            return redirect("company_list")  # Redirect back to list
    else:
        form = CompanyForm(instance=company)

    return render(request, "partners/edit_company.html", {"form": form, "company": company})

def delete_company(request, pk):
    company = get_object_or_404(Company, pk=pk)
    if request.method == "POST":
        company.delete()
        return redirect("company_list")  # Redirect after deleting

    return render(request, "partners/delete_company.html", {"company": company})




# Ledgers for Suppliers and Customers
def supplier_ledger(request, supplier_id):
    supplier = get_object_or_404(Supplier, pk=supplier_id)

    # Date range filtering
    try:
        start_date = datetime.strptime(request.GET.get('start_date'), "%Y-%m-%d")
    except:
        start_date = datetime(datetime.now().year, 1, 1)

    try:
        end_date = datetime.strptime(request.GET.get('end_date'), "%Y-%m-%d")
    except:
        end_date = datetime.now()

    # Get the Accounts Payable account
    payable_account = Account.objects.filter(name__icontains="Accounts Payable").first()

    # Get related journal entries involving this supplier via purchase orders
    transactions = Transaction.objects.filter(
        account=payable_account,
        journal_entry__date__range=[start_date, end_date],
        journal_entry__supplier=supplier,
        journal_entry__status='posted'
    ).select_related('journal_entry')

    # Optional: Opening balance (before the start date)
    opening_balance = Transaction.objects.filter(
        account=payable_account,
        journal_entry__date__lt=start_date,
        # journal_entry__purchaseorder__supplier=supplier,
        journal_entry__status='posted'
    ).aggregate(
        total_debit=Sum('debit') or 0,
        total_credit=Sum('credit') or 0
    )

    opening = (opening_balance['total_credit'] or 0) - (opening_balance['total_debit'] or 0)

    # Process for display
    ledger_entries = []
    running_balance = opening

    for txn in transactions.order_by('journal_entry__date'):
        debit = txn.debit or 0
        credit = txn.credit or 0
        running_balance += credit - debit
        ledger_entries.append({
            'date': txn.journal_entry.date,
            'reference': txn.journal_entry.reference or txn.journal_entry.entry_number,
            'description': txn.journal_entry.description,
            'debit': debit,
            'credit': credit,
            'balance': running_balance,
        })

    context = {
        'supplier': supplier,
        'ledger_entries': ledger_entries,
        'opening_balance': opening,
        'start_date': start_date,
        'end_date': end_date,
        'final_balance': running_balance,
    }

    return render(request, 'accounting/supplier_ledger.html', context)

def customer_ledger(request, customer_id):
    customer = get_object_or_404(Customer, pk=customer_id)

    # Date range filtering
    try:
        start_date = datetime.strptime(request.GET.get('start_date'), "%Y-%m-%d")
    except:
        start_date = datetime(datetime.now().year, 1, 1)

    try:
        end_date = datetime.strptime(request.GET.get('end_date'), "%Y-%m-%d")
    except:
        end_date = datetime.now()

    # Get the Accounts Payable account
    receivable_account = Account.objects.filter(name__icontains="Accounts Receivable").first()

    # Get related journal entries involving this customer via sales orders
    transactions = Transaction.objects.filter(
        account=receivable_account,
        journal_entry__date__range=[start_date, end_date],
        journal_entry__customer=customer,
        journal_entry__status='posted'
    ).select_related('journal_entry')

    # Optional: Opening balance (before the start date)
    opening_balance = Transaction.objects.filter(
        account=receivable_account,
        journal_entry__date__lt=start_date,
        # journal_entry__purchaseorder__supplier=supplier,
        journal_entry__status='posted'
    ).aggregate(
        total_debit=Sum('debit') or 0,
        total_credit=Sum('credit') or 0
    )

    opening = (opening_balance['total_credit'] or 0) - (opening_balance['total_debit'] or 0)

    # Process for display
    ledger_entries = []
    running_balance = opening

    for txn in transactions.order_by('journal_entry__date'):
        debit = txn.debit or 0
        credit = txn.credit or 0
        running_balance += debit - credit
        ledger_entries.append({
            'date': txn.journal_entry.date,
            'reference': txn.journal_entry.reference or txn.journal_entry.entry_number,
            'description': txn.journal_entry.description,
            'debit': debit,
            'credit': credit,
            'balance': running_balance,
        })

    context = {
        'customer': customer,
        'ledger_entries': ledger_entries,
        'opening_balance': opening,
        'start_date': start_date,
        'end_date': end_date,
        'final_balance': running_balance,
    }

    return render(request, 'accounting/customer_ledger.html', context)


