from django.shortcuts import render
import json
from django.conf import settings
from django.shortcuts import render
from expenses.models import *
from common.models import *
from masters.models import *
from expenses.forms import *
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 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 common.views import *
from django.utils.timezone import localdate
from django.core.exceptions import PermissionDenied
from functools import wraps
from decimal import Decimal

#```````````````````````````````````````````````````````````**EXPENSE MASTER**````````````````````````````````````````````````````````````````````````````````

def expense_master(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
       
        if user_type == 'admin':
            company = select_row(company_table, {'id': 1})  
            category = selectList(category_table, order_by='name')                   
           
            return render(request, 'expense_master.html', {'company': company,'category':category})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    


def check_expense_name(request):
    name = request.POST.get('name', '').strip()
    category_id = request.POST.get('category_id')  # for edit case

    exists = expense_master_table.objects.filter(
        name__iexact=name,
        status=1
    )

    if category_id:
        exists = exists.exclude(id=category_id)

    if exists.exists():
        return JsonResponse({
            'exists': True,
            'message': 'Expense name already exists'
        })

    return JsonResponse({'exists': False})

def expense_type_view(request):  
    role_id = request.session.get('role_id')
    has_access, error_message = check_user_access(role_id, 'master_expense_type', "read")

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to read Expense details'})
    
    data = list(selectList(expense_master_table).values())

    formatted = [
        {
            'id': index + 1,
            'action': '<button type="button" onclick="edit_data(\'{}\')" class="btn btn-outline-success btn-xs p-1" title="Edit"><i class="fas fa-edit"></i></button> \
                      <button type="button" onclick="delete_data(\'{}\')" class="btn btn-outline-danger btn-xs p-1" title="Delete"><i class="fas fa-trash"></i></button>\
                      <button type="button" onclick="view_data(\'{}\')" class="btn btn-outline-primary btn-xs p-1" title="View Expense"> <i class="fas fa-eye"></i></button>'.format(item['id'], item['id'], item['id']), 
            'category': item['name'] if item['name'] else '-', 
            'description': item['description'] if item['description'] else '-', 
            'status': '<span class="badge text-bg-success">Active</span>' if item['is_active'] else '<span class="badge text-bg-danger">Inactive</span>'  # Assuming is_active is a boolean field
        } 
        for index, item in enumerate(data)
    ]
    return JsonResponse({'data': formatted})



def expense_type_add(request):
    if request.method == 'POST':
        try:
            user_id = request.session.get('user_id')           
            company_id = request.session.get('company_id')           
            role_id = request.session.get('role_id')
            date_times = timezone.localtime(timezone.now())
            has_access = check_user_access(role_id, 'master_expense_type', "create")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to create Expense details'})
            
            form = ExpenseTypeForm(request.POST, request.FILES)
            if form.is_valid():
                category = form.save(commit=False)
                category.name = request.POST.get('name')
                category.description = request.POST.get('description')
                category.company_id = company_id
                category.is_active = 1
                category.status = 1
                category.created_by = user_id
                category.updated_by = user_id
                category.created_on = date_times
                category.updated_on = date_times
                category.save()
                return JsonResponse({'message': 'success'})
            else:
                errors = form.errors.as_json()
                return JsonResponse({'message': 'form_error', 'errors': errors}, status=400)

        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)}, status=500)





def expense_type_edit(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        data = expense_master_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])



def expense_type_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = expense_master_table.objects.get(id=category_id)
            role_id = request.session.get('role_id')
            date_times = timezone.localtime(timezone.now())
            has_access, error_message = check_user_access(role_id, 'master_expense_type', "update")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update Expense details'})
            
            form = ExpenseTypeForm(request.POST, request.FILES, instance=category)
            if form.is_valid():
                updated_category = form.save(commit=False)
                desc = request.POST.get('description')
                name = request.POST.get('name')
                is_active = request.POST.get('is_active')

                updated_category.name = name            
                updated_category.is_active = is_active            
                updated_category.description = desc
                updated_category.updated_by = request.session.get('user_id')
                updated_category.updated_on = date_times
                updated_category.save()
                return JsonResponse({'message': 'success'})
            else:
                errors = form.errors.as_json()
                return JsonResponse({'message': 'error', 'errors': errors})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})



def expense_type_delete(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, 'master_expense_type', "delete")

        if not has_access:
            return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to delete Expense details'}) 
           
        try:
            updated = expense_master_table.objects.filter(id=data_id).update(status=0)
            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'})



#```````````````````````````````````````````````````````````**EXPENSE**````````````````````````````````````````````````````````````````````````````````


def expenses(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        is_ho = request.session.get('is_ho') or 0
        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')
        if user_type == 'admin':
            company = select_row(company_table, {'id':1})
            expense = selectList(expense_master_table, order_by='name')
            branch = selectList(branch_table, order_by='name')
            is_wholesale = 0
            return render(request, 'expense.html', {'company': company,'expense':expense,'branch':branch,'bank':bank,'is_wholesale':is_wholesale})
        elif user_type == 'stores':
            is_wholesale = 0
            company = select_row(company_table, {'id':1})
            expense = selectList(expense_master_table, order_by='name')
            branch = selectList(branch_table, order_by='name')           
            return render(request, 'store_expense.html', {'company': company,'expense':expense,'branch':branch,'bank':bank,'is_wholesale':is_wholesale})
        elif user_type == 'wholesale':
            is_wholesale = 1
            company = select_row(company_table, {'id':1})
            expense = selectList(expense_master_table, order_by='name')
            branch = selectList(branch_table, order_by='name')           
            return render(request, 'store_expense.html', {'company': company,'expense':expense,'branch':branch,'bank':bank,'is_wholesale':is_wholesale})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    


def expense_type_expenses(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        if user_type == 'admin':
            encoded_id = request.GET.get('id', None)
            decoded_id = decode_base64_id(encoded_id)
            if decoded_id:
                company = select_row(company_table, {'id':1})
                expense = selectList(expense_master_table, order_by='name')
                branch = selectList(branch_table, order_by='name') 
                bank = selectList(bank_table, order_by='name')
            else:
                return HttpResponse("ID parameter is missing")
            
            return render(request, 'expense.html', {'company': company,'expense':expense,'branch':branch,'expense_id':decoded_id,'bank':bank})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")




def expense_view(request):  
    role_id = request.session.get('role_id')
    user_type = request.session.get('user_type')
    has_access, error_message = check_user_access(role_id, 'expense', "read")

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to read Expense details'})
    
    expense_id = request.POST.get('expense_id')
    branch_id = request.POST.get('store_id')
    from_date = request.POST.get('from_date')
    to_date = request.POST.get('to_date')
    fyf_name = request.session.get('fyf')
    financial_year = calculate_financial_year(fyf_name)
    

    query = Q(status=1, current_fy = financial_year)
    
    if expense_id:
        query &= Q(expense_id=expense_id)

    if branch_id:
        query &= Q(branch_id=branch_id)

    if from_date and to_date:
        query &= Q(date__range=[from_date, to_date])

    
    if user_type == 'admin':
        data = list(selectList(expense_table, query).values())
        
    elif user_type in ['stores','wholesale']:
        hob = request.session.get('branch_id')
        print(hob)
        query &= Q(branch_id=hob, current_fy = financial_year,status=1,)
        data = list(selectList(expense_table, query).values())
        

    formatted = [
        {
            'id': index + 1,
            'action': '<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>'.format(item['id'], item['id']), 
            'date': item['date'] if item['date'] else '-', 
            'store': getItemNameById(branch_table, item['branch_id']) if item['branch_id'] else '-', 
            'expense': getItemNameById(expense_master_table, item['expense_id']) if item['expense_id'] else '-', 
            'bank_name': getItemNameById(bank_table, item['bank_id']) if item['bank_id'] else '-', 
            'name': item['name'] if item['name'] else '-', 
            'amount': format_amount(item['amount'] )if item['amount'] else '-', 
            'cash': format_amount(item['cash'] )if item['cash'] else '-', 
            'bank': format_amount(item['bank'] )if item['bank'] else '-', 
            'description': item['description'] if item['description'] else '-', 
            'status': '<span class="badge text-bg-success">Active</span>' if item['is_active'] else '<span class="badge text-bg-danger">Inactive</span>'  # Assuming is_active is a boolean field
        } 
        for index, item in enumerate(data)
    ]
    return JsonResponse({'data': formatted})



def expense_add(request):  
    if request.method == 'POST':
        try:
            user_id = request.session.get('user_id')           
            user_type = request.session.get('user_type')           
            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())
            has_access,error_message = check_user_access(role_id, 'expense', "create")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to create Expense details'})
            
            form = ExpenseForm(request.POST, request.FILES)
            if form.is_valid():
                category = form.save(commit=False)
                date = request.POST.get('date')
                expense = request.POST.get('expense_id') or 0
                name = request.POST.get('name')
                amount = float(request.POST.get('amount') or 0) 
                description = request.POST.get('description')
                cash = float(request.POST.get('cash') or 0)
                bank = float(request.POST.get('bank') or 0)
                bank_id = request.POST.get('bank_id') or 0
                is_wholesale = int(request.POST.get('is_wholesale') or 0)

                negative_check_fields = ['amount', 'cash', 'bank']
                has_negative, error_message = has_negative_values(request.POST, negative_check_fields)

                if has_negative:
                    return JsonResponse({'message': 'infos', 'error_message': error_message})

                category.date = date
                category.cash = cash
                category.bank = bank
                category.bank_id = bank_id
                category.expense_id = expense
                category.name = name
                category.amount = amount
                category.description = description                
                category.current_fy = financial_year
                category.is_active = 1
                category.status = 1
                category.created_by = user_id
                category.updated_by = user_id
                category.time = date_times.strftime('%H:%M:%S')
                category.created_on = date_times
                category.updated_on = date_times
                category.employee_id = user_id
                category.is_wholesale = is_wholesale

                if user_type == 'admin':
                    category.company_id = company_id
                    category.branch_id = 0
                    
                elif user_type in ['stores','wholesale']:
                    balance_info = get_cash_and_bank_balance(
                        branch_id=branch_id,
                        financial_year=financial_year,
                        bank_id=bank_id
                        )

                    cash_balance = balance_info['cash_balance']
                    selected_bank_balance = balance_info['selected_bank_balance']
                    

                    if cash > cash_balance:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient cash balance. Required: {cash}, Available: {cash_balance}'
                        })

                    if bank > selected_bank_balance:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient bank balance. Required: {bank}, Available: {selected_bank_balance}'
                        })
                    



                    category.company_id = 0
                    category.branch_id = branch_id                       
                category.save()
                return JsonResponse({'message': 'success'})
            else:
                errors = form.errors.as_json()
                return JsonResponse({'message': 'form_error', 'errors': errors}, status=400)

        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)}, status=500)

    return JsonResponse({'message': 'invalid_method'}, status=405)


def expense_edit(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        data = expense_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])


def expense_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = expense_table.objects.get(id=category_id)
            form = ExpenseForm(request.POST, request.FILES, instance=category)
            user_type = request.session.get('user_type')
            role_id = request.session.get('role_id')
            store_date = request.session.get('store_date')           
            branch_id = request.session.get('branch_id') 
            fyf_name = request.session.get('fyf')
            financial_year = calculate_financial_year(fyf_name)
            has_access,error_message = check_user_access(role_id, 'expense', "update")
            date_times = timezone.localtime(timezone.now())
            store_status = request.session.get('store_status')

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update Expense details'})
            
            if form.is_valid():
                updated_category = form.save(commit=False)
                date = request.POST.get('date')
                expense = request.POST.get('expense_id') or 0
                name = request.POST.get('name')
                amount = Decimal(str(request.POST.get('amount') or 0))
                cash = Decimal(str(request.POST.get('cash') or 0))
                bank = Decimal(str(request.POST.get('bank') or 0))
                description = request.POST.get('description')
                is_active = request.POST.get('is_active')
                bank_id = request.POST.get('bank_id') or 0

                

                updated_category.date = date            
                updated_category.expense_id = expense            
                updated_category.bank_id = bank_id
                updated_category.name = name            
                updated_category.cash = cash            
                updated_category.bank = bank            
                updated_category.amount = amount            
                updated_category.is_active = 1            
                updated_category.description = description
                updated_category.updated_by = request.session.get('user_id')

                if user_type == 'stores':
                    balance_info = get_cash_and_bank_balance(
                        branch_id=branch_id,
                        financial_year=financial_year,
                        bank_id=bank_id
                        )
                    

                    cash_balance = balance_info['cash_balance']
                    cash_available = cash_balance - cash
                    selected_bank_balance = balance_info['selected_bank_balance']
                    bank_available = selected_bank_balance - bank
                    print(cash_available, bank_available, selected_bank_balance)

                    if cash > cash_available:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient cash balance. Required: {cash}, Available: {cash_balance}'
                        })

                    if bank > bank_available:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient bank balance. Required: {bank}, Available: {selected_bank_balance}'
                        })
                    
                updated_category.updated_on = date_times
                updated_category.save()
                return JsonResponse({'message': 'success'})
            else:
                errors = form.errors.as_json()
                return JsonResponse({'message': 'error', 'errors': errors})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})



def expense_delete(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, 'expense', "delete")



        if not has_access:
            return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to delete Expense details'}) 
           
        try:
            updated = expense_table.objects.filter(id=data_id).update(status=0)
            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'})


from django.http import JsonResponse
from decimal import Decimal

def ajax_get_balance(request):
    branch_id = request.session.get('branch_id')
    fyf_name  = request.session.get('fyf')
    financial_year = calculate_financial_year(fyf_name)

    bank_id = request.GET.get('bank_id')  # optional

    balance_info = get_cash_and_bank_balance(
        branch_id=branch_id,
        financial_year=financial_year,
        bank_id=bank_id
    )

    return JsonResponse({
        'cash_balance': str(balance_info['cash_balance']),
        'bank_balance': str(balance_info['selected_bank_balance']) if bank_id else None
    })
