from django.shortcuts import render
from django.http import JsonResponse, HttpResponseRedirect
from django.db.models import Q
from decimal import Decimal
from inventory.models import *
from sales.models import *
from material.models import *
from stock.models import *
from masters.models import *
from supplier.models import *
from customer.models import *
from store.models import *
from voucher.models import *
from claim_collect_upgrade.models import *
from common.utils import *

# Reuse existing logic from ledgers
from reports.customer_ledger import outstanding_customer
from reports.party_ledger import outstanding_supplier
from reports.supply_branch_ledger import outstanding_supply_branch

def outstanding_report(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 is_ho == 1:
            branches = branch_table.objects.filter(status=1).order_by('name')
        else:
            branches = branch_table.objects.filter(status=1, id=branch_id).order_by('name')

        customers = customer_table.objects.filter(status=1).order_by('name')
        suppliers = supplier_table.objects.filter(status=1).order_by('name')
        supply_branches = branch_table.objects.filter(status=1).order_by('name')

        return render(request, 'outstanding_report.html', {
            'branches': branches,
            'customers': customers,
            'suppliers': suppliers,
            'supply_branches': supply_branches
        })
    else:
        return HttpResponseRedirect("/")

def ajax_outstanding_report(request):
    role_id = request.session.get('role_id')
    branch_id = request.session.get('branch_id')
    is_ho = request.session.get('is_ho')
    fyf_name = request.session.get('fyf')
    financial_year = calculate_financial_year(fyf_name)
    
    has_access, error_message = check_user_access(role_id, 'outstanding_report', "read")
    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to view this report'})

    ledger_type = request.POST.get('ledger_type') # customer, supplier, supply_branch
    selected_customer_id = request.POST.get('customer_id')
    selected_supplier_id = request.POST.get('supplier_id')
    selected_supply_branch_id = request.POST.get('supply_branch_id')
    from_date = request.POST.get('from_date')
    to_date = request.POST.get('to_date')

    # For HO, we might want to filter by the branch whose outstanding we are checking
    # But usually, outstanding is calculated per entity across the system or for a specific store.
    # The requirement says "list all three" if nothing selected.

    data = []
    
    # ---------------------------
    # CUSTOMERS
    # ---------------------------
    if not ledger_type or ledger_type == 'customer':
        customers = customer_table.objects.filter(status=1)
        if selected_customer_id:
            customers = customers.filter(id=selected_customer_id)
        
        # If not HO, only show customers of this branch
        if is_ho == 0 or is_ho == '0':
            customers = customers.filter(branch_id=branch_id)

        for cust in customers:
            res = outstanding_customer(cust.branch_id, cust.id, financial_year)
            running_bal = res['opening_outstanding']
            for row in res['rows']:
                running_bal += Decimal(row['debit']) - Decimal(row['credit'])
            
            if running_bal != 0:
                is_dr = running_bal >= 0
                data.append({
                    'name': cust.name,
                    'type': 'Customer',
                    'branch': getItemNameById(branch_table, cust.branch_id),
                    'payable': format_amount(abs(running_bal)) if is_dr else '0.00',
                    'receivable': format_amount(abs(running_bal)) if not is_dr else '0.00',
                    'outstanding': f"{abs(running_bal):,.2f} ({'DR' if is_dr else 'CR'})",
                    'balance': float(running_bal)
                })

    # ---------------------------
    # SUPPLIERS
    # ---------------------------
    if not ledger_type or ledger_type == 'supplier':
        suppliers = supplier_table.objects.filter(status=1)
        if selected_supplier_id:
            suppliers = suppliers.filter(id=selected_supplier_id)

        for suppl in suppliers:
            # Note: party_ledger outstanding_supplier usually takes current branch_id
            # Suppliers are usually global, but let's use the session branch or HO logic
            target_branch = branch_id if is_ho == 0 else None # HO might see aggregate or per branch
            
            # If HO, we might need a branch filter for suppliers too if they are branch-specific
            # But usually suppliers are central. If target_branch is None, party_ledger might need adjustment
            # Let's assume branch_id for now as most reports are branch-centric
            res = outstanding_supplier(branch_id, suppl.id, financial_year)
            running_bal = res['opening_outstanding']
            for row in res['rows']:
                running_bal += Decimal(row['debit']) - Decimal(row['credit'])
            
            if running_bal != 0:
                is_dr = running_bal >= 0
                data.append({
                    'name': suppl.name,
                    'type': 'Supplier',
                    'branch': 'Central' if is_ho == 1 else getItemNameById(branch_table, branch_id),
                    'payable': format_amount(abs(running_bal)) if is_dr else '0.00',
                    'receivable': format_amount(abs(running_bal)) if not is_dr else '0.00',
                    'outstanding': f"{abs(running_bal):,.2f} ({'DR' if is_dr else 'CR'})",
                    'balance': float(running_bal)
                })

    # ---------------------------
    # SUPPLY BRANCHES
    # ---------------------------
    if not ledger_type or ledger_type == 'supply_branch':
        branches = branch_table.objects.filter(status=1)
        if selected_supply_branch_id:
            branches = branches.filter(id=selected_supply_branch_id)
        
        # Exclude self

        for br in branches:
            res = outstanding_supply_branch(branch_id, br.id, financial_year, from_date, to_date)
            
            running_bal = Decimal("0.00")
            for row in res['rows']:
                running_bal += Decimal(row['credit']) - Decimal(row['debit'])
            
            if running_bal != 0:
                # For Supply Branch: CR means we owe them (Payable usually, but user wants CR -> Receivable)
                # Actually, in supply_branch_ledger: dr_cr = "CR" if running_outstanding >= 0 else "DR"
                is_cr = running_bal >= 0
                data.append({
                    'name': br.name,
                    'type': 'Supply Branch',
                    'branch': getItemNameById(branch_table, branch_id),
                    'payable': format_amount(abs(running_bal)) if not is_cr else '0.00',
                    'receivable': format_amount(abs(running_bal)) if is_cr else '0.00',
                    'outstanding': f"{abs(running_bal):,.2f} ({'CR' if is_cr else 'DR'})",
                    'balance': float(running_bal)
                })

    # Add SL No
    for idx, item in enumerate(data):
        item['sl_no'] = idx + 1

    return JsonResponse({'data': data})
