from django.shortcuts import render
import json
from decimal import Decimal

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 customer(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')      
            c_type='b2b'     
            return render(request, 'b2b_customer.html', {'company': company,'category':category,'employee':employee,'branch':branch,'c_type':c_type})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    


def b2c_customer(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        if user_type in ['stores','wholesale']:
            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')      
            c_type='b2c'
            return render(request, 'b2c_customer.html', {'company': company,'category':category,'employee':employee,'branch':branch,'c_type':c_type})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")
    




def customer_view(request):  
    role_id = request.session.get('role_id')
    branch_id = request.session.get('branch_id')
    c_type = request.POST.get('c_type') 

    if c_type == 'b2b':
        has_access, error_message = check_user_access(role_id, 'b2b_customer', "read")
    
    elif c_type == 'b2c':
        has_access, error_message = check_user_access(role_id, 'b2c_customer', "read")

    if not has_access:
        return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to read customer details'})
    
   
    query = Q(status = 1, branch_id = branch_id)

    if c_type:
        query &= Q(c_type = c_type)
    
    data = list(selectList(customer_table, query).values())
    formatted = []
    for index, item in enumerate(data):

        # show copy button only for wholesale customers
        copy_btn = ''
        if item.get('customer_type') == 'wholesale':
            copy_btn = f'''
            <button type="button" onclick="copy_login_link('{item['uuid']}')" 
            class="btn btn-outline-info btn-xs p-1" title="Copy Login Link">
            <i class="fas fa-copy"></i></button>
            '''

        action = f'''
        <button type="button" onclick="edit_data('{item['id']}')" class="btn btn-outline-success btn-xs p-1" title="Edit">
            <i class="fas fa-edit"></i>
        </button>
        <button type="button" onclick="delete_data('{item['id']}')" class="btn btn-outline-danger btn-xs p-1" title="Delete">
            <i class="fas fa-trash-alt"></i>
        </button>
        {copy_btn}
        '''

        formatted.append({
            'id': index + 1,
            'action': action,
            'store': getItemNameById(branch_table, item['branch_id']) if item['branch_id'] else '-',
            'type': format_badge(
                item['customer_type'],
                mapping={'wholesale': 'badge text-bg-primary', 'retail': 'badge text-bg-info'},
                label_mapping={'wholesale': 'Wholesale', 'retail': 'Retail'}
            ),
            'name': item['name'] or '-',
            'person': item['contact_person'] or '-',
            'email': item['email'] or '-',
            'phone': item['phone'] or '-',
            'mobile': item['mobile'] or '-',
            'city': item['city'] or '-',
            'gst': item['gst'] or '-',
            "days": item['credit_days'] or '-',
            "limit": item['credit_limit'] or '-',
            'status': '<span class="badge text-bg-success">Active</span>' if item['is_active']
                    else '<span class="badge text-bg-danger">Inactive</span>'
        })

    return JsonResponse({'data': formatted})


import hashlib



def customer_add(request):
    if request.method == 'POST':
        try:
            user_type = request.session.get('user_type')           
            user_id = request.session.get('user_id')           
            company_id = request.session.get('company_id')           
            branch_id = request.session.get('branch_id') or 0
            role_id = request.session.get('role_id')
            fyf_name = request.session.get('fyf')
            date_times = timezone.localtime(timezone.now())
            financial_year = calculate_financial_year(fyf_name)

            
            
            form = customerform(request.POST, request.FILES)
            if form.is_valid():
                category = form.save(commit=False)
                name            = request.POST.get('name')
                email           = request.POST.get('email')
                phone           = request.POST.get('phone')
                mobile          = request.POST.get('mobile')
                customer        = request.POST.get('customer_type')
                city            = request.POST.get('city')
                state           = request.POST.get('state')
                pincode         = request.POST.get('pincode') or 0
                address         = request.POST.get('address')
                remarks         = request.POST.get('remarks')
                gst             = request.POST.get('gst')
                credit_days     = request.POST.get('credit_days')
                credit_limit    = request.POST.get('credit_limit')
                contact_person  = request.POST.get('contact_person')
                receivable      = request.POST.get('receivable') or 0.00
                payable         = request.POST.get('payable') or  0.00
                
                # Generate a random 8-digit number string
                random_pass = str(random.randint(10000000, 99999999))
                password_hashed = hashlib.md5(random_pass.encode()).hexdigest()

                c_type          = request.POST.get('c_type') or 'b2c'

                has_access = False
                if c_type == 'b2b':
                    has_access, error_message = check_user_access(role_id, 'b2b_customer', "create")
                elif c_type == 'b2c':
                    has_access, error_message = check_user_access(role_id, 'b2c_customer', "create")
                else:
                    return JsonResponse({'message': 'warning', 'error_message': 'Invalid customer type'})
                
                if not has_access:
                    return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to create customer details'})

                with transaction.atomic():
                    category.company_id     = company_id
                    category.contact_person = contact_person
                    category.receivable     = receivable
                    category.payable        = payable
                    category.c_type         = c_type
                    category.gst            = gst
                    category.credit_days    = credit_days if credit_days else 0
                    category.credit_limit   = credit_limit if credit_limit else 0
                    category.name           = name
                    category.email          = email
                    category.branch_id      = branch_id
                    category.address_line1  = address
                    category.address_line2  = ''
                    category.city           = city
                    category.state          = state
                    category.pincode        = pincode if pincode else None
                    category.phone          = phone
                    category.mobile         = mobile
                    category.customer_type  = customer
                    category.remarks        = remarks
                    category.is_active      = 1
                    category.status         = 1
                    category.created_by     = user_id
                    category.updated_by     = user_id
                    category.created_on     = format_datetime(date_times)
                    category.updated_on     = format_datetime(date_times)
                    category.password       = password_hashed
                    if user_type == 'wholesale':
                        category.is_wholesale = 1
                    else:
                        category.is_wholesale = 0
                    category.save()


                    if Decimal(str(payable)) != 0 or Decimal(str(receivable)) != 0:
                        create_ledger_master_and_opening_balance(
                            current_fy=financial_year,
                            branch_id=branch_id,
                            master_id=category.id,
                            master_name=category.name,
                            ledger_type="customer",
                            ledger_mode="customer",
                            payable=payable,
                            receivable=receivable,
                            created_by=user_id,
                            updated_by=user_id,
                        )

                    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 customer_edit(request):
    if request.method == "POST":
        data = customer_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])



def customer_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = customer_table.objects.get(id=category_id)
            form = customerform(request.POST, request.FILES, instance=category)
            role_id = request.session.get('role_id')
            branch_id = request.session.get('branch_id')
          

            
            if form.is_valid():
                updated_category = form.save(commit=False)
                name = request.POST.get('name')
                email = request.POST.get('email')
                phone = request.POST.get('phone')
                mobile = request.POST.get('mobile')
                customer = request.POST.get('customer_type')
                city = request.POST.get('city')
                state = request.POST.get('state')
                pincode = request.POST.get('pincode') or 0
                address = request.POST.get('address')
                remarks = request.POST.get('remarks')
                is_active = request.POST.get('is_active')
                gst = request.POST.get('gst')
                credit_days = request.POST.get('credit_days')
                credit_limit= request.POST.get('credit_limit')
                contact_person = request.POST.get('contact_person')
                receivable = request.POST.get('receivable') or 0.00
                payable = request.POST.get('payable') or 0.00
                password = request.POST.get('password') or ''
                c_type = category.c_type

                if c_type == 'b2b':
                    has_access, error_message = check_user_access(role_id, 'b2b_customer', "update")
                elif c_type == 'b2c':
                    has_access, error_message = check_user_access(role_id, 'b2c_customer', "update")
                
                if not has_access:
                    return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to update customer details'})

                with transaction.atomic():
                    updated_category.name = name
                    updated_category.contact_person = contact_person
                    updated_category.receivable = receivable
                    updated_category.payable = payable
                    updated_category.gst = gst
                    updated_category.branch_id = branch_id
                    updated_category.credit_days = credit_days if credit_days else 0
                    updated_category.credit_limit = credit_limit if credit_limit else 0
                    updated_category.email = email
                    updated_category.address_line1 = address
                    updated_category.address_line2 = ''
                    updated_category.city = city
                    updated_category.state = state
                    updated_category.pincode = pincode
                    updated_category.phone = phone
                    updated_category.mobile = mobile
                    updated_category.customer_type = customer
                    updated_category.remarks = remarks        
                    updated_category.is_active = is_active            
                    updated_category.updated_by = request.session.get('user_id')
                    updated_category.updated_on = format_datetime(timezone.now())
                    if password:
                        updated_category.password = hashlib.md5(password.encode()).hexdigest()
                    updated_category.save()

                    fyf_name = request.session.get('fyf')
                    financial_year = calculate_financial_year(fyf_name)

                    if Decimal(str(payable)) != 0 or Decimal(str(receivable)) != 0:
                        create_ledger_master_and_opening_balance(
                            current_fy=financial_year,
                            branch_id=branch_id,
                            master_id=category_id,
                            master_name=updated_category.name,
                            ledger_type="customer",
                            ledger_mode="customer",
                            payable=payable,
                            receivable=receivable,
                            created_by=request.session.get('user_id'),
                            updated_by=request.session.get('user_id'),
                            update=True
                        )

                    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 customer_delete(request):
    if request.method == 'POST':
        data_id = request.POST.get('id')   
        role_id = request.session.get('role_id')

        customer = select_row(customer_table, {'id':data_id})
        c_type = customer.customer_type

        if c_type == 'b2b':
            has_access, error_message = check_user_access(role_id, 'b2b_customer', "delete")
        elif c_type == 'b2c':
            has_access, error_message = check_user_access(role_id, 'b2c_customer', "delete")
        
        if not has_access:
            return JsonResponse({'message': 'permission', 'error_message': 'You do not have permission to delete customer details'})
            

        customer.status = 0
        customer.is_active = 0
        customer.save()
        return JsonResponse({'message': 'yes'})


def customer_list(request):
    if 'user_id' in request.session:
        branch = selectList(branch_table, order_by='name')
        return render(request, 'customer_list.html', {'branch': branch})
    else:
        return HttpResponseRedirect("/")


def customer_list_view(request):
    if 'user_id' not in request.session:
        return JsonResponse({'message': 'error', 'error_message': 'Session expired. Please login again.'})

    branch_id = request.POST.get('branch_id')
    customer_type = request.POST.get('customer_type')
    query = Q(status=1)
    if branch_id:
        query &= Q(branch_id=branch_id)
    
    if customer_type:
        query &= Q(customer_type=customer_type)
    
    data = list(selectList(customer_table, query).values())
    formatted = [
        {
            'id'    : index + 1,
            'branch': getItemNameById(branch_table, item['branch_id']) if item['branch_id'] else '-',
            'type'  : format_badge(item['customer_type'], mapping={'wholesale': 'badge text-bg-primary', 'retail': 'badge text-bg-info'}, label_mapping={'wholesale': 'Wholesale', 'retail': 'Retail'}),
            'name'  : item['name'] if item['name'] else '-',
            'person': item['contact_person'] if item['contact_person'] else '-',
            'email' : item['email'] if item['email'] else '-',
            'phone' : item['phone'] if item['phone'] else '-',
            'mobile': item['mobile'] if item['mobile'] else '-',
            'city'  : item['city'] if item['city'] else '-',
            'gst'   : item['gst'] if item['gst'] 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})



# adjust import as needed

def check_customer_name(request):
    name = request.GET.get('name')
    item_id = request.GET.get('id')
    branch_id = request.session.get('branch_id')

    if name and branch_id:
        query = selectList(customer_table, {'name':name,'branch_id':branch_id})

        if item_id:
            query = query.exclude(id=item_id)

        if query.exists():
            return JsonResponse({'exists': True})

    return JsonResponse({'exists': False})




from django.http import JsonResponse

from django.http import JsonResponse

def check_customer_phone(request):
    phone = request.GET.get('phone', '').strip()
    branch_id = request.session.get('branch_id')
    edit_id = request.GET.get('edit_id', 0)
    exists = False

    if phone:
        exists = customer_table.objects.filter(phone=phone, status=1, is_active=1, branch_id=branch_id).exists()
        if edit_id:
            exists = exists and not customer_table.objects.filter(id=edit_id).exists()

    return JsonResponse({'exists': exists})



def customer_search(request):
    query = request.GET.get('query', '').strip()
    branch_id = request.session.get('branch_id')
    
    customers = customer_table.objects.filter(
        Q(name__icontains=query) | Q(phone__icontains=query),
        status=1,
        is_active=1,
        branch_id=branch_id
    )

    data = [
        {
            'id': c.id,
            'name': c.name,
            'phone': c.phone,
            'customer_type': c.customer_type
        }
        for c in customers
    ]
    return JsonResponse(data, safe=False)




