from django.shortcuts import render
import json
from decimal import Decimal
import re

import random
from django.conf import settings
from django.shortcuts import render
from expenses.models import *
from store.models import *
from masters.models import *
from store.forms import *
from customer.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 ledger.views import create_ledger_master_and_opening_balance
from django.db import transaction

def generate_wholesale_customer_code():
    existing_codes = set(
        branch_table.objects.filter(is_wholesale=1, store_type='wholesale')
        .exclude(branch_code__isnull=True)
        .exclude(branch_code__exact='')
        .values_list('branch_code', flat=True)
    )

    used_numbers = set()
    for code in existing_codes:
        match = re.fullmatch(r'WS-(\d+)', str(code).strip())
        if match:
            used_numbers.add(int(match.group(1)))

    next_number = 1
    while next_number in used_numbers:
        next_number += 1

    return f"WS-{next_number}"


def b2b_boys(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        if user_type == 'stores':
            branch_id = request.session.get('branch_id')
            company   = select_row(branch_table, {'id':branch_id})
            branch    = selectList(branch_table,{'is_ho':1}, order_by='name')
            category  = selectList(category_table, order_by='name')
            employee  = selectList(employee_table, {'branch_id':branch_id}, order_by='name')
            customer_code = generate_wholesale_customer_code()
            bank = selectList(bank_table, {'is_default':1}, order_by='name')
            role = selectList(role_table, {'role_type':'wholesale'}, order_by='name')

            return render(
                request,
                'b2b_boys.html',
                {
                    'company': company,
                    'category': category,
                    'employee': employee,
                    'branch': branch,
                    'customer_code': customer_code,
                    'bank': bank,
                    'role': role
                }
            )
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    




def ajax_internal_wholesale(request):  
    role_id = request.session.get('role_id')
    has_access, error_message = check_user_access(role_id, 'b2b_boys', "read")

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to view the store details'})

    data = list(selectList(branch_table,{'is_wholesale':1, 'store_type':'wholesale'}).values())
    formatted = [
        {
            'id': index + 1,
            'action': '<button type="button" onclick="edit_data(\'{}\')" class="btn btn-outline-success btn-sm p-1"><i class="fas fa-edit"></i></button> \
                       <button type="button" onclick="delete_data(\'{}\')" class="btn btn-outline-danger btn-sm p-1"> <i class="fas fa-trash-alt"></i></button>\
                       <button type="button" onclick="employee_data(\'{}\')" class="btn btn-outline-secondary btn-sm p-1">Employee</button>'.format(item['id'], item['id'], item['id']), 
            'name': item['name'] if item['name'] else '-', 
            'code': item['branch_code'] if item['branch_code'] else '-', 
            'person': item['contact_person'] if item['contact_person'] else '-', 
            'email': item['email'] if item['email'] else '-', 
            'phone': item['phone'] if item['phone'] else '-', 
            'gst': item['gstin'] if item['gstin'] else '-', 
            'days': item['credit_days'] if item['credit_days'] else '-', 
            'limit': item['credit_limit'] if item['credit_limit'] else '-', 
            'city': item['city'] if item['city'] else '-', 
            'receivable': item['receivable'] if item['receivable'] else '-', 
            'payable': item['payable'] if item['payable'] else '-', 
            'incharge': getNameByBadge(employee_table, item['branch_incharge_id'])  if item['branch_incharge_id'] 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 internal_wholesale_add(request):
    if request.method == 'POST':
        try:
            with transaction.atomic():
                user_id = request.session.get('user_id')           
                company_id = request.session.get('company_id') 
                role_id = request.session.get('role_id')

                has_access, error_message = check_user_access(role_id, 'b2b_boys', "create")

                if not has_access:
                    return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to add store details'})

                form = storeform(request.POST, request.FILES)
                date_time = timezone.localtime(timezone.now())
                if not form.is_valid():
                    errors = form.errors.as_json()
                    return JsonResponse({'message': 'form_error', 'errors': errors}, status=400)

                if email := request.POST.get('email'):
                    if branch_table.objects.filter(
                        email=email,
                        status=1,
                        is_wholesale=1,
                        store_type='wholesale'
                    ).exists():
                        return JsonResponse({'message': 'info', 'error_message': 'Email already exists for this customer'}, status=400)
                
                                # Prepare store (branch) instance
                category = form.save(commit=False)
                fyf_name = request.session.get('fyf')
                financial_year = calculate_financial_year(fyf_name)

                name = request.POST.get('name')
                branch_code = (request.POST.get('customer_code') or '').strip()
                if not branch_code:
                    branch_code = generate_wholesale_customer_code()
                role_id = request.POST.get('role_id')
                city = request.POST.get('city')
                state = request.POST.get('state')
                pincode = request.POST.get('pincode')
                gst = request.POST.get('gst')
                credit_days = request.POST.get('credit_days')
                credit_limit = request.POST.get('credit_limit')
                receivable = request.POST.get('receivable') or 0
                payable = request.POST.get('payable') or 0
                bank_id = request.POST.get('bank_id') or 0
                bank_opening = request.POST.get('bank_opening') or 0
                person = request.POST.get('contact_person')
                phone = request.POST.get('phone')
                email = request.POST.get('email')
                pwd = request.POST.get('pwd')
              
                address1 = request.POST.get('address', '').strip()
                # Save store (branch) entry
                category.num_series = generate_num_series(branch_table)
                category.bank_id = bank_id
                category.bank_opening = bank_opening
                category.company_id = company_id
                category.is_store = 0
                category.is_franchise = 0
                category.ho_branch_id = 0
                category.name = name
                category.prefix = 'WS'
                category.branch_code = branch_code
                category.contact_person = person
                category.phone = phone
                category.email = email
                category.password = hashlib.md5(pwd.encode()).hexdigest()
                category.address_line1 = address1
                category.city = city
                category.state = state
                category.pincode = pincode if pincode else 0
                category.is_ho = 0
                category.receivable = receivable
                category.payable = payable
                category.created_by = user_id
                category.updated_by = user_id
                category.store_type = 'wholesale'
                category.is_wholesale = 1
                category.credit_days = credit_days
                category.credit_limit = credit_limit
                category.gstin = gst
                category.is_active = 1
                category.status = 1
                category.created_on = format_datetime(date_time)
                category.updated_on = format_datetime(date_time)
                category.save()

                branch_id = category.id

               
                employee_code = generate_wholesale_employee_code(branch_id)

                employee = employee_table(
                    employee_code=employee_code,
                    num_series=generate_num_series(employee_table),
                    company_id=0,
                    role_id=role_id,
                    branch_id=branch_id,
                    is_wholesale=1,
                    store_type='wholesale',
                    name=person,
                    email=email,
                    password=hashlib.md5(pwd.encode()).hexdigest(),
                    address_line1=address1,
                    mobile=phone,
                    city=city,
                    state=state,
                    pincode=int(pincode) if pincode else None,
                    photo='',
                    is_pos=1,
                    is_admin=0,
                    is_active=1,
                    status=1,
                    created_on=format_datetime(date_time),
                    updated_on=format_datetime(date_time),
                    created_by=user_id,
                    updated_by=user_id
                )
                employee.save()

                category.branch_incharge_id = employee.id
                category.save()

                

                return JsonResponse({'message': 'success'})

        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)}, status=500)



def check_internal_wholesale_phone(request):
    phone = request.GET.get('phone', '').strip()   
    edit_id = request.GET.get('edit_id', 0)
    exists = False

    if phone:
        exists = branch_table.objects.filter(
            phone=phone,
            status=1,
            is_active=1,
            is_wholesale=1,
            store_type='wholesale'
        ).exists()
        if edit_id:
            exists = exists and not branch_table.objects.filter(id=edit_id).exists()

    return JsonResponse({'exists': exists})


def check_internal_wholesale_email(request):
    email = request.GET.get('email', '').strip()
    edit_id = request.GET.get('id', 0)
    exists = False

    if email:
        query = branch_table.objects.filter(
            email=email,
            status=1,
            is_active=1,
            is_wholesale=1,
            store_type='wholesale'
        )
        if edit_id:
            query = query.exclude(id=edit_id)
        exists = query.exists()

    return JsonResponse({'exists': exists})





def internal_wholesale_edit(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        branch_id = request.POST.get('id')        
        branch = select_row(branch_table, {'id': branch_id})
        employees = selectList(employee_table, {'branch_id': branch_id}, order_by='name' , fields=['id', 'name'])


        if branch:
            vendor_data = {
                'id': branch.id,
                'credit_days': branch.credit_days,
                'credit_limit': branch.credit_limit,
                'gstin': branch.gstin,
                'name': branch.name,
                'prefix': branch.prefix,
                'branch_code': branch.branch_code,
                'city': branch.city,
                'state': branch.state,
                'pincode': branch.pincode,
                'description': branch.pincode,
                'contact_person': branch.contact_person,
                'email': branch.email,
                'phone': branch.phone,
                'branch_incharge_id': branch.branch_incharge_id,
                'is_active': branch.is_active,
                'address_line_1': branch.address_line1,
                'address_line_2': branch.address_line2,
                'captial': branch.captial,
                'employees': list(employees),  
                'receivable': branch.receivable,
                'payable': branch.payable,
                'bank_id': branch.bank_id,
                'bank_opening': branch.bank_opening,
            }
            return JsonResponse(vendor_data)
        else:
            return JsonResponse({'error': 'Vendor not found'}, status=404)


def internal_wholesale_update(request):
    if request.method == "POST":
        try:
            with transaction.atomic():
                category_id = int(request.POST.get('id'))
                category = branch_table.objects.get(id=category_id)
                role_id = request.session.get('role_id')

                has_access, error_message = check_user_access(role_id, 'b2b_boys', "update")
                if not has_access:
                    return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update customer details'})

                form = storeform(request.POST, request.FILES, instance=category)
                if not form.is_valid():
                    errors = form.errors.as_json()
                    return JsonResponse({'message': 'error', 'errors': errors})

                updated_category = form.save(commit=False)
                updated_category.name = request.POST.get('name')
                updated_category.city = request.POST.get('city')
                updated_category.state = request.POST.get('state')
                updated_category.pincode = request.POST.get('pincode') or 0
                updated_category.gstin = request.POST.get('gst')
                updated_category.credit_days = request.POST.get('credit_days') or 0
                updated_category.credit_limit = request.POST.get('credit_limit') or 0
                updated_category.receivable = request.POST.get('receivable') or 0
                updated_category.payable = request.POST.get('payable') or 0
                updated_category.bank_id = request.POST.get('bank_id') or 0
                updated_category.bank_opening = request.POST.get('bank_opening') or 0
                updated_category.branch_incharge_id = request.POST.get('incharge_id') or 0
                updated_category.is_active = request.POST.get('is_active') or 1
                updated_category.is_wholesale = 1
                updated_category.store_type = 'wholesale'
                updated_category.updated_by = request.session.get('user_id')
                updated_category.updated_on = format_datetime(timezone.localtime(timezone.now()))
                updated_category.save()

                return JsonResponse({'message': 'success'})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})


def internal_wholesale_delete(request):
    if request.method == 'POST':
        try:
            data_id = request.POST.get('id')
            role_id = request.session.get('role_id')
            has_access, error_message = check_user_access(role_id, 'b2b_boys', "delete")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to delete customer details'})

            branch = branch_table.objects.filter(
                id=data_id,
                is_wholesale=1,
                store_type='wholesale',
                status=1
            ).first()

            if not branch:
                return JsonResponse({'message': 'error', 'error_message': 'Record not found'})

            branch.status = 0
            branch.is_active = 0
            branch.updated_by = request.session.get('user_id')
            branch.updated_on = format_datetime(timezone.localtime(timezone.now()))
            branch.save()

            return JsonResponse({'message': 'yes'})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})

    return JsonResponse({'message': 'invalid_request'})



def b2b_employee_addpage(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        if user_type == 'stores':
            encoded_id = request.GET.get('id')
            decoded_id = decode_base64_id(encoded_id)
            cmpy = selectList(company_table, {'id':1})
            role = selectList(role_table, {'role_type': 'wholesale'},order_by='name')
            branch = selectList(branch_table, {'id':decoded_id}, order_by='name')
            if not decoded_id:
                return HttpResponse("ID parameter is missing")            
            employee = select_row(employee_table, {'id': decoded_id})
            return render(request, 'b2b_employee.html', {'company': cmpy,'role':role, 'branch': branch, 'employee': employee,'decoded_id':decoded_id})
        elif user_type == 'wholesale':
            decoded_id = request.session.get('branch_id')
            cmpy = selectList(company_table, {'id':1})
            role = selectList(role_table, {'role_type': 'wholesale'},order_by='name')
            branch = selectList(branch_table, {'id':decoded_id}, order_by='name')
            if not decoded_id:
                return HttpResponse("ID parameter is missing")            
            employee = select_row(employee_table, {'id': decoded_id})
            return render(request, 'b2b_employee.html', {'company': cmpy,'role':role, 'branch': branch, 'employee': employee,'decoded_id':decoded_id})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    

def b2b_employee_view(request):  
    role_id = request.session.get('role_id')
    has_access, error_message = check_user_access(role_id, 'b2b_boys', "read")
    branch_id = request.POST.get('branch_id')
  
    query = Q(status=1, is_wholesale=1, store_type='wholesale')
    if branch_id:
        query &= Q(branch_id=branch_id)

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to read employee details'})
            
    data = list(employee_table.objects.filter(query).order_by('-id').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']), 
            'cmpy': getItemNameById(branch_table, item['branch_id']) if item['branch_id'] else '-', 
            'role': getItemNameById(role_table, item['role_id']) if item['role_id'] else '-', 
            'code': item['employee_code'] if item['employee_code'] else '-', 
            'name': item['name'] if item['name'] else '-', 
            'mail': item['email'] if item['email'] else '-', 
            'phone': item['mobile'] if item['mobile'] else '-', 
            'address': item['address_line1'] if item['address_line1'] 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})

from employee.forms import EmployeeForm

def b2b_employee_add(request):
    if request.method == 'POST':
        try:
            user_id = request.session.get('user_id')           
            company_id = request.session.get('company_id')    
            date_time = datetime.now()       
            form = EmployeeForm(request.POST, request.FILES)

            role_id = request.session.get('role_id')
            has_access, error_message = check_user_access(role_id, 'b2b_boys', "create")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to add employee details'})
            
            if form.is_valid():
                category = form.save(commit=False)
                branch_id = request.POST.get('branch_id') or 0
                user_role = request.POST.get('user_role') or 0
                name = request.POST.get('name')
                user_name = request.POST.get('user_name')
                email = request.POST.get('email')
                pwd = request.POST.get('pwd')
                address1 = request.POST.get('address1')
                address2 = request.POST.get('address2')
                mobile = request.POST.get('mobile')
                city = request.POST.get('city')
                state = request.POST.get('state')
                pincode = request.POST.get('pincode')
                photo = request.FILES.get('photo')
                is_wholesale = request.POST.get('is_wholesale') or 0
                store_type = request.POST.get('store_type') or 'store'

                employee_code= generate_wholesale_employee_code(branch_id)

                if employee_table.objects.filter(
                    email=email,
                    status=1,
                    is_wholesale=1,
                    store_type='wholesale'
                ).exists():
                    return JsonResponse({
                        'message': 'email_exists',
                        'field': 'email',
                        'error': 'This email is already in use.'
                    })
                
                if employee_table.objects.filter(
                    mobile=mobile,
                    status=1,
                    is_wholesale=1,
                    store_type='wholesale'
                ).exists():
                    return JsonResponse({
                        'message': 'mobile_exists',
                        'field': 'mobile',
                        'error': 'This mobile number is already in use.'
                    })

                category.employee_code = employee_code
                category.num_series =  generate_num_series(employee_table)
                category.company_id = 0
                category.is_wholesale = is_wholesale
                category.store_type = store_type
                category.role_id = user_role
                category.branch_id = branch_id
                category.name = name
                category.nick_name = user_name
                category.email = email
                category.password = hashlib.md5(pwd.encode()).hexdigest()
                category.address_line1 = address1
                category.address_line2 = address2
                category.mobile = mobile
                category.city = city
                category.state = state
                category.pincode = int(pincode) if pincode else None
                category.photo = photo

               
                category.is_admin = 1
                category.is_active = 1
                category.status = 1
                category.created_by = user_id
                category.updated_by = user_id
                category.created_on = format_datetime(date_time)
                category.updated_on = format_datetime(date_time)
                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 b2b_employee_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = employee_table.objects.get(id=category_id)
            form = EmployeeForm(request.POST, request.FILES, instance=category)
            date_time = timezone.localtime(timezone.now())
            role_id = request.session.get('role_id')
            has_access, error_message = check_user_access(role_id, 'b2b_boys', "update")

            if not has_access:
                return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update employee details'})
            
            
            if form.is_valid():
                email = request.POST.get('email')
                mobile = request.POST.get('mobile')

                if employee_table.objects.filter(
                    email=email,
                    status=1,
                    is_wholesale=1,
                    store_type='wholesale'
                ).exclude(id=category_id).exists():
                   return JsonResponse({
                        'message': 'email_exists',
                        'field': 'edit_email',  # <== This must match input ID
                        'error': 'This email is already in use.'
                    })
                
                if employee_table.objects.filter(
                    mobile=mobile,
                    status=1,
                    is_wholesale=1,
                    store_type='wholesale'
                ).exclude(id=category_id).exists():
                    return JsonResponse({
                        'message': 'mobile_exists',
                        'field': 'edit_mobile',
                        'error': 'This mobile number is already in use.'
                    })

                
                updated_category = form.save(commit=False)
                company_id = 0
                user_role = request.POST.get('user_role') or 0
                name = request.POST.get('name')
                user_name = request.POST.get('user_name')
                pwd = request.POST.get('pwd')
                address1 = request.POST.get('address1')
                address2 = request.POST.get('address2')
                mobile = request.POST.get('mobile')
                city = request.POST.get('city')
                state = request.POST.get('state')
                pincode = request.POST.get('pincode')
                photo = request.FILES.get('photo')
                is_active = request.POST.get('is_active')
                

                

                updated_category.company_id = company_id
                updated_category.is_wholesale = 1
                updated_category.store_type = 'wholesale'
                updated_category.role_id = user_role
                updated_category.branch_id = request.POST.get('branch_id') or 0
                updated_category.name = name
                updated_category.nick_name = user_name
                updated_category.email = email
                if pwd:
                    updated_category.password = hashlib.md5(pwd.encode()).hexdigest()

                updated_category.address_line1 = address1
                updated_category.address_line2 = address2
                updated_category.mobile = mobile
                updated_category.city = city
                updated_category.state = state
                updated_category.pincode = int(pincode) if pincode else None
               
                if photo:
                    updated_category.photo = photo
                
                # Basic Details
             

                updated_category.is_active = is_active      

                updated_category.updated_by = request.session.get('user_id')
                updated_category.updated_on = format_datetime(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 check_b2b_employee_email(request):
    email = request.GET.get('email', '').strip()
    edit_id = request.GET.get('id')
    exists = False

    if email:
        query = employee_table.objects.filter(
            email=email,
            status=1,
            is_wholesale=1,
            store_type='wholesale'
        )
        if edit_id:
            query = query.exclude(id=edit_id)
        exists = query.exists()

    return JsonResponse({'exists': exists})


def check_b2b_employee_phone(request):
    mobile = request.GET.get('mobile', '').strip()
    edit_id = request.GET.get('id')
    exists = False

    if mobile:
        query = employee_table.objects.filter(
            mobile=mobile,
            status=1,
            is_wholesale=1,
            store_type='wholesale'
        )
        if edit_id:
            query = query.exclude(id=edit_id)
        exists = query.exists()

    return JsonResponse({'exists': exists})
