from django.shortcuts import render
import json
import random
from django.conf import settings
import hashlib
import os
from django.conf import settings
from datetime import datetime
from django.utils import timezone
from django.db.models import Max, F, Q
import base64
from io import BytesIO
from django.conf import settings
from django.template.loader import get_template
from django.http import HttpResponse,HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.templatetags.static import static
from xhtml2pdf import pisa
from num2words import num2words
from django.contrib.staticfiles import finders
from django.contrib import messages
from user_auth.models import *
from company.models import *
from masters.models import *
from financial_year.models import *
from common.utils import *
from common.models import *
from store.models import *
from employee.models import *
from user_auth.forms import *
from privilege.models import *
from wholesale.models import *
from django.db.models.functions import TruncMonth, TruncDay
from django.db.models import Sum, Count, Q, Avg
from django.db import transaction as db_transaction, IntegrityError
from urllib.parse import urlencode

# ********************************************************************************

def wholesale_login(request):
    if request.method == 'GET':
        customer_uuid = (request.GET.get('uuid') or '').strip()
        if not customer_uuid:
            # Backward compatibility for old links like /wholesale/login?<uuid>
            raw_query = (request.META.get('QUERY_STRING', '') or '').strip()
            if raw_query and '=' not in raw_query:
                customer_uuid = raw_query

        next_url = (request.GET.get('next') or '').strip()

        if not customer_uuid:
            return render(request, 'external_wholesale/login.html', {'error': 'UUID missing from URL.'})

        customer = customer_table.objects.filter(uuid=customer_uuid, status=1).first()
        if not customer:
            return render(request, 'external_wholesale/login.html', {'error': 'Invalid or expired login link.'})

        return render(request, 'external_wholesale/login.html', {
            'customer': customer,
            'uuid': customer_uuid,
            'next_url': next_url
        })

    if request.method == 'POST':
        action = request.POST.get('action', 'login')
        customer_uuid = request.POST.get('uuid')
        next_url = (request.POST.get('next') or request.GET.get('next') or '').strip()
        
        if not customer_uuid:
            return JsonResponse({'status': 'error', 'message': 'Missing UUID'}, status=400)
            
        customer = customer_table.objects.filter(uuid=customer_uuid, status=1).first()
        if not customer:
            return JsonResponse({'status': 'error', 'message': 'Customer not found'}, status=404)

        # PREVENT BRUTE FORCE: (Optional implementation - skipped for now as per "Do Not Modify other modules")

        if action == 'login':
            password = request.POST.get('password')
            if not password:
                return JsonResponse({'status': 'error', 'message': 'Password is required'})
                
            hashed_pwd = hashlib.md5(password.encode()).hexdigest()
            
            if customer.password == hashed_pwd:
                # Login logic (setting session)
                company = company_table.objects.get(status=1, id=1)
                request.session['fyf'] = None

                current_fy = company.current_fy
                financial = financial_year_table.objects.filter(id=current_fy).first()

                if financial:
                    request.session['fyf'] = financial.name
                    fyf_parts = financial.name.split('-')
                    if len(fyf_parts) == 2:
                        request.session['fyf_start'] = fyf_parts[0].strip()
                        request.session['fyf_end'] = fyf_parts[1].strip()

                request.session['user_id'] = customer.id
                request.session['customer_id'] = customer.id
                request.session['name'] = customer.name
                request.session['user_name'] = customer.name
                request.session['branch_id'] = customer.branch_id
                request.session['user_mail'] = customer.email
                request.session['phone'] = customer.phone
                request.session['user_type'] = 'wholesale_customer'
                request.session['customer_uuid'] = customer.uuid

                redirect_url = '/wholesale/dashboard'
                if next_url and next_url.startswith('/wholesale/'):
                    redirect_url = next_url
                    print(redirect_url)

                return JsonResponse({
                    'status': 'success',
                    'redirect_url': redirect_url
                })
            else:
                return JsonResponse({'status': 'error', 'message': 'Incorrect password'})

        elif action == 'regenerate':
            # Generate random 8-digit password
            new_pass = str(random.randint(10000000, 99999999))
            hashed_new_pass = hashlib.md5(new_pass.encode()).hexdigest()
            
            customer.password = hashed_new_pass
            customer.save()
            
            # Return new password to display
            return JsonResponse({
                'status': 'success', 
                'message': 'Password regenerated successfully',
                'new_password': new_pass
            })

    return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)


      
def wholesale_dashboard(request):
    user_id = request.session.get('user_id')
    user_type = request.session.get('user_type')
    
    if user_id and user_type == 'wholesale_customer':
        try:
           
            # 1. Purchase Summary (What customer bought from store)
            purchase_data = sales_order_table.objects.filter(
                customer_id=user_id, 
                customer_type__iexact='wholesale', 
                status=1
            ).aggregate(
                total_purchase_amt=Sum('total_amount'),
                total_purchase_qty=Sum('total_quantity')
            )

            today = timezone.now().date()
            this_month = today.replace(day=1)

            # 1. Sales Summary (What customer sold to their customers)
            sales_summary_data = wholesale_sales_order_table.objects.filter(customer_id=user_id, status=1)
            sales_totals = sales_summary_data.aggregate(
                total_amt=Sum('total_amount'),
                total_qty=Sum('total_quantity'),
                total_collected=Sum('collected_amount'),
                total_paid=Sum('total_paid'),
                total_orders=Count('id')
            )

            # Today's Sales
            sales_today = sales_summary_data.filter(inv_date=today).aggregate(Sum('total_amount'))['total_amount__sum'] or 0
            # Monthly Sales
            sales_this_month = sales_summary_data.filter(inv_date__gte=this_month).aggregate(Sum('total_amount'))['total_amount__sum'] or 0
            # Total Customers
            total_customers = sales_summary_data.values('customer_name').distinct().count()

            # 2. Stock Summary
            available_stock = get_wholesale_customer_available_stock(user_id)
            stock_count = available_stock.count()
            stock_value = available_stock.aggregate(Sum('rate'))['rate__sum'] or 0

            # 3. Claims Summary
            claims_summary_data = wholesale_child_sales_order_table.objects.filter(customer_id=user_id, status=1, is_claim=1)
            claims_totals = claims_summary_data.aggregate(
                total_claims=Sum('claim_amount'),
                pending_claims=Sum('claim_amount', filter=Q(upgrade_status='pending')),
                approved_claims=Sum('claim_amount', filter=Q(upgrade_status='approved'))
            )

            # 4. Recent Sales
            recent_sales = sales_summary_data.order_by('-created_on')[:10]
            
            # 5. Brand Performance (Top 5)
            brand_perf = wholesale_child_sales_order_table.objects.filter(
                customer_id=user_id, 
                status=1
            ).values('brand_id').annotate(
                total=Sum('amount'), 
                qty=Sum('quantity')
            ).order_by('-total')[:5]
            
            for item in brand_perf:
                item['brand_name'] = getItemNameById(brand_table, item['brand_id'])

            # 6. Monthly Sales Trend
            sales_trend = sales_summary_data.annotate(
                month=TruncMonth('inv_date')
            ).values('month').annotate(
                total=Sum('total_amount')
            ).order_by('month')
            
            # 7. Recent Claims
            recent_claims = claims_summary_data.order_by('-created_on')[:5]

            context = {
                'purchase_data': purchase_data,
                'sales_totals': sales_totals,
                'sales_today': sales_today,
                'sales_this_month': sales_this_month,
                'total_customers': total_customers,
                'stock_count': stock_count,
                'stock_value': stock_value,
                'claims_totals': claims_totals,
                'recent_sales': recent_sales,
                'brand_perf': list(brand_perf),
                'sales_trend': list(sales_trend),
                'recent_claims': recent_claims,
                'current_datetime': timezone.now(),
            }
            return render(request, 'external_wholesale/dashboard.html', context)
        except Exception as e:
            print(f"Dashboard error: {str(e)}")
            return render(request, 'external_wholesale/dashboard.html', {'error': str(e)})
    else:
        customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
        next_url = request.get_full_path()
        params = {}
        if customer_uuid:
            params['uuid'] = customer_uuid
        if next_url:
            params['next'] = next_url
        login_url = '/wholesale/login/'
        if params:
            login_url = f"{login_url}?{urlencode(params)}"
        return HttpResponseRedirect(login_url)



"""
Common utility functions for wholesale customer stock calculations.
This module provides reusable logic for determining available stock for wholesale customers.
"""

from django.db.models import Q
from sales.models import sales_order_table, child_sales_order_table


def get_wholesale_customer_available_stock(customer_id, filters=None, exclude_tm_sales_id=None):
    """
    Calculate available stock for a wholesale customer.
    
    Logic:
    1. Get all IMEIs purchased by the wholesale customer (from sales_order_table)
    2. Exclude IMEIs already sold by the wholesale customer (from wholesale_child_sales_order_table)
       - If exclude_tm_sales_id is provided, don't count IMEIs from that specific TM Sales record as "sold"
    3. Apply optional filters (subcategory, brand, model, variant, color)
    """
    if filters is None:
        filters = {}
    
    # 1. Get TM Sales IDs (Inward for Wholesaler)
    tm_sales_ids = sales_order_table.objects.filter(
        customer_id=customer_id,
        customer_type__iexact='wholesale',
        status=1
    ).values_list('id', flat=True)
    
    # 2. Build query filters
    query_filters = Q(tm_sales_id__in=tm_sales_ids, status=1)
    
    # Apply optional filters
    if filters.get('subcategory_id'):
        query_filters &= Q(subcategory_id=filters['subcategory_id'])
    if filters.get('brand_id'):
        query_filters &= Q(brand_id=filters['brand_id'])
    if filters.get('model_id'):
        query_filters &= Q(model_id=filters['model_id'])
    if filters.get('variant_id'):
        query_filters &= Q(variant_id=filters['variant_id'])
    if filters.get('color_id'):
        query_filters &= Q(color_id=filters['color_id'])
    
    # 3. Get purchased items
    purchased_items = child_sales_order_table.objects.filter(query_filters)
    
    # 4. Get sold IMEIs (already sold by wholesaler)
    purchased_imeis = purchased_items.exclude(
        imei_no__isnull=True
    ).exclude(
        imei_no=''
    ).values_list('imei_no', flat=True)
    
    sold_query = Q(status=1, imei_no__in=purchased_imeis)
    if exclude_tm_sales_id:
        sold_query &= ~Q(tm_sales_id=exclude_tm_sales_id)
        
    sold_imeis = set(wholesale_child_sales_order_table.objects.filter(
        sold_query
    ).values_list('imei_no', flat=True))

    # 5. Get returned IMEIs (returned by wholesaler back to store)
    # Import here to avoid circular dependency if any
    from sales.models import child_sales_return_table
    returned_imeis = set(child_sales_return_table.objects.filter(
        customer_id=customer_id,
        imei_no__in=purchased_imeis,
        status=1
    ).values_list('imei_no', flat=True))
    
    # 6. Return only available items (not yet sold and not returned)
    available_items = purchased_items.exclude(
        Q(imei_no__in=sold_imeis) | Q(imei_no__in=returned_imeis)
    )
    
    return available_items





def stock_list(request):
    user_type = request.session.get('user_type')
    if user_type != 'wholesale_customer':
        customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
        next_url = request.get_full_path()
        params = {}
        if customer_uuid:
            params['uuid'] = customer_uuid
        if next_url:
            params['next'] = next_url
        login_url = '/wholesale/login/'
        if params:
            login_url = f"{login_url}?{urlencode(params)}"
        return HttpResponseRedirect(login_url)

    context = {}
    context['sub_category'] = selectList(sub_category_table)
    context['brand'] = selectList(brand_table)
    
    return render(request, 'external_wholesale/stock_sumamry.html', context)

def ajax_wholesale_stock(request):
    user_type = request.session.get('user_type')
    if user_type != 'wholesale_customer':
        return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})

    customer_id = request.session.get('customer_id')
    print(customer_id)

    # Build filters from request
    filters = {}
    f_sub = request.POST.get('subcategory')
    f_brand = request.POST.get('brand_id')
    f_model = request.POST.get('model_id')
    f_variant = request.POST.get('variant_id')
    f_color = request.POST.get('color_id')

    if f_sub:
        filters['subcategory_id'] = f_sub
    if f_brand:
        filters['brand_id'] = f_brand
    if f_model:
        filters['model_id'] = f_model
    if f_variant:
        filters['variant_id'] = f_variant
    if f_color:
        filters['color_id'] = f_color

    # Get available stock using common utility
    available_items = get_wholesale_customer_available_stock(customer_id, filters)

    data = []
    counter = 1
    
    for item in available_items:
        row = {}
        row['id'] = counter
        row['sub_category'] = getItemNameById(sub_category_table, item.subcategory_id)
        row['brand'] = getItemNameById(brand_table, item.brand_id)
        row['model'] = getItemNameById(model_table, item.model_id)
        row['variant'] = getItemNameById(variant_table, item.variant_id)
        row['color'] = getItemNameById(color_table, item.color_id)
        row['imei'] = item.imei_no
        row['source'] = item.source
        row['mrp'] = format_amount(item.mrp)
        row['mop'] = format_amount(item.mop)
        row['amount'] = format_amount(item.amount)
        
        data.append(row)
        counter += 1

    return JsonResponse({'data': data})




def wholesale_sales_order(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        branch_id = request.session.get('branch_id')
        customer_id = request.session.get('customer_id') or request.session.get('user_id')
        if user_type == 'wholesale_customer':
            branch = selectList(branch_table, order_by='name').exclude(id=branch_id)
            
            encoded_id = request.GET.get('id') or 0
            if encoded_id != 0:
                decoded_id = decode_base64_id(encoded_id) or 0
            else:
                decoded_id = 0

            return render(request, 'external_wholesale/sales/details.html',{'branch':branch,'decoded_id':decoded_id})
        else:
            customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
            next_url = request.get_full_path()
            params = {}
            if customer_uuid:
                params['uuid'] = customer_uuid
            if next_url:
                params['next'] = next_url
            login_url = '/wholesale/login/'
            if params:
                login_url = f"{login_url}?{urlencode(params)}"
            return HttpResponseRedirect(login_url)
    else:
        customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
        next_url = request.get_full_path()
        params = {}
        if customer_uuid:
            params['uuid'] = customer_uuid
        if next_url:
            params['next'] = next_url
        login_url = '/wholesale/login/'
        if params:
            login_url = f"{login_url}?{urlencode(params)}"
        return HttpResponseRedirect(login_url)
    

def ajax_wholesales_sales_view(request):  
    if request.session.get('user_type') != 'wholesale_customer':
        return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})

    customer_id     = request.session.get('customer_id') or request.session.get('user_id')
    fyf_name        = request.session.get('fyf')
    financial_year  = calculate_financial_year(fyf_name)
    from_date       = request.POST.get('from_date')
    to_date         = request.POST.get('to_date')
    sales_id        = request.POST.get('sales_id')

    filter_sales_status = request.POST.get('filter_sales_status')   



    query = Q(status=1, customer_id=customer_id, current_fy=financial_year)

    if sales_id:
        query &= Q(id=sales_id)
        
    if from_date and to_date:
        query &= Q(inv_date__range=[from_date, to_date])
    
    if customer_id:
        query &= Q(customer_id=customer_id)
    
    if filter_sales_status:
        query &= Q(sales_status=filter_sales_status)

   
    data = list(selectList(wholesale_sales_order_table, query).values())
   
    formatted = []
    for index, item in enumerate(data):
        sales_id = item['id']
        
        # Payment details are now stored directly in the master table
        cash_val    = item.get('cash') or 0.00
        bank_val    = item.get('bank') or 0.00
        finance_val = item.get('finance_amount') or 0.00

        # Action Buttons Logic
        if item.get('sales_status') == 'rejected':
            action_html = (
                '<div class="d-flex gap-1 justify-content-center align-items-center">'
                '<button type="button" onclick="showRejectionDetails(\'{}\')" class="btn btn-outline-warning btn-xs p-1" title="Rejection Info"><i class="fas fa-info-circle"></i></button>'
                '<button type="button" onclick="view_data(\'{}\')" class="btn btn-outline-primary btn-xs p-1" title="View Details"><i class="fas fa-eye"></i></button>'
                '</div>'
            ).format(item['id'], item['id'])

        else:
            action_html = (
                '<div class="d-flex gap-1 justify-content-center align-items-center">'
                '<button type="button" onclick="edit_data(\'{}\')" class="btn btn-outline-success btn-xs p-1"><i class="fas fa-edit"></i></button>'
                '<button type="button" onclick="delete_data(\'{}\')" class="btn btn-outline-danger btn-xs p-1"><i class="fas fa-trash-alt"></i></button>'
                # '<button type="button" onclick="print_data(\'{}\')" class="btn btn-outline-info btn-xs p-1" title="Print"><i class="fas fa-print"></i></button>'
                # '<button type="button" onclick="thermal_print_data(\'{}\')" class="btn btn-outline-primary btn-xs p-1" title="Thermal Print"><i class="fas fa-file-invoice"></i></button>'
                '</div>'
            ).format(item['id'], item['id'], item['id'], item['id'])

        formatted.append({
            'id': index + 1,
            'action': action_html,
            'date'      : format_date_month_year(item['inv_date']) if item['inv_date'] else '-', 
            'inv_no'     : item['inv_no'] if item['inv_no'] else '-', 
            'quantity'  : item['total_quantity'] if item['total_quantity'] else '0', 
            'amount'    : format_amount(item['total_amount']), 
            'claim'     : '', 
            'cash'      : format_amount(cash_val), 
            'bank'      : format_amount(bank_val), 
            'finance'    : format_amount(finance_val), 
            'balance'   : format_amount(item['balance']), 
            'remarks'   : item['remarks'] if item['remarks'] else '-',    
            'status': format_badge(
                item['sales_status'],
                mapping={
                    'pending': 'badge text-bg-info',
                    'approved': 'badge text-bg-success',
                    'rejected': 'badge text-bg-danger'
                },
                label_mapping={
                    'pending': 'Pending',
                    'approved': 'Approved',
                    'rejected': 'Rejected'
                }
            ),
            'rejected_by' : getItemNameById(employee_table, item['rejected_by']) if item.get('rejected_by') else '-',
            'rejected_on' : format_datetime(item['rejected_on']) if item.get('rejected_on') else '-',
            'rejected_remarks' : item.get('rejected_remarks') or '-',
        })

    return JsonResponse({'data': formatted})




def wholesales_sales_order_add(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        branch_id = request.session.get('branch_id')
        user_id = request.session.get('user_id')
        if user_type == 'wholesale_customer':
            customer = selectList(customer_table, {'id':user_id} ,order_by='name')
            branch = selectList(branch_table, order_by='name').exclude(id=branch_id)
            item = selectList(item_table)
            brand= selectList(brand_table, order_by='name')
            employee = employee_list(request)
            subcategory = selectList(sub_category_table, order_by='name')
            is_ho = request.session.get('is_ho')
            if is_ho == 1:
                bank = selectList(bank_table, {'is_default':0}, order_by='name')
            else:
                bank = selectList(bank_table, {'is_default':1}, order_by='name')
            finance = selectList(finance_table,{'f_type': 'finance'}, order_by='name')
            card = selectList(finance_table,{'f_type': 'card'}, order_by='name')
            
            return render(request, 'external_wholesale/sales/add.html',{'customer':customer,'branch':branch,'item':item,'brand':brand,'employee':employee,'subcategory':subcategory,'bank':bank,'finance':finance,'card':card})
        else:
            customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
            next_url = request.get_full_path()
            params = {}
            if customer_uuid:
                params['uuid'] = customer_uuid
            if next_url:
                params['next'] = next_url
            login_url = '/wholesale/login/'
            if params:
                login_url = f"{login_url}?{urlencode(params)}"
            return HttpResponseRedirect(login_url)
    else:
        customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
        next_url = request.get_full_path()
        params = {}
        if customer_uuid:
            params['uuid'] = customer_uuid
        if next_url:
            params['next'] = next_url
        login_url = '/wholesale/login/'
        if params:
            login_url = f"{login_url}?{urlencode(params)}"
        return HttpResponseRedirect(login_url)
    


def get_wholesale_customer_available_stock(customer_id, filters=None, exclude_tm_sales_id=None):
    """
    Calculate available stock for a wholesale customer.
    
    Logic:
    1. Get all IMEIs purchased by the wholesale customer (from sales_order_table)
    2. Exclude IMEIs already sold by the wholesale customer (from wholesale_child_sales_order_table)
       - If exclude_tm_sales_id is provided, don't count IMEIs from that specific TM Sales record as "sold"
    3. Apply optional filters (subcategory, brand, model, variant, color)
    """
    if filters is None:
        filters = {}
    
    # 1. Get TM Sales IDs (Inward for Wholesaler)
    tm_sales_ids = sales_order_table.objects.filter(
        customer_id=customer_id,
        customer_type__iexact='wholesale',
        status=1
    ).values_list('id', flat=True)
    
    # 2. Build query filters
    query_filters = Q(tm_sales_id__in=tm_sales_ids, status=1)
    
    # Apply optional filters
    if filters.get('subcategory_id'):
        query_filters &= Q(subcategory_id=filters['subcategory_id'])
    if filters.get('brand_id'):
        query_filters &= Q(brand_id=filters['brand_id'])
    if filters.get('model_id'):
        query_filters &= Q(model_id=filters['model_id'])
    if filters.get('variant_id'):
        query_filters &= Q(variant_id=filters['variant_id'])
    if filters.get('color_id'):
        query_filters &= Q(color_id=filters['color_id'])
    
    # 3. Get purchased items
    purchased_items = child_sales_order_table.objects.filter(query_filters)
    
    # 4. Get sold IMEIs (already sold by wholesaler)
    purchased_imeis = purchased_items.exclude(
        imei_no__isnull=True
    ).exclude(
        imei_no=''
    ).values_list('imei_no', flat=True)
    
    sold_query = Q(status=1, imei_no__in=purchased_imeis)
    if exclude_tm_sales_id:
        sold_query &= ~Q(tm_sales_id=exclude_tm_sales_id)
        
    sold_imeis = set(wholesale_child_sales_order_table.objects.filter(
        sold_query
    ).values_list('imei_no', flat=True))

    # 5. Get returned IMEIs (returned by wholesaler back to store)
    # Import here to avoid circular dependency if any
    from sales.models import child_sales_return_table
    returned_imeis = set(child_sales_return_table.objects.filter(
        customer_id=customer_id,
        imei_no__in=purchased_imeis,
        status=1
    ).values_list('imei_no', flat=True))
    
    # 6. Return only available items (not yet sold and not returned)
    available_items = purchased_items.exclude(
        Q(imei_no__in=sold_imeis) | Q(imei_no__in=returned_imeis)
    )   
    
    return available_items




def ajax_get_wholesale_customer_stock(request):
    """
    Fetch available stock for the selected wholesale customer.
    Returns IMEI list with product details for display in the stock card.
    """
    user_type = request.session.get('user_type')
    if user_type != 'wholesale_customer':
        return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})
    
    customer_id = request.session.get('customer_id') or request.session.get('user_id')
    edit_id     = request.POST.get('edit_id') or None
    
    # Get available stock using common utility
    available_items = get_wholesale_customer_available_stock(customer_id, exclude_tm_sales_id=edit_id)
    
    # Format response
    stock_list = []
    for item in available_items:
        sku = select_row(item_table, {
            'sub_category_id': item.subcategory_id, 
            'brand_id': item.brand_id, 
            'model_id': item.model_id, 
            'variant_id': item.variant_id, 
            'color_id': item.color_id
        })
        stock_list.append({
            'imei': item.imei_no,
            'subcategory': getItemNameById(sub_category_table, item.subcategory_id),
            'brand': getItemNameById(brand_table, item.brand_id),
            'model': getItemNameById(model_table, item.model_id),
            'variant': getItemNameById(variant_table, item.variant_id),
            'color': getItemNameById(color_table, item.color_id),
            'rate': float(item.rate) if item.rate else 0,
            'source': item.source or '',
            'sku_text': sku.sku_text if sku else '-',
            'sale_id': item.id
        })
    
    return JsonResponse({'status': 'success', 'stock': stock_list})


def add_wholesales_order(request):
    if request.method != 'POST':
        return JsonResponse({'message': 'Invalid request'}, status=400)

    try:
        if request.session.get('user_type') != 'wholesale_customer':
            return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})

        company_id      = request.session.get('company_id')
        branch_id       = request.session.get('customer_id')
        user_id         = request.session.get('user_id')
        role_id         = request.session.get('role_id')
        fyf_name        = request.session.get('fyf')
        financial_year  = calculate_financial_year(fyf_name)
        session_customer_id = request.session.get('customer_id')
        
        po_date         = request.POST.get('sales_date')
        customer_name   = request.POST.get('customer_name')
        customer_type   = request.POST.get('customer_type') or 'wholesale'
        customer_id     = int(request.POST.get('customer_id') or session_customer_id)
        phone           = request.POST.get('customer_phone') or None
        remarks         = request.POST.get('description')
        total_qty       = float(request.POST.get('total_quantity') or 0)
        sub_total       = float(request.POST.get('sub_total') or 0)
        total_amount    = float(request.POST.get('total_payable') or 0)
        total_paid      = float(request.POST.get('total_paid') or 0)
        balance         = float(request.POST.get('balance') or 0)
        charges_order   = float(request.POST.get('charges') or 0) # Overall order charges
        total_discount  = float(request.POST.get('total_discount') or 0)
        total_tax_cgst  = float(request.POST.get('total_tax_cgst') or 0)
        total_tax_sgst  = float(request.POST.get('total_tax_sgst') or 0)
        employee_id     = request.POST.get('employee_id') or user_id
        now             = timezone.localtime(timezone.now())

        # Items
        items       = json.loads(request.POST.get('items') or '[]')
        if not items:
            return JsonResponse({'message': 'warning', 'error_message': 'No items added'})

        # Payments
        payments    = json.loads(request.POST.get('payments') or '[]')

        # Custom Serial Number Generation (Avoid branch_id filter as it doesn't exist in this table)
        prefix = ""
        latest_inv = wholesale_sales_order_table.objects.filter(
            current_fy=financial_year, 
            status=1,
            inv_no__startswith=prefix
        ).aggregate(max_inv=Max('inv_no'))['max_inv']

        if latest_inv:
            try:
                numeric_part = latest_inv.replace(prefix, "")
                last_series = int(numeric_part)
                new_series = last_series + 1
            except ValueError:
                new_series = 1
        else:
            new_series = 1
        
        inv_no = f"{prefix}{new_series:04}"

        # Aggregate payments to save in the child table directly
        payment_cash = 0
        payment_bank = 0
        payment_finance = 0
        payment_finance_id = 0
        payment_charges = 0

        for pay in payments:
            amt = float(pay.get('amount') or 0)
            chg = float(pay.get('charges') or 0)
            if pay['type'] == 'cash':
                payment_cash += amt
            elif pay['type'] == 'bank':
                payment_bank += amt
            elif pay['type'] == 'finance':
                payment_finance += amt
                payment_finance_id = pay.get('id') or 0
            
            payment_charges += chg
        customer = select_row(customer_table, {'id':customer_id})
        print(customer.phone)
        with db_transaction.atomic():            
            main = wholesale_sales_order_table.objects.create(
                company_id      =company_id,
                current_fy      =financial_year,
                inv_no          =inv_no,
                num_series      =generate_num_series(wholesale_sales_order_table),
                inv_date        =po_date,
                time            = now.time(),
                customer_id     =0,
                customer_name   =customer_name,
                customer_phone  =phone,
                customer_type   ='wholesale',
                total_quantity  =total_qty,
                total_amount    =total_amount,
                sub_total       =sub_total,
                total_paid      =total_paid,
                total_discount  = total_discount,
                balance         =balance,
                remarks         =remarks,
                employee_id     =employee_id,
                wholesale_type='external',
                branch_id       =0,
                
                
                # Payment details moved to master table
                cash            =payment_cash,
                bank            =payment_bank,
                finance_id      =payment_finance_id,
                finance_amount  =payment_finance,
                charges         =payment_charges,
                collect_status  ='pending',

                created_on      =now,
                updated_on      =now,
                created_by      =user_id,
                updated_by      =user_id,
                status          =1,
                is_active       =1,
                total_cgst      =total_tax_cgst,
                total_sgst      =total_tax_sgst,
                sales_status    ='approved', 
            )

            # Wholesale Sales Items
            for i, item in enumerate(items):
                wholesale_child_sales_order_table.objects.create(
                    company_id      =company_id,
                    current_fy      =financial_year,
                    tm_sales_id     =main.id,
                    customer_id     =customer_id,
                    sales_id        =item.get('sales_id', 0),
                    imei_no         =item['imei'],
                    ean_number      =item['ean'],
                    subcategory_id  =item['subcategory_id'],
                    brand_id        =item['brand_id'],
                    model_id        =item['model_id'],
                    variant_id      =item['variant_id'],
                    color_id        =item['color_id'],
                    quantity        =1,
                    rate            =item['rate'],
                    amount          =item['net_rate'],
                    tax_percent     =item['tax_percent'],
                    tax_amount      =item['tax_amount'],
                    tax_cgst        =item['tax_cgst'],
                    tax_sgst        =item['tax_sgst'],
                    discount_percent=item['discount_percent'],
                    discount_amount=item['discount_amount'],
                    mop             = item['mop_price'],
                    bop             = item['bop_price'],
                    wsp             = item['wsp_price'],
                    fsp             = item['fsp_price'],
                    db_price        = item['db_price'],
                    mrp             = item.get('mrp') or item['rate'],
                    upgrade_id      =item['upgrade_id'],
                    upgrade_amount  =item['upgrade_amount'],
                    special_id      =item['special_id'],
                    special_amount  =item['special_amount'],
                    purchase_price  =item['purchase_price'],
                    
                    created_on      =now,
                    updated_on      =now,
                    created_by      =user_id,
                    updated_by      =user_id,
                    status          =1,
                    is_active       =1
                )

        return JsonResponse({'message': 'success'})

    except IntegrityError as e:
        return JsonResponse({'message': 'exception', 'error': str(e)}, status=200)
    except Exception as e:
        return JsonResponse({'message': 'exception', 'error': f'Unexpected error: {e}'}, status=500)

  



def wholesales_sales_order_edit(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        branch_id = request.session.get('branch_id')
        user_id = request.session.get('user_id')
        
        if user_type == 'wholesale_customer':
            encoded_id = request.GET.get('id', None)
            decoded_id = decode_base64_id(encoded_id)
            if decoded_id:
                sales = select_row(wholesale_sales_order_table, {'id': decoded_id})



            customer = selectList(customer_table, {'id':user_id} ,order_by='name')
            branch = selectList(branch_table, order_by='name').exclude(id=branch_id)
            item = selectList(item_table)
            brand= selectList(brand_table, order_by='name')
            employee = employee_list(request)
            subcategory = selectList(sub_category_table, order_by='name')
            is_ho = request.session.get('is_ho')
            if is_ho == 1:
                bank = selectList(bank_table, {'is_default':0}, order_by='name')
            else:
                bank = selectList(bank_table, {'is_default':1}, order_by='name')
            finance = selectList(finance_table,{'f_type': 'finance'}, order_by='name')
            card = selectList(finance_table,{'f_type': 'card'}, order_by='name')
            
            return render(request, 'external_wholesale/sales/edit.html',{'customer':customer,'branch':branch,'item':item,'brand':brand,'employee':employee,'subcategory':subcategory,'bank':bank,'finance':finance,'card':card,'sales':sales,'decoded_id':decoded_id})
        else:
            customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
            next_url = request.get_full_path()
            params = {}
            if customer_uuid:
                params['uuid'] = customer_uuid
            if next_url:
                params['next'] = next_url
            login_url = '/wholesale/login/'
            if params:
                login_url = f"{login_url}?{urlencode(params)}"
            return HttpResponseRedirect(login_url)
    else:
        customer_uuid = request.GET.get('uuid') or request.session.get('customer_uuid') or ''
        next_url = request.get_full_path()
        params = {}
        if customer_uuid:
            params['uuid'] = customer_uuid
        if next_url:
            params['next'] = next_url
        login_url = '/wholesale/login/'
        if params:
            login_url = f"{login_url}?{urlencode(params)}"
        return HttpResponseRedirect(login_url)
    


def ajax_get_wholesales_sales_items(request):
    try:
        if request.session.get('user_type') != 'wholesale_customer':
            return JsonResponse({'status': 'error', 'message': 'Unauthorized'})

        tm_id = request.GET.get('tm_sales_id')
        if not tm_id:
            return JsonResponse({'status': 'error', 'message': 'Missing ID'})

        customer_id = request.session.get('customer_id') or request.session.get('user_id')
        items = wholesale_child_sales_order_table.objects.filter(tm_sales_id=tm_id, status=1, customer_id=customer_id)
        data = []
        for item in items:
            # Fetch names using helper
            subcategory_name = getItemNameById(sub_category_table, item.subcategory_id)
            brand_name       = getItemNameById(brand_table, item.brand_id)
            model_name       = getItemNameById(model_table, item.model_id)
            variant_name     = getItemNameById(variant_table, item.variant_id)
            color_name       = getItemNameById(color_table, item.color_id)

            data.append({
                'item_id': item.id,
                'ean': item.ean_number,
                'subcategory_id': item.subcategory_id,
                'subcategory_name': subcategory_name,
                'brand_id': item.brand_id,
                'brand_name': brand_name,
                'model_id': item.model_id,
                'model_name': model_name,
                'variant_id': item.variant_id,
                'variant_name': variant_name,
                'color_id': item.color_id,
                'color_name': color_name,
                'imei': item.imei_no,
                'rate': float(item.rate),
                'tax_percent': float(item.tax_percent),
                'tax_amount': float(item.tax_amount),
                'tax_cgst': float(item.tax_cgst),
                'tax_sgst': float(item.tax_sgst),
                'discount_percent': float(item.discount_percent),
                'discount_amount': float(item.discount_amount),
                'net_rate': float(item.amount),
                'upgrade_id': item.upgrade_id,
                'upgrade_amount': float(item.upgrade_amount),
                'special_id': item.special_id,
                'special_amount': float(item.special_amount),
                'mop_price': float(item.mop),
                'bop_price': float(item.bop),
                'wsp_price': float(item.wsp),
                'fsp_price': float(item.fsp),
                'db_price': float(item.db_price),
                'purchase_price': float(item.purchase_price),
                'sales_id': item.sales_id
            })
        return JsonResponse({'status': 'success', 'data': data})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': str(e)})


def update_wholesales_order(request):
    if request.method != 'POST':
        return JsonResponse({'message': 'Invalid request'}, status=400)

    try:
        if request.session.get('user_type') != 'wholesale_customer':
            return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})

        sales_id = request.POST.get('id')
        if not sales_id:
            return JsonResponse({'message': 'warning', 'error_message': 'Sales ID missing'})

        company_id      = request.session.get('company_id')
        user_id         = request.session.get('user_id')
        fyf_name        = request.session.get('fyf')
        financial_year  = calculate_financial_year(fyf_name)
        
        po_date         = request.POST.get('sales_date')
        customer_id     = int(request.POST.get('customer_id') or 0)
        remarks         = request.POST.get('description')
        total_qty       = float(request.POST.get('total_quantity') or 0)
        sub_total       = float(request.POST.get('sub_total') or 0)
        total_amount    = float(request.POST.get('total_payable') or 0)
        total_paid      = float(request.POST.get('total_paid') or 0)
        balance         = float(request.POST.get('balance') or 0)
        total_discount  = float(request.POST.get('total_discount') or 0)
        total_tax_cgst  = float(request.POST.get('total_tax_cgst') or 0)
        total_tax_sgst  = float(request.POST.get('total_tax_sgst') or 0)
        now             = timezone.localtime(timezone.now())

        items       = json.loads(request.POST.get('items') or '[]')
        payments    = json.loads(request.POST.get('payments') or '[]')

        if not items:
            return JsonResponse({'message': 'warning', 'error_message': 'No items added'})

        payment_cash = 0
        payment_bank = 0
        payment_finance = 0
        payment_finance_id = 0
        payment_charges = 0

        for pay in payments:
            amt = float(pay.get('amount') or 0)
            chg = float(pay.get('charges') or 0)
            if pay['type'] == 'cash':
                payment_cash += amt
            elif pay['type'] == 'bank':
                payment_bank += amt
            elif pay['type'] == 'finance':
                payment_finance += amt
                payment_finance_id = pay.get('id') or 0
            
            payment_charges += chg

        with db_transaction.atomic():
            main = wholesale_sales_order_table.objects.get(id=sales_id)
            
           
            
            main.inv_date        = po_date
            main.customer_id     = customer_id
            # main.customer_name   = cust.name
            # main.customer_phone  = cust.phone
            # main.customer_type   = cust.customer_type
            main.total_quantity  = total_qty
            main.total_amount    = total_amount
            main.sub_total       = sub_total
            main.total_paid      = total_paid
            main.total_discount  = total_discount
            main.balance         = balance
            main.remarks         = remarks
            main.cash            = payment_cash
            main.bank            = payment_bank
            main.finance_id      = payment_finance_id
            main.finance_amount  = payment_finance
            main.charges         = payment_charges
            main.total_cgst      = total_tax_cgst
            main.total_sgst      = total_tax_sgst
            main.updated_on      = now
            main.updated_by      = user_id
            main.save()

            # Remove old items and add new ones
            wholesale_child_sales_order_table.objects.filter(tm_sales_id=sales_id).update(status=0, is_active=0)

            for item in items:
                # To handle claim/upgrade status, we fetch them from the old record if item_id exists
                old_item_id = item.get('item_id')
                extra_fields = {}
                if old_item_id:
                    old_item = wholesale_child_sales_order_table.objects.filter(id=old_item_id).first()
                    if old_item:
                        extra_fields = {
                            'is_upgrade_approved': old_item.is_upgrade_approved,
                            'upgrade_approved_on': old_item.upgrade_approved_on,
                            'upgrade_approved_by': old_item.upgrade_approved_by,
                            'upgrade_collect': old_item.upgrade_collect,
                            'upgrade_status': old_item.upgrade_status,
                            'upgrade_rejected_on': old_item.upgrade_rejected_on,
                            'upgrade_rejected_by': old_item.upgrade_rejected_by,
                            'upgrade_rejected_remarks': old_item.upgrade_rejected_remarks,
                            'is_claim': old_item.is_claim,
                            'claim_amount': old_item.claim_amount,
                            'claimed_on': old_item.claimed_on,
                        }

                wholesale_child_sales_order_table.objects.create(
                    company_id      =company_id,
                    current_fy      =financial_year,
                    tm_sales_id     =main.id,
                    customer_id     =customer_id,
                    sales_id        =item.get('sales_id', 0),
                    imei_no         =item['imei'],
                    ean_number      =item['ean'],
                    subcategory_id  =item['subcategory_id'],
                    brand_id        =item['brand_id'],
                    model_id        =item['model_id'],
                    variant_id      =item['variant_id'],
                    color_id        =item['color_id'],
                    quantity        =1,
                    rate            =item['rate'],
                    amount          =item['net_rate'],
                    tax_percent     =item['tax_percent'],
                    tax_amount      =item['tax_amount'],
                    tax_cgst        =item['tax_cgst'],
                    tax_sgst        =item['tax_sgst'],
                    discount_percent=item['discount_percent'],
                    discount_amount=item['discount_amount'],
                    mop             = item['mop_price'],
                    bop             = item['bop_price'],
                    wsp             = item['wsp_price'],
                    fsp             = item['fsp_price'],
                    db_price        = item['db_price'],
                    mrp             = item.get('mrp') or item['rate'],
                    upgrade_id      =item['upgrade_id'],
                    upgrade_amount  =item['upgrade_amount'],
                    special_id      =item['special_id'],
                    special_amount  =item['special_amount'],
                    purchase_price  =item['purchase_price'],
                    created_on      =now,
                    updated_on      =now,
                    created_by      =user_id,
                    updated_by      =user_id,
                    status          =1,
                    is_active       =1,
                    **extra_fields
                )

        return JsonResponse({'message': 'success'})

    except Exception as e:
        return JsonResponse({'message': 'exception', 'error': str(e)}, status=500)


def delete_wholesales_order(request):
    if request.method != 'POST':
        return JsonResponse({'message': 'Invalid request method'})

    if request.session.get('user_type') != 'wholesale_customer':
        return JsonResponse({'message': 'permission', 'error_message': 'Unauthorized'})

    data_id = request.POST.get('id')
    customer_id = request.session.get('customer_id') or request.session.get('user_id')

    try:
        main_qs = wholesale_sales_order_table.objects.filter(
            id=data_id,
            customer_id=customer_id,
            status=1
        )
        if not main_qs.exists():
            return JsonResponse({'message': 'no such data'})

        main_qs.update(status=0, is_active=0)
        wholesale_child_sales_order_table.objects.filter(
            tm_sales_id=data_id,
            customer_id=customer_id,
            status=1
        ).update(status=0, is_active=0)
        return JsonResponse({'message': 'yes'})
    except Exception as e:
        return JsonResponse({'message': 'exception', 'error': str(e)})
    
