from django.shortcuts import render
import json
from django.conf import settings
from django.shortcuts import render
from common.models import *
from masters.models import *
from masters.forms import *
from privilege.models 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,JsonResponse,HttpResponseRedirect
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.db.models.functions import Cast

from scheme.models import *


#```````````````````````````````````````````````````````````**ITEMS**````````````````````````````````````````````````````````````````````````````````

def ajax_load_colors(request):
    if request.method == 'POST':
        brand_id = request.POST.get('brand_id')
        model_id = request.POST.get('model_id')
        variant_id = request.POST.get('variant_id')

        variants = color_table.objects.filter(
            brand_id=brand_id,
            model_id=model_id,
            variant_id=variant_id,
            status=1
        ).values('id', 'name')

        return JsonResponse(list(variants), safe=False)

    return JsonResponse([], safe=False)
def items(request):
    if 'user_id' in request.session:
        user_type = request.session.get('user_type')
        if user_type == 'admin':
            cmpy = select_row(company_table, {'id':1})
            category = selectList(category_table, order_by='name')
            sub_category = selectList(sub_category_table, order_by='name')
            uom = selectList(uom_table, order_by='name')
            variant = selectList(variant_table, order_by='name')
            model = selectList(model_table, order_by='name')
            tax = selectList(tax_table, order_by='name')
            brand = selectList(brand_table, order_by='name')
            color = selectList(color_table, order_by='name')
            return render(request, 'items.html', {'company': cmpy,'category':category,'sub_category':sub_category,'uom':uom,'brand':brand,'tax':tax,'variant':variant, 'model':model,'color':color})
        else:
            return HttpResponseRedirect("/")
    else:
        return HttpResponseRedirect("/")



def load_subcategories(request):
    if 'user_id' in request.session:
        category_id = request.GET.get('category_id')
        subcategories = selectList(sub_category_table, {'category_id' : category_id, 'status': 1}, order_by='name', fields=['id', 'name'])
        return JsonResponse({'subcategories': list(subcategories)})
    else:
        return JsonResponse({'message': 'Unauthorized access'})




def load_device_model(request):
    if 'user_id' in request.session:
        category_id = request.GET.get('device_id')
        subcategories = selectList(model_table, {'device_id' : category_id, 'status': 1}, order_by='name', fields=['id', 'name'])
        return JsonResponse({'subcategories': list(subcategories)})
    else:
        return JsonResponse({'message': 'Unauthorized access'})

from django.http import JsonResponse
from django.db.models import Q

def check_ean_exists(request):
    if 'user_id' not in request.session:
        return JsonResponse({'message': 'Unauthorized access'}, status=401)

    ean = request.POST.get('ean', '').strip()
    brand_id = request.POST.get('brand_id')
    model_id = request.POST.get('model_id')
    variant_id = request.POST.get('variant_id')
    color_id = request.POST.get('color_id')
    item_id = request.POST.get('data_id')

    if not ean:
        return JsonResponse({'exists': False})

    query = Q(status=1, ean__iexact=ean)

    if brand_id:
        query &= Q(brand_id=brand_id)
    if model_id:
        query &= Q(model_id=model_id)
    if variant_id:
        query &= Q(variant_id=variant_id)
    if color_id:
        query &= Q(color_id=color_id)

    qs = item_table.objects.filter(query)

    if item_id:
        qs = qs.exclude(id=item_id)

    if qs.exists():
        return JsonResponse({
            'exists': True,
            'message': 'EAN already exists'
        })

    return JsonResponse({'exists': False})



def generate_next_sku():
    from django.db.models import Max

    latest_sku_entry = (
        item_table.objects
        .filter(sku__regex=r'^\d+$')  # only numeric SKUs
        .aggregate(max_sku=Max(Cast('sku', models.IntegerField())))
    )
    last_sku = latest_sku_entry['max_sku'] or 0
    next_sku = str(last_sku + 1)

    while item_table.objects.filter(sku=next_sku).exists():
        last_sku += 1
        next_sku = str(last_sku + 1)

    return next_sku



def item_add(request):
    if request.method == 'POST':
        try:
            user_id = request.session.get('user_id')           
            company_id = request.session.get('company_id')           
            form = ItemForm(request.POST, request.FILES)
            role_id = request.session.get('role_id')
            item_type = 'accessories'
            if item_type == 'accessories':
                has_access, error_message = check_user_access(role_id, 'items', "create")
                if not has_access:
                    return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to add Items details'})
                
            
            if form.is_valid():
                category = form.save(commit=False)
                category_id = request.POST.get('category_id') or 0
                sub_id = request.POST.get('sub_category_id') or 0
                brand_id = request.POST.get('brand_id') or 0
                variant_id = request.POST.get('variant_id') or 0
                model_id = request.POST.get('model_id') or 0
                uom_id = request.POST.get('uom_id') or 0
                color_id = request.POST.get('color_id') or 0
                hsn_code = request.POST.get('hsn_code') or 0
                ean_number = request.POST.get('ean_number') or 0
                cell_life = request.POST.get('cell_life') or 0
                image = request.FILES.get('image') 
                tax_id = request.POST.get('tax_id') or 0
                fsp_amount = request.POST.get('fsp_amount') or 0
                wsp_amount = request.POST.get('wsp_amount') or 0
               
                sub_name = getItemNameById(sub_category_table, sub_id)
                brand_name = getItemNameById(brand_table, brand_id)
                model_name = getItemNameById(model_table, model_id)
                variant_name = getItemNameById(variant_table, variant_id)
                color_name = getItemNameById(color_table, color_id) or ""
                sku_parts = [sub_name, brand_name, model_name, variant_name, color_name]
                sku_text = " - ".join(filter(None, sku_parts))

                db = request.POST.get('db_price') or 0
                wsp = request.POST.get('wsp') or 0
                fsp = request.POST.get('fsp') 
                mop = request.POST.get('mop_price') or 0
                bop = request.POST.get('bop_price') or 0
                mrp = request.POST.get('mrp') or 0
                

                description = request.POST.get('description')

                
                sku = generate_next_sku()                           
                
                if item_table.objects.filter(
                    # category_id=category_id,
                    # sub_category_id=sub_id,
                    # brand_id=brand_id,
                    # model_id=model_id,
                    # variant_id=variant_id,
                    # color_id=color_id,
                    status=1,
                    ean=ean_number
                ).exists():
                    return JsonResponse({
                        'message': 'field_error',
                        'field': 'name',
                        'error': f'Item with EAN Number "{ean_number}" already exists'
                    }, status=400)
                
                category.category_id =category_id
                category.sku_text = sku_text
                category.item_type= item_type
                category.company_id = company_id
                category.brand_id = brand_id
                category.sub_category_id = sub_id
                category.variant_id = variant_id
                category.model_id = model_id
                category.tax_id = tax_id
                category.uom_id = uom_id
                category.color_id = color_id
                category.hsn_code = hsn_code
                category.sku = sku
                category.ean = ean_number
                category.image = image
                category.mrp = mrp
                category.db_price = db
                category.wholesale_price = wsp
                category.wholesale_amount = wsp_amount
                category.franchise_price = fsp
                category.franchise_amount = fsp_amount
                category.mop_price = mop
                category.bop_price = bop
                category.cell_life = cell_life
                category.description = description
                category.is_active = 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)



from django.db import connection
from django.http import JsonResponse
import os
from django.conf import settings

def item_view(request):
    role_id = request.session.get('role_id')    
    category_id = request.POST.get('category_id')
    subcategory_id = request.POST.get('subcategory')
    brand_id = request.POST.get('brand_id')
    keyword = request.POST.get('keyword_search', '').strip()
    search_type = request.POST.get('search_type')
    
    has_access, error_message = check_user_access(role_id, 'items', "read")
    if not has_access:
        return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to view Items details'})
                
    # Permission Check
 

    

    # Prepare WHERE clauses
    filters = ["i.status = 1"]
    params = []

    if category_id:
        filters.append("i.category_id = %s")
        params.append(category_id)
    if subcategory_id:
        filters.append("i.sub_category_id = %s")
        params.append(subcategory_id)
    if brand_id:
        filters.append("i.brand_id = %s")
        params.append(brand_id)
    if keyword:
        if search_type == 'sku':
            filters.append("i.sku LIKE %s")
        else:
            filters.append("i.name LIKE %s")
        params.append(f"%{keyword}%")

    where_clause = " AND ".join(filters)

    query = f"""
        SELECT 
            i.id,  i.sku, i.description, i.db_price, i.wholesale_price, i.franchise_price,i.mop_price,i.bop_price,i.mrp,i.ean,
            i.image, i.category_id, i.sub_category_id, i.brand_id, i.uom_id, i.tax_id,i.hsn_code,
            i.is_active,
            c.name as category_name,
            sc.name as sub_category_name,
            b.name as brand_name,
            tx.name as tax_name,
            u.name as uom_name,
            co.name as color_name,
            v.name as variant_name,
            dm.name as model_name
        FROM m_items i
        LEFT JOIN category c ON i.category_id = c.id
        LEFT JOIN sub_category sc ON i.sub_category_id = sc.id
        LEFT JOIN brands b ON i.brand_id = b.id
        LEFT JOIN uom u ON i.uom_id = u.id
        LEFT JOIN tax tx ON i.tax_id = tx.id
        LEFT JOIN variants v ON i.variant_id = v.id
        LEFT JOIN colors co ON i.color_id = co.id
        LEFT JOIN model dm ON i.model_id = dm.id
        WHERE {where_clause}
        ORDER BY i.id DESC
    """

    with connection.cursor() as cursor:
        cursor.execute(query, params)
        rows = cursor.fetchall()
        columns = [col[0] for col in cursor.description]

    # Convert rows to dicts
    items = [dict(zip(columns, row)) for row in rows]

    formatted = []
    for idx, item in enumerate(items):
        image_url = f"/media/{item['image']}" if item['image'] else None
        image_path = os.path.join(settings.MEDIA_ROOT, str(item['image'])) if item['image'] else None

        # Base action buttons
        action_buttons = f'''
            <button type="button" onclick="edit_data('{item['id']}')" class="btn btn-outline-success btn-xs p-1" title="Edit Item">
                <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 Item">
                <i class="fas fa-trash-alt"></i>
            </button>  
            <button type="button" onclick="duplicate_data('{item['id']}')" class="btn btn-outline-primary btn-xs p-1" title="Duplicate Item">
                <i class="fas fa-copy"></i>
            </button>            
        '''       

        formatted.append({
            'id': idx + 1,
            'action': action_buttons,
            'category': item['category_name'] or '-',
            'sub_category': item['sub_category_name'] or '-',
            'brand': item['brand_name'] or '-',
            'variant': item['variant_name'] or '-',
            'model': item['model_name'] or '-',
            'color': item['color_name'] or '-',
            'tax': item['tax_name'] or '-',
            'uom': item['uom_name'] or '-',
            'hsn_code': item.get('hsn_code', '-') or '-',
            'ean_number': item.get('ean', '-') or '-',
            'cell_life': item.get('cell_life', '-') or '-',
            'description': item['description'] or '-',
            'db': format_amount(item['db_price']) or '-',
            'wsp': item['wholesale_price'] or '-',
            'fsp': item['franchise_price'] or '-',
            'mop': format_amount(item['mop_price']) or '-',
            'bop': format_amount(item['bop_price']) or '-',
            'mrp': format_amount(item['mrp']) or '-',
            'image': (
                f'<img src="{image_url}" alt="Image" style="width: 45px; height: 45px; border-radius: 10px; background: #f3f3f3;" />'
                if image_path and os.path.exists(image_path)
                else '<div style="width: 50px; height: 50px; background: #f3f3f3; border-radius: 5px;"></div>'
            ),
            
            'status': (
                '<span class="badge text-bg-success">Active</span>'
                if item.get('is_active') else
                '<span class="badge text-bg-danger">Inactive</span>'
            )
        })

    return JsonResponse({'data': formatted})


from django.views.decorators.http import require_POST
from django.db import transaction

def make_default_item(request):
    item_id = request.POST.get('id')

    if not item_id:
        return JsonResponse({'status': 'error', 'message': 'Invalid item ID'})

    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT name, has_stock, item_type FROM m_items WHERE id = %s", [item_id])
            row = cursor.fetchone()
            if not row:
                return JsonResponse({'status': 'error', 'message': 'Item not found'})

            name, has_stock, item_type = row

            if item_type != "service":
                return JsonResponse({'status': 'error', 'message': 'Only service items can be default'})
            if has_stock != 0:
                return JsonResponse({'status': 'error', 'message': f'Cannot set {name} as default (stock available)'})

            # Update inside transaction
            with transaction.atomic():
                cursor.execute("UPDATE m_items SET is_default = 0 WHERE item_type = 'service'")

                cursor.execute("UPDATE m_items SET is_default = 1 WHERE id = %s", [item_id])

        return JsonResponse({'message': 'yes'})

    except Exception as e:
        return JsonResponse({'status': 'error', 'message': str(e)})


from django.utils import timezone
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
def item_edit(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        data = item_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])



def item_update(request):
    if request.method == "POST":
        try:
            category_id = request.POST.get('id')
            category = item_table.objects.get(id=category_id)
            form = ItemForm(request.POST, request.FILES, instance=category)
            role_id = request.session.get('role_id')
            
            has_access, error_message = check_user_access(role_id, 'items', "update")
            if not has_access:                        
                return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to update Items details'})
            
            if form.is_valid():
                updated_category = form.save(commit=False)
                
                category_id = request.POST.get('category_id') or 0
                sub_id = request.POST.get('sub_category_id') or 0
                brand_id = request.POST.get('brand_id') or 0
                variant_id = request.POST.get('variant_id') or 0
                uom_id = request.POST.get('uom_id') or 0
                tax_id = request.POST.get('tax_id') or 0                
                model_id = request.POST.get('model_id') or 0
                color_id = request.POST.get('color_id') or 0
                hsn_code = request.POST.get('hsn_code') or 0
                ean_number = request.POST.get('ean_number') or 0
                cell_life = request.POST.get('cell_life') or 0
                fsp_amount = request.POST.get('fsp_amount') or 0
                wsp_amount = request.POST.get('wsp_amount') or 0
                
                image = request.FILES.get('image') 
                description = request.POST.get('description')
                is_active = request.POST.get('is_active')
                db = request.POST.get('db_price') or 0
                wsp = request.POST.get('wsp') or 0
                fsp = request.POST.get('fsp') 
                mop = request.POST.get('mop_price') or 0
                bop = request.POST.get('bop_price') or 0
                mrp = request.POST.get('mrp') or 0
                scheme_id = request.POST.get('scheme_id') or 0
                sub_name = getItemNameById(sub_category_table, sub_id)
                brand_name = getItemNameById(brand_table, brand_id)
                model_name = getItemNameById(model_table, model_id)
                variant_name = getItemNameById(variant_table, variant_id)
                color_name = getItemNameById(color_table, color_id) or ""
                sku_parts = [sub_name, brand_name, model_name, variant_name, color_name]
                sku_text = " - ".join(filter(None, sku_parts))

                updated_category.sku_text = sku_text
                updated_category.category_id = category_id     
                updated_category.variant_id = variant_id     
                updated_category.color_id = color_id       
                updated_category.brand_id = brand_id            
                updated_category.sub_category_id = sub_id            
                updated_category.uom_id = uom_id            
                updated_category.model_id = model_id            
                updated_category.hsn_code = hsn_code            
                updated_category.ean = ean_number            
                updated_category.cell_life = cell_life  
                updated_category.tax_id = tax_id
                updated_category.db_price = db
                updated_category.franchise_price = fsp  
                updated_category.wholesale_price = wsp  
                updated_category.bop_price = bop  
                updated_category.mop_price = mop  
                updated_category.franchise_amount = fsp_amount
                updated_category.wholesale_amount = wsp_amount
                updated_category.mrp = mrp  
                if image:
                    updated_category.image = image           
                    
                updated_category.is_active = is_active            
                updated_category.description = description
                updated_category.updated_by = request.session.get('user_id')
                updated_category.updated_on = format_datetime(date_time)

                # Duplicate name check
                if item_table.objects.filter(
                    category_id=category_id,
                    sub_category_id=sub_id,
                    brand_id=brand_id,
                    model_id=model_id,
                    variant_id=variant_id,
                    color_id=color_id,
                    status=1,
                    ean=ean_number
                ).exclude(id=category.id).exists():

                    return JsonResponse({
                        'message': 'field_error',
                        'field': 'name',
                        'error': f'Item with EAN "{ean_number}" already exists for the selected category, subcategory, and brand.'
                    }, status=400)
                updated_category.save()
                
                updated_category.updated_on = format_datetime(date_time)

              
                if scheme_id != 0:
                    scheme  = item_scheme_table.objects.get(id=scheme_id, status=1, scheme_type= 'price_drop')
                    scheme.fsp = fsp
                    scheme.wsp = wsp
                    scheme.mop = mop
                    scheme.bop = bop
                    scheme.save()
               
                # Action buttons
                edit_button = f"<button type='button' onclick='edit_data({updated_category.id})' class='btn btn-outline-success btn-xs p-1' title='Edit Item'><i class='fas fa-edit'></i></button>"
                delete_button = f"<button type='button' onclick='delete_data({updated_category.id})' class='btn btn-outline-danger btn-xs p-1' title='Delete Item'><i class='fas fa-trash'></i></button>"
                duplicate_button = f"<button type='button' onclick='duplicate_data({updated_category.id})' class='btn btn-outline-primary btn-xs p-1' title='Duplicate Item'><i class='fas fa-copy'></i></button>"
                action_buttons = [edit_button, delete_button, duplicate_button]

                # Image path
                image_url = updated_category.image.url if updated_category.image else None
                image_path = os.path.join(settings.MEDIA_ROOT, str(updated_category.image)) if updated_category.image else None

                updated_row = {
                    'action': ' '.join(action_buttons),
                    'category': getItemNameById(category_table, updated_category.category_id),
                    'sub_category': getItemNameById(sub_category_table, updated_category.sub_category_id),
                    'brand': getItemNameById(brand_table, updated_category.brand_id),
                    'variant': getItemNameById(variant_table, updated_category.variant_id),
                    'model': getItemNameById(model_table, updated_category.model_id),
                    'color': getItemNameById(color_table, updated_category.color_id),
                    'tax': getItemNameById(tax_table, updated_category.tax_id),
                    'uom': getItemNameById(uom_table, updated_category.uom_id),
                    'hsn_code': updated_category.hsn_code,
                    'ean_number': updated_category.ean,
                    'cell_life': updated_category.cell_life,
                    'image': (
                        f'<img src="{image_url}" alt="Image" style="width: 45px; height: 45px; border-radius: 10px; background: #f3f3f3;" />'
                        if image_path and os.path.exists(image_path)
                        else '<div style="width: 50px; height: 50px; background: #f3f3f3; border-radius: 5px;"></div>'
                    ),
                    'db': format_amount(updated_category.db_price),
                    'wsp': format_amount(updated_category.wholesale_price),
                    'fsp': format_amount(updated_category.franchise_price),
                    'mop': format_amount(updated_category.mop_price),
                    'bop': format_amount(updated_category.bop_price),
                    'mrp': format_amount(updated_category.mrp),
                    'description': updated_category.description,
                   'status': (
                    '<span class="badge text-bg-success">Active</span>'
                        if updated_category.is_active else
                        '<span class="badge text-bg-danger">Inactive</span>'
                    ),
                    'item_id': updated_category.id
                }
                return JsonResponse({'message': 'success', 'updated_row': updated_row})

            else:
                errors = form.errors.as_json()
                return JsonResponse({'message': 'error', 'errors': errors})
        except Exception as e:
            return JsonResponse({'message': 'exception', 'error': str(e)})



def item_delete(request):
    if request.method == 'POST':
        data_id = request.POST.get('id')   
        role_id = request.session.get('role_id')
        item = select_row(item_table,{'id':data_id})
        has_access, error_message = check_user_access(role_id, 'items', "delete")
        
        if not has_access:
            return JsonResponse({'message': 'warning', 'error_message': 'You do not have permission to delete Items details'})
                    
        try:
            updated = item_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'})


# **********ITEM DUPLICATE**********
def item_duplicate(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest' and request.method == "POST":
        data = item_table.objects.filter(id=request.POST.get('id'))    
    return JsonResponse(data.values()[0])

