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 sales.forms import *
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 django.views.decorators.csrf import csrf_exempt

#```````````````````````````````````````````````````````````**PURCHASE ORDER**````````````````````````````````````````````````````````````````````````````````

def contra_sales(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        is_ho = request.session.get('is_ho')
        if user_type in ['stores','wholesale']:
            company = select_row(company_table, {'id':1})
            branch = selectList(branch_table, order_by='name')
            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')
            return render(request, 'contra/contra_sales.html', {'company': company,'branch':branch,'bank':bank})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    


def contra_sales_view(request):  
    role_id = request.session.get('role_id')
    branch_id = request.session.get('branch_id')
    user_type = request.session.get('user_type')
    has_access, error_message = check_user_access(role_id, 'contra_sales', "read")

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to read contra sales details'})
    
    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)
    bank_id = request.POST.get('bank_id')

    query = Q(status=1, current_fy = financial_year,branch_id=branch_id)
  
    if from_date and to_date:
        query &= Q(date__range=[from_date, to_date])
  
    if bank_id:
        query &= Q(bank_id=bank_id)

    
    data = list(selectList(contra_sales_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': format_date_month_year(item['date']) if item['date'] else '-',
            'bank': getItemNameById(bank_table,item['bank_id']) if item['bank_id'] else '-',
            'to': (
                '<span class="badge text-bg-primary">Cash to Bank</span>' if item['payment_type'] == 'cash_to_bank'
                else '<span class="badge text-bg-info text-dark">Bank to Cash</span>' if item['payment_type'] == 'bank_to_cash'
                else '-'
            ),
            'amount': format_amount(item['amount']) if item['amount'] else '-',
            'c_no': item['contra_no'] if item['contra_no'] 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>'
            )
        }
        for index, item in enumerate(data)
    ]

    return JsonResponse({'data': formatted})

def contra_sales_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')
            has_access,error_message = check_user_access(role_id, 'contra_sales', "create")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to create contra sales details'})

            form = contraForm(request.POST, request.FILES)
            if form.is_valid():
                category = form.save(commit=False)
                date = request.POST.get('date')
                from_type = request.POST.get('from_type') or 0
                bank_id = request.POST.get('bank_id') or 0
                amount = float(request.POST.get('amount') or 0)
                description = request.POST.get('description')    
                date_time = timezone.localtime(timezone.now())
           
                
                negative_check_fields = ['amount']
                has_negative, error_message = has_negative_values(request.POST, negative_check_fields)
                if has_negative:
                    return JsonResponse({'message': 'infos', 'error_message': error_message})
            


                generated_po_no = generate_serial_number(
                    model=contra_sales_table,
                    number_field='contra_no',
                    financial_year_field='current_fy',
                    financial_year=financial_year,
                    branch_id=branch_id,
                    prefix="CN",
                    padding=3
                )
                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']
             
                if from_type == 'cash_to_bank':
                    if amount > cash_balance:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient cash balance. Required: {amount}, Available: {cash_balance}'
                        })
                if from_type == 'bank_to_cash':
                    selected_bank_balance = balance_info['selected_bank_balance']
                    if amount > selected_bank_balance:
                        return JsonResponse({
                            'message': 'infos',
                            'error_message': f'Insufficient bank balance. Required: {amount}, Available: {selected_bank_balance}'
                        })

               

                

                # Save transaction
                category.date = date
                category.time=format_time(date_time)
                category.contra_no = generated_po_no
                category.payment_type = from_type
                category.bank_id = bank_id
                category.amount = amount
                category.description = description                
                category.current_fy = financial_year
                category.company_id = company_id
                category.branch_id = branch_id
                category.employee_id = user_id
                category.is_active = 1
                category.status = 1
                category.created_by = user_id
                category.updated_by = user_id
                category.created_on = date_time
                category.updated_on = date_time  
                if user_type == 'wholesale':
                    category.is_wholesale = 1
                else:
                    category.is_wholesale = 0
                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 contra_sales_edit(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        data = contra_sales_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])


def contra_sales_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = contra_sales_table.objects.get(id=category_id)
            form = contraForm(request.POST, request.FILES, instance=category)
            role_id = request.session.get('role_id')
            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, 'contra_sales', "update")
            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update contra sales details'})
            
            if form.is_valid():
                updated_category = form.save(commit=False)
                from_type = request.POST.get('from_type') or ''
                # date = request.POST.get('date')                
                bank_id = request.POST.get('bank_id') or 0
                amount = float(request.POST.get('amount') or 0)
                description = request.POST.get('description')   
                is_active = request.POST.get('is_active')                
                negative_check_fields = ['amount']
                has_negative, error_message = has_negative_values(request.POST, negative_check_fields)

                if has_negative:
                    return JsonResponse({'message': 'infos', 'error_message': error_message})

               

                # Save updates
                updated_category.payment_type = from_type   
                # updated_category.date = date             
                updated_category.bank_id = bank_id
                updated_category.amount = amount            
                updated_category.is_active = is_active            
                updated_category.description = description
                updated_category.updated_by = request.session.get('user_id')
                updated_category.updated_on = date_time
                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 contra_sales_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, 'contra_sales', "delete")

          
        
        if not has_access:
            return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to delete contra sales details'}) 
           
        try:
            updated = contra_sales_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'})

