from django.shortcuts import render
import json
from django.conf import settings
from django.shortcuts import render
from sales.models import *
from expenses.models import *
from store.models import *
from masters.models import *
from stock.models import *
from scheme.models import *
from sales.forms import *
from django.db import IntegrityError, transaction

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,Sum
import base64
from django.shortcuts import render
from io import BytesIO
from django.conf import settings
from django.template.loader import get_template
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
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 common.utils import *
from supplier.models import *
from django.db.models import Sum
from django.db.models.functions import Coalesce
from django.db.models import Sum, F, DecimalField, Value
from claim_collect_upgrade.claim import update_master_scheme_status

# ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````

def upgrade_sales(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        branch_id = request.session.get('branch_id')
        is_ho = request.session.get('is_ho')
        if user_type == 'stores':
            branch = selectList(branch_table, order_by='name').exclude(id=branch_id)        
            if is_ho == 1:
                supplier = selectList(supplier_table, order_by='name' )
            else:
                supplier = selectList(supplier_table, Q(is_global=1) , order_by='name' )
            brand = selectList(brand_table, order_by='name')
            model = selectList(model_table, order_by='name')
            variant = selectList(variant_table, order_by='name')
            return render(request, 'upgrade/upgrade_sales.html',{'supplier':supplier,'branch':branch,'brand':brand,'model':model,'variant':variant})
            
        
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")

from django.http import JsonResponse
from django.db.models import F
from datetime import datetime
from django.http import JsonResponse

def ajax_upgrade_sales_view(request):  
    role_id = request.session.get('role_id')

    from_date = request.POST.get('from_date')
    to_date = request.POST.get('to_date')
    brand_id = request.POST.get('brand_id')
    model_id = request.POST.get('model_id')
    variant_id = request.POST.get('variant_id')
    approve_status = request.POST.get('approve_status')

    has_access, error_message = check_user_access(
        role_id, 'upgrade_sales', "read"
    )

    if not has_access:
        return JsonResponse({
            'message': 'permission',
            'error_message': 'You do not have permission to view this data'
        })

    # --------------------------------------------------
    # STEP 1: Filter tm_sales (DATE FILTER)
    # --------------------------------------------------
    tm_sales_qs = sales_order_table.objects.filter(
        status=1,
        is_active=1
    )

    if from_date and to_date:
        tm_sales_qs = tm_sales_qs.filter(
            inv_date__range=[
                datetime.strptime(from_date, '%Y-%m-%d'),
                datetime.strptime(to_date, '%Y-%m-%d')
            ]
        )

    tm_sales_ids = tm_sales_qs.values_list('id', flat=True)

    # --------------------------------------------------
    # STEP 2: Filter tx_sales (UPGRADE + ITEM FILTERS)
    # --------------------------------------------------
    upgrades = child_sales_order_table.objects.filter(
        tm_sales_id__in=tm_sales_ids,
        upgrade_id__gt=0,
        upgrade_amount__gt=0,
        status=1
    )

    if brand_id:
        upgrades = upgrades.filter(brand_id=brand_id)

    if model_id:
        upgrades = upgrades.filter(model_id=model_id)

    if variant_id:
        upgrades = upgrades.filter(variant_id=variant_id)

    if approve_status != '' and approve_status is not None:
        upgrades = upgrades.filter(is_upgrade_approved=approve_status)

    # --------------------------------------------------
    # STEP 3: FORMAT RESPONSE
    # --------------------------------------------------
    # ... (rest of your filtering logic) ...

    formatted = []
    for index, item in enumerate(upgrades, start=1):
        parent = tm_sales_qs.filter(id=item.tm_sales_id).first()                
        upgrade = float(item.upgrade_amount or 0)
        collect = float(item.upgrade_collect or 0)
        balance = upgrade - collect

        action_btn = ''
        if item.upgrade_status in ['pending', 'partial']:
            action_btn = (
                f'<div class="d-flex flex-column align-items-center gap-1">'
                f'<button type="button" onclick="approve_data(\'{item.id}\')" '
                f'class="btn btn-success btn-sm w-100"><i class="fa fa-check"></i>&nbsp;Approve</button>'
                f'<button type="button" onclick="reject_data(\'{item.id}\')" '
                f'class="btn btn-danger btn-sm w-100"><i class="fa fa-times"></i>&nbsp;Reject</button>'                
                f'</div>'
            )
        else:
            action_btn = (
                f'<button type="button" '
                f'onclick="revert_data(\'{item.id}\')" '
                f'class="btn btn-warning btn-sm"><i class="fa fa-undo"></i>&nbsp;Revert</button>'
            )

        formatted.append({
            'id'            : index,
            'action'        : action_btn,
            'inv_no'        : parent.inv_no if parent else '-',
            'date'          : format_date_month_year(parent.inv_date) if parent and parent.inv_date else '-',
            'branch'        : getItemNameById(branch_table, item.branch_id),
            'customer'      : parent.customer_name if parent else '-',
            'phone'         : parent.customer_phone if parent else '-',
            'customer_type' : parent.customer_type.title() if parent and parent.customer_type else '-',
            'imei'          : item.imei_no if item.imei_no else '-',
            '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),
            'upgrade'       : format_amount(upgrade),
            'upgrade_amount': format_amount(item.upgrade_collect or 0),
            'debit'         : format_amount(collect),
            'balance'       : format_amount(balance),
            'amount'        : format_amount(parent.total_amount or 0),
            'paid'          : format_amount(parent.total_paid or 0),
            'status'        : format_badge(item.upgrade_status, mapping={
                'pending'   : 'badge text-bg-info',
                'partial'   : 'badge text-bg-warning',
                'approved' : 'badge text-bg-success',
                'rejected'  : 'badge text-bg-danger'
            }, label_mapping={
                'pending': 'Pending',
                'partial': 'Partial',
                'approved': 'Approved',
                'rejected': 'Rejected',
            })
        })

    return JsonResponse({'data': formatted})

from decimal import Decimal
from django.shortcuts import get_object_or_404

def load_upgrade_sales(request):
    edit_id = request.POST.get('id') 
    
    item = get_object_or_404(child_sales_order_table, id=edit_id, status=1)    
    amount = float(item.upgrade_amount or 0) - float(item.upgrade_collect or 0)
    
    data = {
        'id': item.id,
        'sales_id': item.tm_sales_id,
        'imei': item.imei_no or '-',
        'upgrade_amount': format_amount(amount),
        '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,
        'imei_no': item.imei_no,
        'branch_id': item.branch_id,
    }
            
    return JsonResponse(data)

from claim_collect_upgrade.forms import *
from django.db.models import F
from django.utils import timezone
from django.http import JsonResponse

def add_upgrade_sales_old(request):
    if request.method == 'POST':
        try:
            user_id = request.session.get('user_id')           
            company_id = request.session.get('company_id')           
            branch_id = request.session.get('branch_id')    
            fyf_name = request.session.get('fyf')
            financial_year = calculate_financial_year(fyf_name)       
            role_id = request.session.get('role_id')
            date_times = timezone.localtime(timezone.now())
            
            # Form Processing
            form = UpgradeForm(request.POST, request.FILES)
            if form.is_valid():
                category = form.save(commit=False)
                
                # Fetching IDs and Amounts
                tx_sales_id = request.POST.get('edit_id')
                sales_id = request.POST.get('sales_id')
                debit_amount = float(request.POST.get('debit_amount') or 0)
                
                # 1. Generate Serial Number
                inv_no = generate_serial_number(
                    model=tm_upgrade_table,
                    number_field='upgrade_no',
                    financial_year_field='current_fy',
                    financial_year=financial_year,
                    branch_id=branch_id,
                    prefix=""
                )
                
                # 2. Assign values to the Upgrade Master record (tm_upgrade_table)
                category.company_id = company_id
                category.branch_id = branch_id
                category.current_fy = financial_year
                category.upgrade_no = inv_no
                category.imei_no = request.POST.get('imei_no')
                category.supply_branch_id = request.POST.get('branch_id')
                category.date = date_times.date()
                category.time = date_times.time()
                category.sales_id = sales_id
                category.tx_sales_id = tx_sales_id
                category.subcategory_id = request.POST.get('subcategory_id')
                category.brand_id = request.POST.get('brand_id')
                category.model_id = request.POST.get('model_id')
                category.variant_id = request.POST.get('variant_id')
                category.color_id = request.POST.get('color_id')
                category.debit_note_no = request.POST.get('debit_note_no')
                category.debit_note_date = request.POST.get('debit_note_date')
                category.total_amount = float(request.POST.get('upgrade_amount') or 0)
                category.debit_amount = debit_amount
                category.balance = category.total_amount - debit_amount
                category.remarks = request.POST.get('remarks')
                category.status = 1
                category.created_by = user_id
                category.employee_id = user_id
                category.updated_by = user_id
                category.created_on = date_times
                category.updated_on = date_times
                category.save()
                
                child_sales_qs = child_sales_order_table.objects.filter(
                    id=tx_sales_id, 
                    tm_sales_id=sales_id, 
                    status=1
                )
                
                child_sales_qs.update(
                    upgrade_collect = F('upgrade_collect') + debit_amount,
                    updated_on = date_times,
                    updated_by = user_id
                )
                
                # 4. Final Check: If balance is cleared, mark as approved
                # Fetch fresh data after F() update to check totals
                updated_item = child_sales_qs.first()
                if updated_item:
                    total_up = float(updated_item.upgrade_amount or 0)
                    total_coll = float(updated_item.upgrade_collect or 0)
                    
                    if total_coll >= total_up:
                        child_sales_qs.update(
                            is_upgrade_approved=1,
                            upgrade_approved_on=date_times,
                            upgrade_approved_by=user_id
                        )   

                return JsonResponse({'message': 'success'})
            else:
                return JsonResponse({'message': 'form_error', 'errors': form.errors.as_json()}, status=400)

        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)}, status=500)
        

from django.db.models import Sum, Q

def update_scheme_status(scheme_id):
    """
    Updates the claim_status of a scheme based on the upgrade collection 
    progress of all related sales within the scheme's date range.
    """
    # 1. Get the Scheme Details
    scheme = item_scheme_table.objects.filter(id=scheme_id, status=1).first()
    if not scheme:
        return

    # 2. Get all Sale IDs from TM_Sales within the Scheme's Date Range
    tm_sales_ids = sales_order_table.objects.filter(
        inv_date__range=[scheme.from_date, scheme.to_date],
        branch_id=scheme.branch_id,
        status=1,
        is_active=1
    ).values_list('id', flat=True)

    # 3. Filter TX_Sales (Child Table) for these sales and matching item attributes
    related_upgrades = child_sales_order_table.objects.filter(
        tm_sales_id__in=tm_sales_ids,
        subcategory_id=scheme.subcategory_id,
        brand_id=scheme.brand_id,
        model_id=scheme.model_id,
        upgrade_amount__gt=0,
        status=1
    )

    if not related_upgrades.exists():
        scheme.claim_status = 'pending'
        scheme.save()
        return

    # 4. Calculate Totals to determine status
    totals = related_upgrades.aggregate(
        total_up_amt=Sum('upgrade_amount'),
        total_coll_amt=Sum('upgrade_collect')
    )

    total_upgrade = float(totals['total_up_amt'] or 0)
    total_collected = float(totals['total_coll_amt'] or 0)

    # 5. Determine Status Logic
    if total_collected <= 0:
        new_status = 'pending'
    elif total_collected < total_upgrade:
        new_status = 'partial'
    else:
        new_status = 'completed'

    # 6. Update the Scheme Table
    scheme.claim_status = new_status
    scheme.updated_on = timezone.now()
    scheme.save()

    return new_status


from django.http import JsonResponse
from django.db.models import F, Sum
from django.utils import timezone
from datetime import datetime
def add_upgrade_sales(request):
    if request.method != 'POST':
        return JsonResponse({'message': 'invalid_request'}, status=400)
    role_id = request.session.get('role_id')
    has_access, error_message = check_user_access(role_id, 'upgrade_sales', "create")    
    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to approve the upgrade sales'})
    
    try:
        # -------------------------------
        # SESSION DATA
        # -------------------------------
        user_id = request.session.get('user_id')
        company_id = request.session.get('company_id')
        branch_id = request.session.get('branch_id')
        fyf_name = request.session.get('fyf')
        financial_year = calculate_financial_year(fyf_name)
        date_times = timezone.localtime(timezone.now())

        # -------------------------------
        # FORM
        # -------------------------------
        form = UpgradeForm(request.POST, request.FILES)
        if not form.is_valid():
            return JsonResponse({
                'message': 'form_error',
                'errors': form.errors.as_json()
            }, status=400)

        upgrade = form.save(commit=False)

        # -------------------------------
        # REQUEST DATA
        # -------------------------------
        tx_sales_id = request.POST.get('edit_id')
        sales_id = request.POST.get('sales_id')
        debit_amount = float(request.POST.get('debit_amount') or 0)

        # -------------------------------
        # GENERATE UPGRADE NO
        # -------------------------------
        upgrade_no = generate_serial_number(
            model=tm_upgrade_table,
            number_field='upgrade_no',
            financial_year_field='current_fy',
            financial_year=financial_year,
            branch_id=branch_id,
            prefix=""
        )

        # -------------------------------
        # SAVE UPGRADE MASTER (tm_upgrade)
        # -------------------------------
        upgrade.company_id = company_id
        upgrade.branch_id = branch_id
        upgrade.current_fy = financial_year
        upgrade.upgrade_no = upgrade_no
        upgrade.date = date_times.date()
        upgrade.time = date_times.time()
        upgrade.sales_id = sales_id
        upgrade.tx_sales_id = tx_sales_id
        upgrade.total_amount = float(request.POST.get('upgrade_amount') or 0)
        upgrade.subcategory_id = request.POST.get('subcategory_id')
        upgrade.brand_id = request.POST.get('brand_id')
        upgrade.model_id = request.POST.get('model_id')
        upgrade.variant_id = request.POST.get('variant_id')
        upgrade.color_id = request.POST.get('color_id')
        upgrade.debit_note_no = request.POST.get('debit_note_no')
        upgrade.debit_note_date = request.POST.get('debit_note_date')
        upgrade.imei_no = request.POST.get('imei_no')
        upgrade.total_amount = float(request.POST.get('upgrade_amount') or 0)
        upgrade.debit_amount = debit_amount
        upgrade.balance = upgrade.total_amount - debit_amount
        upgrade.status = 1
        upgrade.created_by = user_id
        upgrade.updated_by = user_id
        upgrade.created_on = date_times
        upgrade.updated_on = date_times
        upgrade.save()

        tx_sales_qs = child_sales_order_table.objects.filter(
            id=tx_sales_id,
            tm_sales_id= sales_id,
            status = 1
        )


        if tx_sales_qs.exists():

            tx_sales_qs.update(
                upgrade_collect=Coalesce(F('upgrade_collect'), Value(0)) + debit_amount,
                upgrade_approved_on=date_times,
                upgrade_approved_by=user_id,
                updated_on=date_times
            )

            updated_tx = tx_sales_qs.first()
            updated_tx.refresh_from_db()


            total_required = float(updated_tx.upgrade_amount or 0)
            total_collected = float(updated_tx.upgrade_collect or 0)


            if total_collected <= 0:
                tx_sales_qs.update(
                    is_upgrade_approved=0,
                    upgrade_status='pending'
                )

            elif total_collected < total_required:
                tx_sales_qs.update(
                    is_upgrade_approved=0,
                    upgrade_status='partial'
                )

            else:
                tx_sales_qs.update(
                    is_upgrade_approved=1,
                    upgrade_status='approved'
                )


            update_master_scheme_status(
                updated_tx.upgrade_id,
                user_id,
                date_times,
                'upgrade'
            )

        return JsonResponse({'message': 'success'})

    except Exception as e:
        return JsonResponse({
            'message': 'exception',
            'error': str(e)
        }, status=500)

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone


def upgrade_rejected(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('upgrade_id')
            print(category_id)
            category = child_sales_order_table.objects.get(id=category_id)
            date_times = timezone.localtime(timezone.now())  # returns datetime object
            role_id = request.session.get('role_id')
            user_id = request.session.get('user_id')
            has_access, error_message = check_user_access(role_id, 'upgrade_sales', "update")

            if not has_access:
                return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to reject upgrade sales'})

            remarks = request.POST.get('remarks').strip()

            category.upgrade_status = 'rejected'  # 🔴 Rejected
            category.upgrade_rejected_on = format_datetime(date_times)
            category.upgrade_rejected_by = user_id
            category.upgrade_rejected_remarks = remarks
            category.updated_on = timezone.now()
            category.save()           
          
            return JsonResponse({'message': 'success'})

        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})



from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone


def upgrade_revert(request):
    if request.method == 'POST':
        data_id = request.POST.get('id')    
        role_id = request.session.get('role_id')

        has_access, error_message = check_user_access(role_id, 'upgrade_sales', "update")

        if not has_access:
            return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to delete category details'})
               
        try:
            updated = child_sales_order_table.objects.filter(id=data_id)
            updated.update(
                upgrade_status='pending',
                is_upgrade_approved=0,
                upgrade_approved_on=None,
                upgrade_approved_by=0,
                upgrade_collect=0,
                updated_on=timezone.localtime(timezone.now())  # returns datetime object
            )

            if updated:
                return JsonResponse({'message': 'yes'})
            else:
                return JsonResponse({'message': 'no such data'})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})

    return JsonResponse({'message': 'Invalid request method'})
