import base64
import os
import subprocess
from django.conf import settings as django_settings
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy as _
from .utils import number_to_words_en, send_whatsapp_document
from django.core.paginator import Paginator
import decimal
from django.contrib.auth.models import User, Group, Permission
from django.urls import reverse
import random
import string
from django.shortcuts import render, get_object_or_404, redirect
from django.db.models import Sum, Count, F, Q
from django.db.models.functions import TruncDate, TruncMonth
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from .models import ( Expense, ExpenseCategory,
    Product, Sale, Category, Unit, Customer, Supplier, 
    Purchase, PurchaseItem, PurchasePayment, 
    SaleItem, SalePayment, SystemSetting,
    Quotation, QuotationItem,
    SaleReturn, SaleReturnItem, PurchaseReturn, PurchaseReturnItem,
    PaymentMethod, HeldSale, LoyaltyTier, LoyaltyTransaction
, Device)
import json
from datetime import timedelta
from django.utils import timezone
from django.contrib import messages
from django.utils.text import slugify
import openpyxl

@login_required
def index(request):
    """
    Enhanced Meezan Dashboard View
    """
    # Summary Stats
    total_products = Product.objects.count()
    total_sales_count = Sale.objects.count()
    total_sales_amount = Sale.objects.aggregate(total=Sum('total_amount'))['total'] or 0
    total_customers = Customer.objects.count()
    
        # Expired Items Alert
    today = timezone.now().date()
    expired_count = Product.objects.filter(has_expiry=True, expiry_date__lt=today, stock_quantity__gt=0).count()

    # Stock Alert (Low stock < 5)
    low_stock_products = Product.objects.filter(stock_quantity__lt=5)
    
    # Recent Transactions
    recent_sales = Sale.objects.order_by('-created_at').select_related('created_by')[:5]
    
    # Chart Data: Sales for the last 7 days
    seven_days_ago = timezone.now().date() - timedelta(days=6)
    sales_over_time = Sale.objects.filter(created_at__date__gte=seven_days_ago) \
        .annotate(date=TruncDate('created_at')) \
        .values('date') \
        .annotate(total=Sum('total_amount')) \
        .order_by('date')
    
    # Prepare data for Chart.js
    chart_labels = []
    chart_data = []
    
    date_dict = {s['date']: float(s['total']) for s in sales_over_time}
    for i in range(7):
        date = seven_days_ago + timedelta(days=i)
        chart_labels.append(date.strftime('%b %d'))
        chart_data.append(date_dict.get(date, 0))

    context = {
        'total_products': total_products,
        'total_sales_count': total_sales_count,
        'total_sales_amount': total_sales_amount,
        'total_customers': total_customers,
        'low_stock_products': low_stock_products, 'expired_count': expired_count,
        'recent_sales': recent_sales,
        'chart_labels': json.dumps(chart_labels),
        'chart_data': json.dumps(chart_data),
    }
    return render(request, 'core/index.html', context)

@login_required
def inventory(request):
    products_list = Product.objects.all().select_related('category', 'unit', 'supplier').order_by('-created_at')
    
    # Filter by category
    category_id = request.GET.get('category')
    if category_id:
        products_list = products_list.filter(category_id=category_id)
        
    # Search
    search = request.GET.get('search')
    if search:
        products_list = products_list.filter(
            Q(name_en__icontains=search) | 
            Q(name_ar__icontains=search) | 
            Q(sku__icontains=search)
        )

    # Expired items
    today = timezone.now().date()
    expired_products = Product.objects.filter(has_expiry=True, expiry_date__lt=today, stock_quantity__gt=0)
    expiring_soon_products = Product.objects.filter(has_expiry=True, expiry_date__gte=today, expiry_date__lte=today + timedelta(days=30), stock_quantity__gt=0)

    paginator = Paginator(products_list, 25)
    page_number = request.GET.get('page')
    products = paginator.get_page(page_number)
    
    categories = Category.objects.all()
    suppliers = Supplier.objects.all()
    units = Unit.objects.all()
    
    context = {
        'products': products, 
        'categories': categories, 
        'suppliers': suppliers,
        'units': units,
        'expired_products': expired_products,
        'expiring_soon_products': expiring_soon_products,
        'today': today
    }
    return render(request, 'core/inventory.html', context)

@login_required
def pos(request):
    products = Product.objects.all().filter(stock_quantity__gt=0, is_active=True)
    customers = Customer.objects.all()
    categories = Category.objects.all()
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    settings = SystemSetting.objects.first()
    
    # Ensure at least Cash exists
    if not payment_methods.exists():
        PaymentMethod.objects.create(name_en="Cash", name_ar="نقدي", is_active=True)
        payment_methods = PaymentMethod.objects.filter(is_active=True)
        
    context = {
        'products': products, 
        'customers': customers, 
        'categories': categories,
        'payment_methods': payment_methods,
        'settings': settings
    }
    return render(request, 'core/pos.html', context)

@login_required
def customers(request):
    customers_qs = Customer.objects.all().annotate(total_sales=Sum('sales__total_amount')).order_by('name')
    paginator = Paginator(customers_qs, 25)
    page_number = request.GET.get('page')
    customers_list = paginator.get_page(page_number)
    context = {'customers': customers_list}
    return render(request, 'core/customers.html', context)

@login_required
def suppliers(request):
    suppliers_qs = Supplier.objects.all().order_by('name')
    paginator = Paginator(suppliers_qs, 25)
    page_number = request.GET.get('page')
    suppliers_list = paginator.get_page(page_number)
    context = {'suppliers': suppliers_list}
    return render(request, 'core/suppliers.html', context)

# --- Purchase Views ---

@login_required
def supplier_payments(request):
    payments_qs = PurchasePayment.objects.all().select_related("purchase", "purchase__supplier", "payment_method", "created_by").order_by("-payment_date", "-id")
    paginator = Paginator(payments_qs, 25)
    page_number = request.GET.get("page")
    payments = paginator.get_page(page_number)
    return render(request, "core/supplier_payments.html", {"payments": payments})

def purchases(request):
    purchases_qs = Purchase.objects.all().select_related('supplier', 'created_by').order_by('-created_at')
    paginator = Paginator(purchases_qs, 25)
    page_number = request.GET.get('page')
    purchases_list = paginator.get_page(page_number)
    suppliers_qs = Supplier.objects.all().order_by('name')
    paginator = Paginator(suppliers_qs, 25)
    page_number = request.GET.get('page')
    suppliers_list = paginator.get_page(page_number)
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    context = {
        'purchases': purchases_list, 
        'suppliers': suppliers_list,
        'payment_methods': payment_methods
    }
    return render(request, 'core/purchases.html', context)

@login_required
def purchase_create(request):
    products = Product.objects.filter(is_active=True)
    suppliers = Supplier.objects.all()
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    return render(request, 'core/purchase_create.html', {
        'products': products, 
        'suppliers': suppliers,
        'payment_methods': payment_methods
    })

@login_required
def purchase_detail(request, pk):
    purchase = get_object_or_404(Purchase, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, 'core/purchase_detail.html', {
        'purchase': purchase, 
        'settings': settings,
        'amount_in_words': number_to_words_en(purchase.total_amount)
    })

@csrf_exempt
@login_required
def create_purchase_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            supplier_id = data.get('supplier_id')
            invoice_number = data.get('invoice_number', '')
            items = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            paid_amount = data.get('paid_amount', 0)
            payment_type = data.get('payment_type', 'cash')
            payment_method_id = data.get('payment_method_id')
            due_date = data.get('due_date')
            notes = data.get('notes', '')

            supplier = None
            if supplier_id:
                supplier = Supplier.objects.get(id=supplier_id)

            purchase = Purchase.objects.create(
                supplier=supplier,
                invoice_number=invoice_number,
                total_amount=total_amount,
                paid_amount=paid_amount,
                balance_due=float(total_amount) - float(paid_amount),
                payment_type=payment_type,
                due_date=due_date if due_date else None,
                notes=notes,
                created_by=request.user
            )

            # Set status based on payments
            if float(paid_amount) >= float(total_amount):
                purchase.status = 'paid'
            elif float(paid_amount) > 0:
                purchase.status = 'partial'
            else:
                purchase.status = 'unpaid'
            purchase.save()

            # Record the initial payment if any
            if float(paid_amount) > 0:
                pm = None
                if payment_method_id:
                    pm = PaymentMethod.objects.filter(id=payment_method_id).first()
                
                PurchasePayment.objects.create(
                    purchase=purchase,
                    amount=paid_amount,
                    payment_method=pm,
                    payment_method_name=pm.name_en if pm else payment_type.capitalize(),
                    notes="Initial payment",
                    created_by=request.user
                )

            for item in items:
                product = Product.objects.get(id=item['id'])
                item_expiry = item.get('expiry_date')
                PurchaseItem.objects.create(
                    purchase=purchase,
                    product=product,
                    quantity=item['quantity'],
                    cost_price=item['price'],
                    expiry_date=item_expiry if item_expiry else None,
                    line_total=item['line_total']
                )
                # Update Stock
                product.stock_quantity += int(item['quantity'])
                product.cost_price = item['price']
                
                if item_expiry:
                    product.has_expiry = True
                    if not product.expiry_date or str(item_expiry) > str(product.expiry_date):
                        product.expiry_date = item_expiry
                
                product.save()

            return JsonResponse({'success': True, 'purchase_id': purchase.id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def add_purchase_payment(request, pk):
    purchase = get_object_or_404(Purchase, pk=pk)
    if request.method == 'POST':
        amount = request.POST.get('amount')
        payment_date = request.POST.get('payment_date', timezone.now().date())
        payment_method_id = request.POST.get('payment_method_id')
        notes = request.POST.get('notes', '')
        
        pm = None
        if payment_method_id:
            pm = PaymentMethod.objects.filter(id=payment_method_id).first()

        PurchasePayment.objects.create(
            purchase=purchase,
            amount=amount,
            payment_date=payment_date,
            payment_method=pm,
            payment_method_name=pm.name_en if pm else "Cash",
            notes=notes,
            created_by=request.user
        )
        purchase.update_balance()
        messages.success(request, _("Payment added successfully!"))
    return redirect('purchases')

@login_required
def delete_purchase(request, pk):
    purchase = get_object_or_404(Purchase, pk=pk)
    for item in purchase.items.all():
        item.product.stock_quantity -= item.quantity
        item.product.save()
    
    purchase.delete()
    messages.success(request, _("Purchase deleted successfully!"))
    return redirect('purchases')

# --- Sale Views ---

@login_required
def invoice_list(request):
    sales = Sale.objects.all().select_related("customer", "created_by")

    # Filtering
    start_date = request.GET.get("start_date")
    end_date = request.GET.get("end_date")
    customer_id = request.GET.get("customer")
    status = request.GET.get("status")

    if start_date:
        sales = sales.filter(created_at__date__gte=start_date)
    if end_date:
        sales = sales.filter(created_at__date__lte=end_date)
    if customer_id:
        sales = sales.filter(customer_id=customer_id)
    if status:
        sales = sales.filter(status=status)

    sales = sales.order_by("-created_at")
    paginator = Paginator(sales, 25)
    page_number = request.GET.get("page")
    sales = paginator.get_page(page_number)

    customers = Customer.objects.all()
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    return render(request, "core/invoices.html", {
        "sales": sales,
        "customers": customers,
        "payment_methods": payment_methods
    })
@login_required
def invoice_create(request):

    products = Product.objects.filter(is_active=True)
    customers = Customer.objects.all()
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    return render(request, 'core/invoice_create.html', {
        'products': products, 
        'customers': customers,
        'payment_methods': payment_methods
    })

@login_required
def invoice_detail(request, pk):
    sale = get_object_or_404(Sale, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, 'core/invoice_detail.html', {
        'sale': sale, 
        'settings': settings,
        'amount_in_words': number_to_words_en(sale.total_amount)
    })

@login_required
def edit_invoice(request, pk):
    sale = get_object_or_404(Sale, pk=pk)
    # Prepare cart items for JSON
    cart_items = []
    for item in sale.items.all():
        cart_items.append({
            'id': item.product.id,
            'name_en': item.product.name_en,
            'sku': item.product.sku,
            'price': float(item.unit_price),
            'quantity': item.quantity
        })
    
    customers = Customer.objects.all()
    products = Product.objects.filter(is_active=True)
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    
    # Find initial payment method
    initial_payment = sale.payments.filter(notes='Initial payment').first()
    payment_method_id = initial_payment.payment_method_id if initial_payment else ''

    return render(request, 'core/invoice_edit.html', {
        'sale': sale,
        'customers': customers,
        'products': products,
        'payment_methods': payment_methods,
        'cart_json': json.dumps(cart_items),
        'payment_method_id': payment_method_id
    })

@csrf_exempt
def create_sale_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            customer_id = data.get('customer_id')
            invoice_number = data.get('invoice_number', '')
            items = data.get('items', [])
            
            # Retrieve amounts
            subtotal = data.get('subtotal', 0)
            vat_amount = data.get('vat_amount', 0)
            total_amount = data.get('total_amount', 0)
            
            paid_amount = data.get('paid_amount', 0)
            discount = data.get('discount', 0)
            payment_type = data.get('payment_type', 'cash')
            payment_method_id = data.get('payment_method_id')
            due_date = data.get('due_date')
            notes = data.get('notes', '')
            
            # Loyalty data
            points_to_redeem = data.get('loyalty_points_redeemed', 0)

            customer = None
            if customer_id:
                customer = Customer.objects.get(id=customer_id)

            if not customer and payment_type != 'cash':
                return JsonResponse({'success': False, 'error': _('Credit or Partial payments are not allowed for Guest customers.')}, status=400)

            settings = SystemSetting.objects.first()
            if not settings:
                settings = SystemSetting.objects.create()

            loyalty_discount = 0
            if settings.loyalty_enabled and customer and points_to_redeem > 0:
                if customer.loyalty_points >= points_to_redeem:
                    loyalty_discount = float(points_to_redeem) * float(settings.currency_per_point)

            sale = Sale.objects.create(
                customer=customer,
                invoice_number=invoice_number,
                subtotal=subtotal,
                vat_amount=vat_amount,
                total_amount=total_amount,
                paid_amount=paid_amount,
                balance_due=float(total_amount) - float(paid_amount),
                discount=discount,
                loyalty_points_redeemed=points_to_redeem,
                loyalty_discount_amount=loyalty_discount,
                payment_type=payment_type,
                due_date=due_date if due_date else None,
                notes=notes,
                created_by=request.user
            )

            # Set status based on payments
            if float(paid_amount) >= float(total_amount):
                sale.status = 'paid'
            elif float(paid_amount) > 0:
                sale.status = 'partial'
            else:
                sale.status = 'unpaid'
            sale.save()

            # Record initial payment if any
            if float(paid_amount) > 0:
                pm = None
                if payment_method_id:
                    pm = PaymentMethod.objects.filter(id=payment_method_id).first()
                
                SalePayment.objects.create(
                    sale=sale,
                    amount=paid_amount,
                    payment_method=pm,
                    payment_method_name=pm.name_en if pm else payment_type.capitalize(),
                    notes="Initial payment",
                    created_by=request.user
                )

            for item in items:
                product = Product.objects.get(id=item['id'])
                SaleItem.objects.create(
                    sale=sale,
                    product=product,
                    quantity=item['quantity'],
                    unit_price=item['price'],
                    line_total=item['line_total']
                )
                product.stock_quantity -= int(item['quantity'])
                product.save()

            # Handle Loyalty Points
            if settings.loyalty_enabled and customer:
                # Earn Points
                points_earned = float(total_amount) * float(settings.points_per_currency)
                if customer.loyalty_tier:
                    points_earned *= float(customer.loyalty_tier.point_multiplier)
                
                if points_earned > 0:
                    customer.loyalty_points += decimal.Decimal(str(points_earned))
                    LoyaltyTransaction.objects.create(
                        customer=customer,
                        sale=sale,
                        transaction_type='earned',
                        points=points_earned,
                        notes=f"Points earned from Sale #{sale.id}"
                    )
                
                # Redeem Points
                if points_to_redeem > 0:
                    customer.loyalty_points -= decimal.Decimal(str(points_to_redeem))
                    LoyaltyTransaction.objects.create(
                        customer=customer,
                        sale=sale,
                        transaction_type='redeemed',
                        points=-points_to_redeem,
                        notes=f"Points redeemed for Sale #{sale.id}"
                    )
                
                customer.update_tier()
                customer.save()

            return JsonResponse({
                'success': True, 
                'sale_id': sale.id,
                'business': {
                    'name': settings.business_name,
                    'address': settings.address,
                    'phone': settings.phone,
                    'email': settings.email,
                    'currency': settings.currency_symbol,
                    'vat_number': settings.vat_number,
                    'registration_number': settings.registration_number,
                    'logo_url': settings.logo.url if settings.logo else None
                },
                'sale': {
                    'id': sale.id,
                    'invoice_number': sale.invoice_number,
                    'created_at': sale.created_at.strftime("%Y-%m-%d %H:%M"),
                    'subtotal': float(sale.subtotal),
                    'vat_amount': float(sale.vat_amount),
                    'total': float(sale.total_amount),
                    'discount': float(sale.discount),
                    'paid': float(sale.paid_amount),
                    'balance': float(sale.balance_due),
                    'customer_name': sale.customer.name if sale.customer else 'Guest',
                    'items': [
                        {
                            'name_en': si.product.name_en,
                            'name_ar': si.product.name_ar,
                            'qty': si.quantity,
                            'price': float(si.unit_price),
                            'total': float(si.line_total)
                        } for si in sale.items.all()
                    ]
                }
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
def send_invoice_whatsapp(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            sale_id = data.get('sale_id')
            phone = data.get('phone')
            pdf_base64 = data.get('pdf_data')
            
            if not phone or not pdf_base64:
                return JsonResponse({'success': False, 'error': 'Missing phone or PDF data.'}, status=400)
            
            if ',' in pdf_base64:
                pdf_base64 = pdf_base64.split(',')[1]
            
            pdf_content = base64.b64decode(pdf_base64)
            
            temp_dir = os.path.join(django_settings.MEDIA_ROOT, 'temp_invoices')
            if not os.path.exists(temp_dir):
                os.makedirs(temp_dir)
            
            filename = f'Invoice_{sale_id}.pdf'
            file_path_pdf = os.path.join(temp_dir, filename)
            
            with open(file_path_pdf, 'wb') as f_pdf:
                f_pdf.write(pdf_content)
            
            base_url = request.build_absolute_uri('/')
            document_url = f"{base_url.rstrip('/')}{django_settings.MEDIA_URL}temp_invoices/{filename}"
            
            sale = Sale.objects.filter(id=sale_id).first()
            invoice_num = sale.invoice_number if sale and sale.invoice_number else sale_id
            caption = f'Invoice #{invoice_num}'
            
            success, message = send_whatsapp_document(phone, document_url, caption)
            
            return JsonResponse({'success': success, 'message': message})
            
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=500)
    
    return JsonResponse({'success': False, 'error': 'Invalid request method.'}, status=405)

@login_required
def add_sale_payment(request, pk):
    sale = get_object_or_404(Sale, pk=pk)
    if request.method == 'POST':
        amount = request.POST.get('amount')
        payment_date = request.POST.get('payment_date', timezone.now().date())
        payment_method_id = request.POST.get('payment_method_id')
        notes = request.POST.get('notes', '')
        
        pm = None
        if payment_method_id:
            pm = PaymentMethod.objects.filter(id=payment_method_id).first()

        SalePayment.objects.create(
            sale=sale,
            amount=amount,
            payment_date=payment_date,
            payment_method=pm,
            payment_method_name=pm.name_en if pm else "Cash",
            notes=notes,
            created_by=request.user
        )
        sale.update_balance()
        messages.success(request, _("Payment added successfully!"))
    return redirect('invoices')

@login_required
def delete_sale(request, pk):
    sale = get_object_or_404(Sale, pk=pk)
    for item in sale.items.all():
        item.product.stock_quantity += item.quantity
        item.product.save()
    sale.delete()
    messages.success(request, _("Sale deleted successfully!"))
    return redirect('invoices')

# --- Quotation Views ---

@login_required
def quotations(request):
    quotations_qs = Quotation.objects.all().select_related('customer', 'created_by').order_by('-created_at')
    paginator = Paginator(quotations_qs, 25)
    page_number = request.GET.get('page')
    quotations_list = paginator.get_page(page_number)
    customers = Customer.objects.all()
    return render(request, 'core/quotations.html', {'quotations': quotations_list, 'customers': customers})

@login_required
def quotation_create(request):
    products = Product.objects.filter(is_active=True)
    customers = Customer.objects.all()
    return render(request, 'core/quotation_create.html', {'products': products, 'customers': customers})

@login_required
def quotation_detail(request, pk):
    quotation = get_object_or_404(Quotation, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, 'core/quotation_detail.html', {
        'quotation': quotation, 
        'settings': settings,
        'amount_in_words': number_to_words_en(quotation.total_amount)
    })

@csrf_exempt
@login_required
def create_quotation_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            customer_id = data.get('customer_id')
            quotation_number = data.get('quotation_number', '')
            items = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            discount = data.get('discount', 0)
            valid_until = data.get('valid_until')
            terms_and_conditions = data.get('terms_and_conditions', '')
            notes = data.get('notes', '')

            customer = None
            if customer_id:
                customer = Customer.objects.get(id=customer_id)

            quotation = Quotation.objects.create(
                customer=customer,
                quotation_number=quotation_number,
                total_amount=total_amount,
                discount=discount,
                valid_until=valid_until if valid_until else None,
                terms_and_conditions=terms_and_conditions,
                notes=notes,
                created_by=request.user
            )

            for item in items:
                product = Product.objects.get(id=item['id'])
                QuotationItem.objects.create(
                    quotation=quotation,
                    product=product,
                    quantity=item['quantity'],
                    unit_price=item['price'],
                    line_total=item['line_total']
                )

            return JsonResponse({'success': True, 'quotation_id': quotation.id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def convert_quotation_to_invoice(request, pk):
    quotation = get_object_or_404(Quotation, pk=pk)
    if quotation.status == 'converted':
        messages.warning(request, _("This quotation has already been converted to an invoice."))
        return redirect('invoices')
    
    # Create Sale from Quotation
    sale = Sale.objects.create(
        customer=quotation.customer,
        quotation=quotation,
        total_amount=quotation.total_amount,
        discount=quotation.discount,
        balance_due=quotation.total_amount,
        payment_type='cash',
        status='unpaid',
        notes=quotation.notes,
        created_by=request.user
    )
    
    # Create SaleItems and Update Stock
    for item in quotation.items.all():
        SaleItem.objects.create(
            sale=sale,
            product=item.product,
            quantity=item.quantity,
            unit_price=item.unit_price,
            line_total=item.line_total
        )
        # Deduct Stock
        item.product.stock_quantity -= item.quantity
        item.product.save()
    
    # Update Quotation Status
    quotation.status = 'converted'
    quotation.save()
    
    messages.success(request, _("Quotation converted to Invoice successfully!"))
    return redirect('invoice_detail', pk=sale.pk)

@login_required
def delete_quotation(request, pk):
    quotation = get_object_or_404(Quotation, pk=pk)
    quotation.delete()
    messages.success(request, _("Quotation deleted successfully!"))
    return redirect('quotations')

# --- Sale Return Views ---

@login_required
def sales_returns(request):
    returns_qs = SaleReturn.objects.all().select_related('customer', 'created_by').order_by('-created_at')
    paginator = Paginator(returns_qs, 25)
    page_number = request.GET.get('page')
    returns = paginator.get_page(page_number)
    return render(request, 'core/sales_returns.html', {'returns': returns})

@login_required
def sale_return_create(request):
    products = Product.objects.filter(is_active=True)
    customers = Customer.objects.all()
    sales = Sale.objects.all().order_by('-created_at')
    return render(request, 'core/sale_return_create.html', {
        'products': products, 
        'customers': customers,
        'sales': sales
    })

@login_required
def sale_return_detail(request, pk):
    sale_return = get_object_or_404(SaleReturn, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, 'core/sale_return_detail.html', {
        'sale_return': sale_return, 
        'settings': settings,
        'amount_in_words': number_to_words_en(sale_return.total_amount)
    })

@csrf_exempt
@login_required
def create_sale_return_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            sale_id = data.get('sale_id')
            customer_id = data.get('customer_id')
            return_number = data.get('return_number', '')
            items = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            notes = data.get('notes', '')

            customer = None
            if customer_id:
                customer = Customer.objects.get(id=customer_id)
            
            sale = None
            if sale_id:
                sale = Sale.objects.get(id=sale_id)

            sale_return = SaleReturn.objects.create(
                sale=sale,
                customer=customer,
                return_number=return_number,
                total_amount=total_amount,
                notes=notes,
                created_by=request.user
            )

            for item in items:
                product = Product.objects.get(id=item['id'])
                SaleReturnItem.objects.create(
                    sale_return=sale_return,
                    product=product,
                    quantity=item['quantity'],
                    unit_price=item['price'],
                    line_total=item['line_total']
                )
                # Increase Stock for Sales Return
                product.stock_quantity += int(item['quantity'])
                product.save()

            return JsonResponse({'success': True, 'return_id': sale_return.id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def delete_sale_return(request, pk):
    sale_return = get_object_or_404(SaleReturn, pk=pk)
    for item in sale_return.items.all():
        item.product.stock_quantity -= item.quantity
        item.product.save()
    sale_return.delete()
    messages.success(request, _("Sale return deleted successfully!"))
    return redirect('sales_returns')


# --- Purchase Return Views ---

@login_required
def purchase_returns(request):
    returns_qs = PurchaseReturn.objects.all().select_related('supplier', 'created_by').order_by('-created_at')
    paginator = Paginator(returns_qs, 25)
    page_number = request.GET.get('page')
    returns = paginator.get_page(page_number)
    return render(request, 'core/purchase_returns.html', {'returns': returns})

@login_required
def purchase_return_create(request):
    products = Product.objects.filter(is_active=True)
    suppliers = Supplier.objects.all()
    purchases = Purchase.objects.all().order_by('-created_at')
    return render(request, 'core/purchase_return_create.html', {
        'products': products, 
        'customers': suppliers,
        'purchases': purchases
    })

@login_required
def purchase_return_detail(request, pk):
    purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, 'core/purchase_return_detail.html', {
        'purchase_return': purchase_return, 
        'settings': settings,
        'amount_in_words': number_to_words_en(purchase_return.total_amount)
    })

@csrf_exempt
@login_required
def create_purchase_return_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            purchase_id = data.get('purchase_id')
            supplier_id = data.get('supplier_id')
            return_number = data.get('return_number', '')
            items = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            notes = data.get('notes', '')

            supplier = None
            if supplier_id:
                supplier = Supplier.objects.get(id=supplier_id)
            
            purchase = None
            if purchase_id:
                purchase = Purchase.objects.get(id=purchase_id)

            purchase_return = PurchaseReturn.objects.create(
                purchase=purchase,
                supplier=supplier,
                return_number=return_number,
                total_amount=total_amount,
                notes=notes,
                created_by=request.user
            )

            for item in items:
                product = Product.objects.get(id=item['id'])
                PurchaseReturnItem.objects.create(
                    purchase_return=purchase_return,
                    product=product,
                    quantity=item['quantity'],
                    cost_price=item['price'],
                    line_total=item['line_total']
                )
                # Decrease Stock for Purchase Return
                product.stock_quantity -= int(item['quantity'])
                product.save()

            return JsonResponse({'success': True, 'return_id': purchase_return.id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def delete_purchase_return(request, pk):
    purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
    for item in purchase_return.items.all():
        item.product.stock_quantity += item.quantity
        item.product.save()
    purchase_return.delete()
    messages.success(request, _("Purchase return deleted successfully!"))
    return redirect('purchase_returns')

# --- Other Management Views ---

@login_required
def reports(request):
    """
    Smart Reports View
    """
    # Monthly Revenue
    monthly_sales = Sale.objects.annotate(month=TruncMonth('created_at')) \
        .values('month') \
        .annotate(total=Sum('total_amount')) \
        .order_by('-month')[:12]
    
    # Top Selling Products
    top_products = SaleItem.objects.values('product__name_en', 'product__name_ar') \
        .annotate(total_qty=Sum('quantity'), revenue=Sum('line_total')) \
        .order_by('-total_qty')[:5]
    
    context = {
        'monthly_sales': monthly_sales,
        'top_products': top_products,
    }
    return render(request, 'core/reports.html', context)

@login_required
def settings_view(request):
    """
    Smart Admin Settings View
    """
    settings = SystemSetting.objects.first()
    if not settings:
        settings = SystemSetting.objects.create()
    
    if request.method == "POST":
        if "business_name" in request.POST:
            settings.business_name = request.POST.get("business_name") or "Meezan Accounting"
            settings.address = request.POST.get("address", "")
            settings.phone = request.POST.get("phone", "")
            settings.email = request.POST.get("email", "")
            settings.currency_symbol = request.POST.get("currency_symbol", "OMR")
            settings.tax_rate = request.POST.get("tax_rate", 0)
            settings.decimal_places = request.POST.get("decimal_places", 3)
            settings.vat_number = request.POST.get("vat_number", "")
            settings.registration_number = request.POST.get("registration_number", "")
            
            settings.loyalty_enabled = request.POST.get("loyalty_enabled") == "on"
            settings.points_per_currency = request.POST.get("points_per_currency", 1.0)
            settings.currency_per_point = request.POST.get("currency_per_point", 0.010)
            settings.min_points_to_redeem = request.POST.get("min_points_to_redeem", 100)
            
            if "logo" in request.FILES:
                settings.logo = request.FILES["logo"]
        
        elif "wablas_token" in request.POST or "wablas_enabled" in request.POST or "wablas_server_url" in request.POST:
            settings.wablas_enabled = request.POST.get("wablas_enabled") == "on"
            settings.wablas_token = request.POST.get("wablas_token", "")
            settings.wablas_server_url = request.POST.get("wablas_server_url", "")
            settings.wablas_secret_key = request.POST.get("wablas_secret_key", "")

        settings.save()
        messages.success(request, _("Settings updated successfully!"))
        
        if "business_name" in request.POST:
            return redirect(reverse("settings") + "#profile")
        elif "wablas_token" in request.POST or "wablas_enabled" in request.POST or "wablas_server_url" in request.POST:
            return redirect(reverse("settings") + "#whatsapp")
        else:
            return redirect(reverse("settings"))

    payment_methods = PaymentMethod.objects.all().order_by("name_en")
    loyalty_tiers = LoyaltyTier.objects.all().order_by("min_points")
    devices = Device.objects.all().order_by("name")
    
    context = {
        "settings": settings,
        "payment_methods": payment_methods,
        "loyalty_tiers": loyalty_tiers,
        "devices": devices
    }
    return render(request, "core/settings.html", context)

@login_required
def add_payment_method(request):
    if request.method == 'POST':
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        is_active = request.POST.get('is_active') == 'on'
        has_expiry = request.POST.get('has_expiry') == 'on'
        expiry_date = request.POST.get('expiry_date')
        if not has_expiry:
            expiry_date = None
        PaymentMethod.objects.create(name_en=name_en, name_ar=name_ar, is_active=is_active)
        messages.success(request, _("Payment method added successfully!"))
    return redirect(reverse('settings') + '#payments')

@login_required
def edit_payment_method(request, pk):
    pm = get_object_or_404(PaymentMethod, pk=pk)
    if request.method == 'POST':
        pm.name_en = request.POST.get('name_en')
        pm.name_ar = request.POST.get('name_ar')
        pm.is_active = request.POST.get('is_active') == 'on'
        pm.save()
        messages.success(request, _("Payment method updated successfully!"))
    return redirect(reverse('settings') + '#payments')

@login_required
def delete_payment_method(request, pk):
    pm = get_object_or_404(PaymentMethod, pk=pk)
    pm.delete()
    messages.success(request, _("Payment method deleted successfully!"))
    return redirect(reverse('settings') + '#payments')

@login_required
def add_customer(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        phone = request.POST.get('phone')
        email = request.POST.get('email')
        address = request.POST.get('address')
        Customer.objects.create(name=name, phone=phone, email=email, address=address)
        messages.success(request, _("Customer added successfully!"))
    return redirect('customers')

@login_required
def edit_customer(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    if request.method == 'POST':
        customer.name = request.POST.get('name')
        customer.phone = request.POST.get('phone')
        customer.email = request.POST.get('email')
        customer.address = request.POST.get('address')
        customer.save()
        messages.success(request, _("Customer updated successfully!"))
    return redirect('customers')

@login_required
def delete_customer(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    customer.delete()
    messages.success(request, _("Customer deleted successfully!"))
    return redirect('customers')

@login_required
def add_supplier(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        contact_person = request.POST.get('contact_person')
        phone = request.POST.get('phone')
        Supplier.objects.create(name=name, contact_person=contact_person, phone=phone)
        messages.success(request, _("Supplier added successfully!"))
    return redirect('suppliers')

@login_required
def edit_supplier(request, pk):
    supplier = get_object_or_404(Supplier, pk=pk)
    if request.method == 'POST':
        supplier.name = request.POST.get('name')
        supplier.contact_person = request.POST.get('contact_person')
        supplier.phone = request.POST.get('phone')
        supplier.save()
        messages.success(request, _("Supplier updated successfully!"))
    return redirect('suppliers')

@login_required
def delete_supplier(request, pk):
    supplier = get_object_or_404(Supplier, pk=pk)
    supplier.delete()
    messages.success(request, _("Supplier deleted successfully!"))
    return redirect('suppliers')


@login_required
def suggest_sku(request):
    """
    API endpoint to suggest a unique SKU. 
    """
    while True: 
        # Generate a random 8-digit number 
        sku = "".join(random.choices(string.digits, k=8)) 
        if not Product.objects.filter(sku=sku).exists(): 
            return JsonResponse({"sku": sku})

@login_required
def add_product(request):
    if request.method == 'POST':
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        category_id = request.POST.get('category')
        unit_id = request.POST.get('unit')
        supplier_id = request.POST.get('supplier')
        sku = request.POST.get('sku')
        if not sku:
            while True:
                sku = ''.join(random.choices(string.digits, k=8))
                if not Product.objects.filter(sku=sku).exists():
                    break
        cost_price = request.POST.get('cost_price', 0)
        price = request.POST.get('price', 0)
        vat = request.POST.get('vat', 0)
        description = request.POST.get('description', '')
        opening_stock = request.POST.get('opening_stock', 0)
        stock_quantity = request.POST.get('stock_quantity', 0)
        is_active = request.POST.get('is_active') == 'on'
        has_expiry = request.POST.get('has_expiry') == 'on'
        expiry_date = request.POST.get('expiry_date')
        if not has_expiry:
            expiry_date = None
        
        category = get_object_or_404(Category, id=category_id)
        unit = get_object_or_404(Unit, id=unit_id) if unit_id else None
        supplier = get_object_or_404(Supplier, id=supplier_id) if supplier_id else None
        
        product = Product.objects.create(
            name_en=name_en, 
            name_ar=name_ar, 
            category=category, 
            unit=unit,
            supplier=supplier,
            sku=sku, 
            cost_price=cost_price,
            price=price, 
            vat=vat,
            description=description,
            opening_stock=opening_stock,
            stock_quantity=stock_quantity,
            is_active=is_active,
            has_expiry=has_expiry,
            min_stock_level=request.POST.get('min_stock_level', 0),
            expiry_date=expiry_date
        )
        
        if 'image' in request.FILES:
            product.image = request.FILES['image']
            product.save()
            
        messages.success(request, _("Product added successfully!"))
    return redirect(reverse('inventory') + '#items')

@login_required
def edit_product(request, pk):
    product = get_object_or_404(Product, pk=pk)
    if request.method == 'POST':
        product.name_en = request.POST.get('name_en')
        product.name_ar = request.POST.get('name_ar')
        product.sku = request.POST.get('sku')
        product.category = get_object_or_404(Category, id=request.POST.get('category'))
        
        unit_id = request.POST.get('unit')
        product.unit = get_object_or_404(Unit, id=unit_id) if unit_id else None
        
        supplier_id = request.POST.get('supplier')
        product.supplier = get_object_or_404(Supplier, id=supplier_id) if supplier_id else None
        
        product.cost_price = request.POST.get('cost_price', 0)
        product.price = request.POST.get('price', 0)
        product.vat = request.POST.get('vat', 0)
        product.description = request.POST.get('description', '')
        product.opening_stock = request.POST.get('opening_stock', 0)
        product.stock_quantity = request.POST.get('stock_quantity', 0)
        product.min_stock_level = request.POST.get('min_stock_level', 0)
        product.is_active = request.POST.get('is_active') == 'on'
        product.has_expiry = request.POST.get('has_expiry') == 'on'
        product.expiry_date = request.POST.get('expiry_date')
        if not product.has_expiry:
            product.expiry_date = None
        
        if 'image' in request.FILES:
            product.image = request.FILES['image']
            
        product.save()
        messages.success(request, _("Product updated successfully!"))
        return redirect(reverse('inventory') + '#items')
    return redirect(reverse('inventory') + '#items')

    return redirect(reverse('inventory') + '#items')

@login_required
def delete_product(request, pk):
    product = get_object_or_404(Product, pk=pk)
    product.delete()
    messages.success(request, _("Product deleted successfully!"))
    return redirect(reverse('inventory') + '#items')

@login_required
def add_category(request):
    if request.method == 'POST':
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        slug = slugify(name_en)
        Category.objects.create(name_en=name_en, name_ar=name_ar, slug=slug)
        messages.success(request, _("Category added successfully!"))
    return redirect(reverse('inventory') + '#categories-list')

@login_required
def edit_category(request, pk):
    category = get_object_or_404(Category, pk=pk)
    if request.method == 'POST':
        category.name_en = request.POST.get('name_en')
        category.name_ar = request.POST.get('name_ar')
        category.slug = slugify(category.name_en)
        category.save()
        messages.success(request, _("Category updated successfully!"))
    return redirect(reverse('inventory') + '#categories-list')

@login_required
def delete_category(request, pk):
    category = get_object_or_404(Category, pk=pk)
    category.delete()
    messages.success(request, _("Category deleted successfully!"))
    return redirect(reverse('inventory') + '#categories-list')

@login_required
def add_unit(request):
    if request.method == 'POST':
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        short_name = request.POST.get('short_name')
        Unit.objects.create(name_en=name_en, name_ar=name_ar, short_name=short_name)
        messages.success(request, _("Unit added successfully!"))
    return redirect(reverse('inventory') + '#units-list')

@login_required
def edit_unit(request, pk):
    unit = get_object_or_404(Unit, pk=pk)
    if request.method == 'POST':
        unit.name_en = request.POST.get('name_en')
        unit.name_ar = request.POST.get('name_ar')
        unit.short_name = request.POST.get('short_name')
        unit.save()
        messages.success(request, _("Unit updated successfully!"))
    return redirect(reverse('inventory') + '#units-list')

@login_required
def delete_unit(request, pk):
    unit = get_object_or_404(Unit, pk=pk)
    unit.delete()
    messages.success(request, _("Unit deleted successfully!"))
    return redirect(reverse('inventory') + '#units-list')

@login_required
def barcode_labels(request):
    products = Product.objects.filter(is_active=True).order_by('name_en')
    context = {'products': products}
    return render(request, 'core/barcode_labels.html', context)

@login_required
def import_products(request):
    """
    Import products from an Excel (.xlsx) file.
    Expected columns: Name (Eng), Name (Ar), SKU, Cost Price, Sale Price
    """
    if request.method == 'POST' and request.FILES.get('excel_file'):
        excel_file = request.FILES['excel_file']
        
        if not excel_file.name.endswith('.xlsx'):
            messages.error(request, _("Please upload a valid .xlsx file."))
            return redirect(reverse('inventory') + '#items')

        try:
            wb = openpyxl.load_workbook(excel_file)
            sheet = wb.active
            
            # Get or create a default category
            default_category, _ = Category.objects.get_or_create(
                name_en="General", 
                defaults={'name_ar': "عام", 'slug': 'general'}
            )
            
            count = 0
            updated_count = 0
            errors = []
            
            # Skip header row (min_row=2)
            for i, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
                if not any(row): continue # Skip empty rows
                
                # Unpack columns with fallbacks for safety
                # Format: name_en, name_ar, sku, cost_price, sale_price
                name_en = str(row[0]).strip() if row[0] else None
                name_ar = str(row[1]).strip() if len(row) > 1 and row[1] else name_en
                sku = str(row[2]).strip() if len(row) > 2 and row[2] else None
                cost_price = row[3] if len(row) > 3 and row[3] is not None else 0
                sale_price = row[4] if len(row) > 4 and row[4] is not None else 0
                
                if not name_en:
                    errors.append(f"Row {i}: Missing English Name. Skipped.")
                    continue
                
                if not sku:
                    # Generate unique SKU if missing
                    while True:
                        sku = "".join(random.choices(string.digits, k=8))
                        if not Product.objects.filter(sku=sku).exists():
                            break
                
                product, created = Product.objects.update_or_create(
                    sku=sku,
                    defaults={
                        'name_en': name_en,
                        'name_ar': name_ar,
                        'cost_price': cost_price,
                        'price': sale_price,
                        'category': default_category,
                        'is_active': True
                    }
                )
                
                if created:
                    count += 1
                else:
                    updated_count += 1
            
            if count > 0 or updated_count > 0:
                msg = f"Import completed: {count} new items added"
                if updated_count > 0:
                    msg += f", {updated_count} items updated"
                messages.success(request, msg)
                
            if errors:
                for error in errors:
                    messages.warning(request, error)
                    
        except Exception as e:
            messages.error(request, f"Error processing file: {str(e)}")
            
    return redirect(reverse('inventory') + '#items')

@csrf_exempt
@login_required
def add_category_ajax(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            name_en = data.get('name_en')
            name_ar = data.get('name_ar')
            if not name_en or not name_ar:
                return JsonResponse({'success': False, 'error': 'Missing names'}, status=400)
            
            slug = slugify(name_en)
            category = Category.objects.create(name_en=name_en, name_ar=name_ar, slug=slug)
            return JsonResponse({
                'success': True, 
                'id': category.id, 
                'name_en': category.name_en, 
                'name_ar': category.name_ar
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@csrf_exempt
@login_required
def add_unit_ajax(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            name_en = data.get('name_en')
            name_ar = data.get('name_ar')
            short_name = data.get('short_name')
            if not name_en or not name_ar or not short_name:
                return JsonResponse({'success': False, 'error': 'Missing fields'}, status=400)
            
            unit = Unit.objects.create(name_en=name_en, name_ar=name_ar, short_name=short_name)
            return JsonResponse({
                'success': True, 
                'id': unit.id, 
                'name_en': unit.name_en, 
                'name_ar': unit.name_ar
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@csrf_exempt
@login_required
def add_supplier_ajax(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            name = data.get('name')
            contact_person = data.get('contact_person', '')
            phone = data.get('phone', '')
            if not name:
                return JsonResponse({'success': False, 'error': 'Missing name'}, status=400)
            
            supplier = Supplier.objects.create(name=name, contact_person=contact_person, phone=phone)
            return JsonResponse({
                'success': True, 
                'id': supplier.id, 
                'name': supplier.name
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def user_management(request):
    if not (request.user.is_superuser or request.user.groups.filter(name='admin').exists()):
        messages.error(request, _("Access denied."))
        return redirect('index')
    
    users_qs = User.objects.all().prefetch_related('groups').order_by('username')
    paginator = Paginator(users_qs, 25)
    page_number = request.GET.get('page')
    users = paginator.get_page(page_number)
    groups = Group.objects.all().prefetch_related('permissions')
    # Filter for relevant permissions (core and auth)
    excluded_apps = ['admin', 'auth', 'contenttypes', 'sessions']
    permissions = Permission.objects.select_related('content_type').exclude(content_type__app_label__in=excluded_apps).order_by('content_type__app_label', 'content_type__model', 'codename')
    
    if request.method == 'POST':
        action = request.POST.get('action')
        if action == 'add':
            username = request.POST.get('username')
            password = request.POST.get('password')
            email = request.POST.get('email')
            group_ids = request.POST.getlist('groups')
            
            if User.objects.filter(username=username).exists():
                messages.error(request, _("Username already exists."))
            else:
                user = User.objects.create_user(username=username, email=email, password=password)
                if group_ids:
                    selected_groups = Group.objects.filter(id__in=group_ids)
                    user.groups.set(selected_groups)
                user.is_staff = True
                user.save()
                messages.success(request, f"User {username} created successfully.")
        
        elif action == 'edit_user':
            user_id = request.POST.get('user_id')
            user = get_object_or_404(User, id=user_id)
            user.email = request.POST.get('email')
            group_ids = request.POST.getlist('groups')
            selected_groups = Group.objects.filter(id__in=group_ids)
            user.groups.set(selected_groups)
            
            password = request.POST.get('password')
            if password:
                user.set_password(password)
            
            user.save()
            messages.success(request, f"User {user.username} updated.")

        elif action == 'add_group':
            name = request.POST.get('name')
            permission_ids = request.POST.getlist('permissions')
            if Group.objects.filter(name=name).exists():
                messages.error(request, _("Group name already exists."))
            else:
                group = Group.objects.create(name=name)
                if permission_ids:
                    perms = Permission.objects.filter(id__in=permission_ids)
                    group.permissions.set(perms)
                messages.success(request, f"Group {name} created successfully.")

        elif action == 'edit_group':
            group_id = request.POST.get('group_id')
            group = get_object_or_404(Group, id=group_id)
            group.name = request.POST.get('name')
            permission_ids = request.POST.getlist('permissions')
            perms = Permission.objects.filter(id__in=permission_ids)
            group.permissions.set(perms)
            group.save()
            messages.success(request, f"Group {group.name} updated.")

        elif action == 'delete_group':
            group_id = request.POST.get('group_id')
            group = get_object_or_404(Group, id=group_id)
            group.delete()
            messages.success(request, _("Group deleted."))

        elif action == 'toggle_status':
            user_id = request.POST.get('user_id')
            user = get_object_or_404(User, id=user_id)
            if user == request.user:
                messages.error(request, _("You cannot deactivate yourself."))
            else:
                user.is_active = not user.is_active
                user.save()
                messages.success(request, f"User {user.username} status updated.")
        
        # Determine redirect hash based on action
        target_hash = ""
        if action in ['add_group', 'edit_group', 'delete_group']:
            target_hash = "#groups"
        
        return redirect(reverse('user_management') + target_hash)
        
    return render(request, 'core/users.html', {
        'users': users, 
        'groups': groups,
        'permissions': permissions
    })

@login_required
def group_details_api(request, pk):
    group = get_object_or_404(Group, pk=pk)
    permissions = group.permissions.all().values_list('id', flat=True)
    return JsonResponse({
        'id': group.id,
        'name': group.name,
        'permissions': list(permissions)
    })

@csrf_exempt
@login_required
def add_payment_method_ajax(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            name_en = data.get('name_en')
            name_ar = data.get('name_ar')
            is_active = data.get('is_active', True)
            if not name_en or not name_ar:
                return JsonResponse({'success': False, 'error': 'Missing names'}, status=400)
            
            pm = PaymentMethod.objects.create(name_en=name_en, name_ar=name_ar, is_active=is_active)
            return JsonResponse({
                'success': True, 
                'id': pm.id, 
                'name_en': pm.name_en, 
                'name_ar': pm.name_ar
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@csrf_exempt
@login_required
def add_customer_ajax(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            name = data.get('name')
            phone = data.get('phone', '')
            email = data.get('email', '')
            address = data.get('address', '')
            if not name:
                return JsonResponse({'success': False, 'error': 'Missing name'}, status=400)
            
            customer = Customer.objects.create(name=name, phone=phone, email=email, address=address)
            return JsonResponse({
                'success': True, 
                'id': customer.id, 
                'name': customer.name
            })
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def hold_sale_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            customer_id = data.get('customer_id')
            cart_data = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            notes = data.get('notes', '')

            customer = None
            if customer_id:
                customer = Customer.objects.filter(id=customer_id).first()

            held_sale = HeldSale.objects.create(
                customer=customer,
                cart_data=cart_data,
                total_amount=total_amount,
                notes=notes,
                created_by=request.user
            )
            return JsonResponse({'success': True, 'held_id': held_sale.id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def get_held_sales_api(request):
    held_sales = HeldSale.objects.filter(created_by=request.user).select_related('customer').order_by('-created_at')
    data = []
    for hs in held_sales:
        data.append({
            'id': hs.id,
            'customer_name': hs.customer.name if hs.customer else 'Guest',
            'total_amount': float(hs.total_amount),
            'items_count': len(hs.cart_data),
            'created_at': hs.created_at.strftime("%Y-%m-%d %H:%M"),
            'notes': hs.notes
        })
    return JsonResponse({'success': True, 'held_sales': data})

@login_required
def recall_held_sale_api(request, pk):
    held_sale = get_object_or_404(HeldSale, pk=pk, created_by=request.user)
    data = {
        'success': True,
        'customer_id': held_sale.customer.id if held_sale.customer else None,
        'customer_name': held_sale.customer.name if held_sale.customer else "",
        'items': held_sale.cart_data,
        'total_amount': float(held_sale.total_amount),
        'notes': held_sale.notes
    }
    held_sale.delete()
    return JsonResponse(data)

@login_required
def delete_held_sale_api(request, pk):
    held_sale = get_object_or_404(HeldSale, pk=pk, created_by=request.user)
    held_sale.delete()
    return JsonResponse({'success': True})

@login_required
def add_loyalty_tier(request):
    if request.method == 'POST':
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        min_points = request.POST.get('min_points', 0)
        multiplier = request.POST.get('point_multiplier', 1.0)
        discount = request.POST.get('discount_percentage', 0)
        color = request.POST.get('color_code', '#6c757d')
        
        LoyaltyTier.objects.create(
            name_en=name_en, name_ar=name_ar, 
            min_points=min_points, point_multiplier=multiplier, 
            discount_percentage=discount, color_code=color
        )
        messages.success(request, _("Loyalty tier added successfully!"))
    return redirect(reverse('settings') + '#loyalty')

@login_required
def edit_loyalty_tier(request, pk):
    tier = get_object_or_404(LoyaltyTier, pk=pk)
    if request.method == 'POST':
        tier.name_en = request.POST.get('name_en')
        tier.name_ar = request.POST.get('name_ar')
        tier.min_points = request.POST.get('min_points')
        tier.point_multiplier = request.POST.get('point_multiplier')
        tier.discount_percentage = request.POST.get('discount_percentage')
        tier.color_code = request.POST.get('color_code')
        tier.save()
        messages.success(request, _("Loyalty tier updated successfully!"))
    return redirect(reverse('settings') + '#loyalty')

@login_required
def delete_loyalty_tier(request, pk):
    tier = get_object_or_404(LoyaltyTier, pk=pk)
    tier.delete()
    messages.success(request, _("Loyalty tier deleted successfully!"))
    return redirect(reverse('settings') + '#loyalty')

@login_required
def get_customer_loyalty_api(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    settings = SystemSetting.objects.first()
    
    tier_info = None
    if customer.loyalty_tier:
        tier_info = {
            'name_en': customer.loyalty_tier.name_en,
            'name_ar': customer.loyalty_tier.name_ar,
            'multiplier': float(customer.loyalty_tier.point_multiplier),
            'discount': float(customer.loyalty_tier.discount_percentage),
            'color': customer.loyalty_tier.color_code
        }
    
    return JsonResponse({
        'success': True,
        'points': float(customer.loyalty_points),
        'tier': tier_info,
        'currency_per_point': float(settings.currency_per_point) if settings else 0.01,
        'min_points_to_redeem': settings.min_points_to_redeem if settings else 100
    })

@login_required
def profile_view(request):
    """
    User Profile View
    """
    if request.method == 'POST':
        user = request.user
        user.first_name = request.POST.get('first_name')
        user.last_name = request.POST.get('last_name')
        user.email = request.POST.get('email')
        
        # Profile specific
        profile = user.profile
        profile.phone = request.POST.get('phone')
        profile.bio = request.POST.get('bio')
        
        if 'image' in request.FILES:
            profile.image = request.FILES['image']
            
        user.save()
        profile.save()
        
        # Password change
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        if password:
            if password == confirm_password:
                user.set_password(password)
                user.save()
                from django.contrib.auth import update_session_auth_hash
                update_session_auth_hash(request, user)
                messages.success(request, _("Profile and password updated successfully!"))
            else:
                messages.error(request, _("Passwords do not match."))
        else:
            messages.success(request, _("Profile updated successfully!"))
            
        return redirect('profile')

    return render(request, 'core/profile.html')

# --- Expenses Views ---

@login_required
def expenses_view(request):
    """
    List and filter expenses
    """
    expenses = Expense.objects.all().order_by('-date', '-created_at')
    
    # Filtering
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    category_id = request.GET.get('category')
    
    if start_date:
        expenses = expenses.filter(date__gte=start_date)
    if end_date:
        expenses = expenses.filter(date__lte=end_date)
    if category_id:
        expenses = expenses.filter(category_id=category_id)
        
    paginator = Paginator(expenses, 25)
    page_number = request.GET.get('page')
    expenses = paginator.get_page(page_number)
    categories = ExpenseCategory.objects.all()
    payment_methods = PaymentMethod.objects.filter(is_active=True)
    
    context = {
        'expenses': expenses,
        'categories': categories,
        'payment_methods': payment_methods,
        'start_date': start_date,
        'end_date': end_date,
        'category_id': category_id,
    }
    return render(request, 'core/expenses.html', context)

@login_required
def expense_create_view(request):
    """
    Create a new expense
    """
    if request.method == 'POST':
        category_id = request.POST.get('category')
        amount = request.POST.get('amount')
        date = request.POST.get('date') or timezone.now().date()
        description = request.POST.get('description', '')
        payment_method_id = request.POST.get('payment_method')
        attachment = request.FILES.get('attachment')
        
        category = get_object_or_404(ExpenseCategory, id=category_id)
        pm = None
        if payment_method_id:
            pm = get_object_or_404(PaymentMethod, id=payment_method_id)
            
        Expense.objects.create(
            category=category,
            amount=amount,
            date=date,
            description=description,
            payment_method=pm,
            attachment=attachment,
            created_by=request.user
        )
        messages.success(request, _("Expense recorded successfully!"))
        
    return redirect('expenses')

@login_required
def expense_delete_view(request, pk):
    """
    Delete an expense
    """
    expense = get_object_or_404(Expense, pk=pk)
    expense.delete()
    messages.success(request, _("Expense deleted successfully!"))
    return redirect('expenses')

@login_required
def expense_categories_view(request):
    """
    Manage expense categories
    """
    if request.method == 'POST':
        category_id = request.POST.get('category_id')
        name_en = request.POST.get('name_en')
        name_ar = request.POST.get('name_ar')
        description = request.POST.get('description', '')
        
        if category_id:
            category = get_object_or_404(ExpenseCategory, id=category_id)
            category.name_en = name_en
            category.name_ar = name_ar
            category.description = description
            category.save()
            messages.success(request, _("Expense category updated successfully!"))
        else:
            ExpenseCategory.objects.create(
                name_en=name_en,
                name_ar=name_ar,
                description=description
            )
            messages.success(request, _("Expense category created successfully!"))
        return redirect('expense_categories')
        
    categories = ExpenseCategory.objects.all().order_by('name_en')
    return render(request, 'core/expense_categories.html', {'categories': categories})

@login_required
def expense_category_delete_view(request, pk):
    """
    Delete an expense category
    """
    category = get_object_or_404(ExpenseCategory, pk=pk)
    category.delete()
    messages.success(request, _("Expense category deleted successfully!"))
    return redirect('expense_categories')
@csrf_exempt
@login_required
def update_sale_api(request, pk):
    if request.method == 'POST':
        try:
            sale = get_object_or_404(Sale, pk=pk)
            data = json.loads(request.body)
            customer_id = data.get('customer_id')
            invoice_number = data.get('invoice_number', '')
            items = data.get('items', [])
            total_amount = data.get('total_amount', 0)
            paid_amount = data.get('paid_amount', 0)
            discount = data.get('discount', 0)
            payment_type = data.get('payment_type', 'cash')
            payment_method_id = data.get('payment_method_id')
            due_date = data.get('due_date')
            notes = data.get('notes', '')
            points_to_redeem = data.get('loyalty_points_redeemed', 0)

            settings = SystemSetting.objects.first()
            if not settings:
                settings = SystemSetting.objects.create()

            # 1. Restore Stock
            for item in sale.items.all():
                item.product.stock_quantity += item.quantity
                item.product.save()

            # 2. Reverse Loyalty Points for the old customer
            if sale.customer and settings.loyalty_enabled:
                for lt in sale.loyalty_transactions.all():
                    sale.customer.loyalty_points -= decimal.Decimal(str(lt.points))
                    lt.delete()
                sale.customer.update_tier()
                sale.customer.save()

            # 3. Update Sale Metadata
            customer = None
            if customer_id:
                customer = Customer.objects.get(id=customer_id)

            if not customer and payment_type != 'cash':
                return JsonResponse({'success': False, 'error': _('Credit or Partial payments are not allowed for Guest customers.')}, status=400)
            
            sale.customer = customer
            sale.invoice_number = invoice_number
            sale.total_amount = total_amount
            sale.discount = discount
            sale.payment_type = payment_type
            sale.due_date = due_date if due_date else None
            sale.notes = notes
            
            # Loyalty discount recalculation
            loyalty_discount = 0
            if settings.loyalty_enabled and customer and points_to_redeem > 0:
                if float(customer.loyalty_points) >= float(points_to_redeem):
                    loyalty_discount = float(points_to_redeem) * float(settings.currency_per_point)
            
            sale.loyalty_points_redeemed = points_to_redeem
            sale.loyalty_discount_amount = loyalty_discount
            sale.save()

            # 4. Handle Items (Delete old, Create new)
            sale.items.all().delete()
            for item in items:
                product = Product.objects.get(id=item['id'])
                SaleItem.objects.create(
                    sale=sale,
                    product=product,
                    quantity=item['quantity'],
                    unit_price=item['price'],
                    line_total=item['line_total']
                )
                product.stock_quantity -= int(item['quantity'])
                product.save()

            # 5. Handle Payments
            sale.paid_amount = paid_amount
            sale.balance_due = float(total_amount) - float(paid_amount)
            
            if float(paid_amount) >= float(total_amount):
                sale.status = 'paid'
            elif float(paid_amount) > 0:
                sale.status = 'partial'
            else:
                sale.status = 'unpaid'
            sale.save()

            pm = None
            if payment_method_id:
                pm = PaymentMethod.objects.filter(id=payment_method_id).first()
            
            initial_payment = sale.payments.filter(notes="Initial payment").first()
            if initial_payment:
                initial_payment.amount = paid_amount
                initial_payment.payment_method = pm
                initial_payment.payment_method_name = pm.name_en if pm else payment_type.capitalize()
                initial_payment.save()
            elif float(paid_amount) > 0:
                SalePayment.objects.create(
                    sale=sale,
                    amount=paid_amount,
                    payment_method=pm,
                    payment_method_name=pm.name_en if pm else payment_type.capitalize(),
                    notes="Initial payment",
                    created_by=request.user
                )

            # 6. Re-apply Loyalty for the (possibly new) customer
            if settings.loyalty_enabled and customer:
                points_earned = float(total_amount) * float(settings.points_per_currency)
                if customer.loyalty_tier:
                    points_earned *= float(customer.loyalty_tier.point_multiplier)
                
                if points_earned > 0:
                    customer.loyalty_points += decimal.Decimal(str(points_earned))
                    LoyaltyTransaction.objects.create(
                        customer=customer,
                        sale=sale,
                        transaction_type='earned',
                        points=points_earned,
                        notes=f"Points earned from Updated Sale #{sale.id}"
                    )
                
                if points_to_redeem > 0:
                    customer.loyalty_points -= decimal.Decimal(str(points_to_redeem))
                    LoyaltyTransaction.objects.create(
                        customer=customer,
                        sale=sale,
                        transaction_type='redeemed',
                        points=-points_to_redeem,
                        notes=f"Points redeemed for Updated Sale #{sale.id}"
                    )
                
                customer.update_tier()
                customer.save()

            return JsonResponse({'success': True})
        except Exception as e:
            import traceback
            traceback.print_exc()
            return JsonResponse({'success': False, 'error': str(e)}, status=400)
    return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)

@login_required
def customer_payments(request):
    """
    List of payments received from customers
    """
    payments_qs = SalePayment.objects.all().select_related("sale", "sale__customer", "payment_method", "created_by").order_by("-payment_date", "-id")
    
    # Filtering
    start_date = request.GET.get("start_date")
    end_date = request.GET.get("end_date")
    customer_id = request.GET.get("customer")
    
    if start_date:
        payments_qs = payments_qs.filter(payment_date__gte=start_date)
    if end_date:
        payments_qs = payments_qs.filter(payment_date__lte=end_date)
    if customer_id:
        payments_qs = payments_qs.filter(sale__customer_id=customer_id)
        
    paginator = Paginator(payments_qs, 25)
    page_number = request.GET.get("page")
    payments = paginator.get_page(page_number)
    
    customers = Customer.objects.all().order_by("name")
    
    return render(request, "core/customer_payments.html", {
        "payments": payments,
        "customers": customers,
        "start_date": start_date,
        "end_date": end_date,
        "customer_id": customer_id,
    })

@login_required
@login_required
def sale_receipt(request, pk):
    """
    Printable receipt for a fully paid sale
    """
    sale = get_object_or_404(Sale, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, "core/sale_receipt.html", {
        "sale": sale,
        "settings": settings,
        "amount_in_words": number_to_words_en(sale.total_amount)
    })

def customer_payment_receipt(request, pk):
    """
    Printable receipt for a customer payment
    """
    payment = get_object_or_404(SalePayment, pk=pk)
    settings = SystemSetting.objects.first()
    return render(request, "core/customer_payment_receipt.html", {
        "payment": payment,
        "settings": settings,
        "amount_in_words": number_to_words_en(payment.amount)
    })

@login_required
def customer_statement(request):
    """
    Generate a transaction statement for a specific customer.
    """
    customers = Customer.objects.all().order_by('name')
    customer_id = request.GET.get('customer')
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    
    statement_data = []
    customer = None
    opening_balance = 0
    
    if customer_id:
        customer = get_object_or_404(Customer, id=customer_id)
        
        # Calculate opening balance before start_date
        if start_date:
            sales_before = Sale.objects.filter(customer=customer, created_at__date__lt=start_date).aggregate(total=Sum('total_amount'))['total'] or 0
            returns_before = SaleReturn.objects.filter(customer=customer, created_at__date__lt=start_date).aggregate(total=Sum('total_amount'))['total'] or 0
            payments_before = SalePayment.objects.filter(sale__customer=customer, payment_date__lt=start_date).aggregate(total=Sum('amount'))['total'] or 0
            opening_balance = float(sales_before) - float(returns_before) - float(payments_before)

        # Fetch transactions within range
        sales = Sale.objects.filter(customer=customer)
        returns = SaleReturn.objects.filter(customer=customer)
        payments = SalePayment.objects.filter(sale__customer=customer)
        
        if start_date:
            sales = sales.filter(created_at__date__gte=start_date)
            returns = returns.filter(created_at__date__gte=start_date)
            payments = payments.filter(payment_date__gte=start_date)
        if end_date:
            sales = sales.filter(created_at__date__lte=end_date)
            returns = returns.filter(created_at__date__lte=end_date)
            payments = payments.filter(payment_date__lte=end_date)
            
        for sale in sales:
            statement_data.append({
                'date': sale.created_at.date(),
                'type': _('Sale Invoice'),
                'reference': sale.invoice_number or f"#{sale.id}",
                'debit': float(sale.total_amount),
                'credit': 0,
            })
        for ret in returns:
            statement_data.append({
                'date': ret.created_at.date(),
                'type': _('Sale Return'),
                'reference': ret.return_number or f"#{ret.id}",
                'debit': 0,
                'credit': float(ret.total_amount),
            })
        for pay in payments:
            statement_data.append({
                'date': pay.payment_date,
                'type': _('Payment'),
                'reference': pay.notes or _('Payment Received'),
                'debit': 0,
                'credit': float(pay.amount),
            })
            
        statement_data.sort(key=lambda x: (x['date'], x['type']))
        
        running_balance = opening_balance
        for item in statement_data:
            running_balance += item['debit'] - item['credit']
            item['balance'] = running_balance
            
    settings = SystemSetting.objects.first()
    context = {
        'customers': customers,
        'customer': customer,
        'statement_data': statement_data,
        'opening_balance': opening_balance, 'opening_balance_abs': abs(opening_balance),
        'start_date': start_date,
        'end_date': end_date,
        'settings': settings
    }
    return render(request, 'core/customer_statement.html', context)

@login_required
def supplier_statement(request):
    """
    Generate a transaction statement for a specific supplier.
    """
    suppliers = Supplier.objects.all().order_by('name')
    supplier_id = request.GET.get('supplier')
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    
    statement_data = []
    supplier = None
    opening_balance = 0
    
    if supplier_id:
        supplier = get_object_or_404(Supplier, id=supplier_id)
        
        # Calculate opening balance before start_date
        if start_date:
            purchases_before = Purchase.objects.filter(supplier=supplier, created_at__date__lt=start_date).aggregate(total=Sum('total_amount'))['total'] or 0
            returns_before = PurchaseReturn.objects.filter(supplier=supplier, created_at__date__lt=start_date).aggregate(total=Sum('total_amount'))['total'] or 0
            payments_before = PurchasePayment.objects.filter(purchase__supplier=supplier, payment_date__lt=start_date).aggregate(total=Sum('amount'))['total'] or 0
            opening_balance = float(purchases_before) - float(returns_before) - float(payments_before)

        # Fetch transactions within range
        purchases = Purchase.objects.filter(supplier=supplier)
        returns = PurchaseReturn.objects.filter(supplier=supplier)
        payments = PurchasePayment.objects.filter(purchase__supplier=supplier)
        
        if start_date:
            purchases = purchases.filter(created_at__date__gte=start_date)
            returns = returns.filter(created_at__date__gte=start_date)
            payments = payments.filter(payment_date__gte=start_date)
        if end_date:
            purchases = purchases.filter(created_at__date__lte=end_date)
            returns = returns.filter(created_at__date__lte=end_date)
            payments = payments.filter(payment_date__lte=end_date)
            
        for purchase in purchases:
            statement_data.append({
                'date': purchase.created_at.date(),
                'type': _('Purchase Invoice'),
                'reference': purchase.invoice_number or f"#{purchase.id}",
                'debit': float(purchase.total_amount),
                'credit': 0,
            })
        for ret in returns:
            statement_data.append({
                'date': ret.created_at.date(),
                'type': _('Purchase Return'),
                'reference': ret.return_number or f"#{ret.id}",
                'debit': 0,
                'credit': float(ret.total_amount),
            })
        for pay in payments:
            statement_data.append({
                'date': pay.payment_date,
                'type': _('Payment'),
                'reference': pay.notes or _('Payment Sent'),
                'debit': 0,
                'credit': float(pay.amount),
            })
            
        statement_data.sort(key=lambda x: (x['date'], x['type']))
        
        running_balance = opening_balance
        for item in statement_data:
            running_balance += item['debit'] - item['credit']
            item['balance'] = running_balance
            
    settings = SystemSetting.objects.first()
    context = {
        'suppliers': suppliers,
        'supplier': supplier,
        'statement_data': statement_data,
        'opening_balance': opening_balance, 'opening_balance_abs': abs(opening_balance),
        'start_date': start_date,
        'end_date': end_date,
        'settings': settings
    }
    return render(request, 'core/supplier_statement.html', context)

@login_required
def cashflow_report(request):
    """
    Generate a Cashflow report summarizing income and expenses.
    """
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    
    # Defaults to current month if no dates provided
    if not start_date:
        start_date = timezone.now().date().replace(day=1).strftime('%Y-%m-%d')
    if not end_date:
        end_date = timezone.now().date().strftime('%Y-%m-%d')

    # Fetching Inflows (Sale Payments)
    sale_payments = SalePayment.objects.all().select_related('sale', 'sale__customer')
    if start_date:
        sale_payments = sale_payments.filter(payment_date__gte=start_date)
    if end_date:
        sale_payments = sale_payments.filter(payment_date__lte=end_date)
    
    # Fetching Outflows (Purchase Payments)
    purchase_payments = PurchasePayment.objects.all().select_related('purchase', 'purchase__supplier')
    if start_date:
        purchase_payments = purchase_payments.filter(payment_date__gte=start_date)
    if end_date:
        purchase_payments = purchase_payments.filter(payment_date__lte=end_date)
        
    # Fetching Outflows (Expenses)
    expenses = Expense.objects.all().select_related('category', 'payment_method')
    if start_date:
        expenses = expenses.filter(date__gte=start_date)
    if end_date:
        expenses = expenses.filter(date__lte=end_date)

    # Prepare detailed transactions list
    transactions = []
    
    for pay in sale_payments:
        transactions.append({
            'date': pay.payment_date,
            'type': _('Sale Payment'),
            'reference': pay.sale.invoice_number or f"Sale #{pay.sale.id}",
            'contact': pay.sale.customer.name if pay.sale.customer else _('Guest'),
            'inflow': float(pay.amount),
            'outflow': 0,
            'method': pay.payment_method_name
        })
        
    for pay in purchase_payments:
        transactions.append({
            'date': pay.payment_date,
            'type': _('Purchase Payment'),
            'reference': pay.purchase.invoice_number or f"Purchase #{pay.purchase.id}",
            'contact': pay.purchase.supplier.name if pay.purchase.supplier else 'N/A',
            'inflow': 0,
            'outflow': float(pay.amount),
            'method': pay.payment_method_name
        })
        
    for exp in expenses:
        transactions.append({
            'date': exp.date,
            'type': _('Expense'),
            'reference': exp.category.name_en,
            'contact': _('Various'),
            'inflow': 0,
            'outflow': float(exp.amount),
            'method': exp.payment_method.name_en if exp.payment_method else _('N/A')
        })

    transactions.sort(key=lambda x: x['date'], reverse=True)
    
    total_inflow = sum(item['inflow'] for item in transactions)
    total_outflow = sum(item['outflow'] for item in transactions)
    net_cashflow = total_inflow - total_outflow
    
    settings = SystemSetting.objects.first()
    
    context = {
        'transactions': transactions,
        'total_inflow': total_inflow,
        'total_outflow': total_outflow,
        'net_cashflow': net_cashflow,
        'start_date': start_date,
        'end_date': end_date,
        'settings': settings
    }
    return render(request, 'core/cashflow_report.html', context)


@login_required
def test_whatsapp_connection(request):
    """
    AJAX view to test the WhatsApp connection.
    """
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            phone = data.get('phone')
            if not phone:
                return JsonResponse({'success': False, 'error': _("Phone number is required.")})
            
            from .utils import send_whatsapp_message
            success, message = send_whatsapp_message(phone, _("Hello! This is a test message from your Meezan Smart Admin WhatsApp Gateway."))
            
            return JsonResponse({'success': success, 'message': message})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})
    return JsonResponse({'success': False, 'error': _("Invalid request method.")})


@login_required
def add_device(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        device_type = request.POST.get('device_type')
        connection_type = request.POST.get('connection_type')
        ip_address = request.POST.get('ip_address')
        port = request.POST.get('port')
        is_active = request.POST.get('is_active') == 'on'
        
        Device.objects.create(
            name=name,
            device_type=device_type,
            connection_type=connection_type,
            ip_address=ip_address if ip_address else None,
            port=port if port else None,
            is_active=is_active
        )
        messages.success(request, _("Device added successfully!"))
    return redirect(reverse('settings') + '#devices')

@login_required
def edit_device(request, pk):
    device = get_object_or_404(Device, pk=pk)
    if request.method == 'POST':
        device.name = request.POST.get('name')
        device.device_type = request.POST.get('device_type')
        device.connection_type = request.POST.get('connection_type')
        device.ip_address = request.POST.get('ip_address')
        device.port = request.POST.get('port')
        device.is_active = request.POST.get('is_active') == 'on'
        
        if not device.ip_address:
            device.ip_address = None
        if not device.port:
            device.port = None
            
        device.save()
        messages.success(request, _("Device updated successfully!"))
    return redirect(reverse('settings') + '#devices')

@login_required
def delete_device(request, pk):
    device = get_object_or_404(Device, pk=pk)
    device.delete()
    messages.success(request, _("Device deleted successfully!"))
    return redirect(reverse('settings') + '#devices')
@login_required
def search_customers_api(request):
    query = request.GET.get('q', '')
    if query:
        customers = Customer.objects.filter(
            Q(name__icontains=query) | Q(phone__icontains=query)
        ).values('id', 'name', 'phone')[:20]
    else:
        customers = []
    return JsonResponse({'results': list(customers)})
@login_required
def backup_database(request):
    if not request.user.is_superuser:
        messages.error(request, _("Access denied."))
        return redirect('settings')
    
    db_settings = django_settings.DATABASES['default']
    db_name = db_settings['NAME']
    db_user = db_settings['USER']
    db_password = db_settings['PASSWORD']
    db_host = db_settings['HOST']
    db_port = db_settings['PORT']
    
    timestamp = timezone.now().strftime('%Y-%m-%d_%H-%M-%S')
    filename = f"backup_{db_name}_{timestamp}.sql"
    
    env = os.environ.copy()
    env['MYSQL_PWD'] = db_password
    
    command = [
        'mysqldump',
        '-h', db_host,
        '-P', str(db_port),
        '-u', db_user,
        '--no-tablespaces',
        db_name
    ]
    
    try:
        process = subprocess.Popen(command, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        output, error = process.communicate()
        
        if process.returncode != 0:
            messages.error(request, f"Backup failed: {error.decode('utf-8')}")
            return redirect('settings')
            
        response = HttpResponse(output, content_type='application/octet-stream')
        response['Content-Disposition'] = f'attachment; filename="{filename}"'
        return response
        
    except Exception as e:
        messages.error(request, f"An error occurred: {str(e)}")
        return redirect('settings')

@login_required
def restore_database(request):
    if not request.user.is_superuser:
        messages.error(request, _("Access denied."))
        return redirect('settings')
        
    if request.method == 'POST' and request.FILES.get('backup_file'):
        backup_file = request.FILES['backup_file']
        
        if not backup_file.name.endswith('.sql'):
             messages.error(request, _("Please upload a valid .sql file."))
             return redirect(reverse('settings') + '#backup')
             
        db_settings = django_settings.DATABASES['default']
        db_name = db_settings['NAME']
        db_user = db_settings['USER']
        db_password = db_settings['PASSWORD']
        db_host = db_settings['HOST']
        db_port = db_settings['PORT']
        
        env = os.environ.copy()
        env['MYSQL_PWD'] = db_password
        
        command = [
            'mysql',
            '-h', db_host,
            '-P', str(db_port),
            '-u', db_user,
            db_name
        ]
        
        try:
            file_content = backup_file.read()
            
            process = subprocess.Popen(command, env=env, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
            output, error = process.communicate(input=file_content)
            
            if process.returncode != 0:
                 messages.error(request, f"Restore failed: {error.decode('utf-8')}")
            else:
                 messages.success(request, _("Database restored successfully!"))
                 
        except Exception as e:
             messages.error(request, f"An error occurred: {str(e)}")
             
    return redirect(reverse('settings') + '#backup')


@login_required
def customer_display(request):
    """
    Customer Facing Display (CFD) View
    """
    settings = SystemSetting.objects.first()
    return render(request, 'core/customer_display.html', {'settings': settings})
