import json
from django.shortcuts import redirect, render, HttpResponse
from .models import Produit,Product,Bom,Bom_lines,Author
from django.views import View
from .forms import ProduitForm,ArticleFilterForm
from django.contrib import messages
import xmlrpc.client
from django.db.models import Sum
from collections import defaultdict
url = 'http://bms.insidjam.com'  # Odoo URL
db = 'BMS_PROD'  # Database name
username = 'T.Boualbani'  # Odoo login username
password = 'admin'  # Odoo login password
common = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/common')
uid = -1
models = {}
product_couvetutre = []
Stock_min = []
Articles = []
Articles_MP = []
# Define the object you want to interact with
Articles_semulation = []

boms = []
#print('MP=',Articles_MP)

# Create your views here.
result_prd = []



def index(request,*args,**kwargs):
    form = ArticleFilterForm(request.GET or None)
    result = []
    for item1 in Stock_min:
        for item2 in Articles:
            if item1['product_id'][0] == item2['id']:
                # Combine the dictionaries from both lists into one
                
                
                combined_item = {**item1, **item2,}
                combined_item['ecar'] = item2['virtual_available']-item1['product_min_qty']
                if item1['product_min_qty']==0:
                    combined_item['couvert'] ='Stock min non défini'
                else:
                    if combined_item['ecar']<0:
                        combined_item['couvert']=0
                    else:
                        combined_item['couvert'] = item2['virtual_available']/item1['product_min_qty']*100
                result.append(combined_item)
    global result_prd
    result_prd = result

    if form.is_valid():
        if form.cleaned_data['default_code']:            
            result = [art for art in result if form.cleaned_data['default_code'].lower() in art['default_code'].lower() or form.cleaned_data['default_code'].lower() in art['name'].lower()] 
        
        if form.cleaned_data['chiffre']:
            if form.cleaned_data['regle']:
                match form.cleaned_data['regle']:
                    case 'egal':                            
                        result = [art for art in result if art[form.cleaned_data['chiffre']] == form.cleaned_data['val']] 
                    case 'notegal': 
                        result = [art for art in result if art[form.cleaned_data['chiffre']] != form.cleaned_data['val']] 
                    case 'sup': 
                        result = [art for art in result if art[form.cleaned_data['chiffre']] > form.cleaned_data['val']] 
                    case 'inf': 
                        result = [art for art in result if art[form.cleaned_data['chiffre']] < form.cleaned_data['val']] 
                    case 'supegal': 
                        result = [art for art in result if art[form.cleaned_data['chiffre']] >= form.cleaned_data['val']] 
                    case _: 
                        result = [art for art in result if art[form.cleaned_data['chiffre']] <= form.cleaned_data['val']] 

    result = sorted(result,key=lambda art: art["default_code"])
    global product_couvetutre
    product_couvetutre = result

    context = {
        'produits' : result,
        'nom':'Produits de la boutique',
        'form': form
        }




    return render(request,'index.html',context)



result2 = []


def get_product(id_prd):
    art = [art for art in Articles_MP if id_prd == art['id']]
    return art



#print('name = ',get_product(32111)[0]['name'])

def get_bom_lines1(id_bom):
    fields6 = ['product_id', 'product_qty']
    bom_data = models.execute_kw(db, uid, password, 'mrp.bom', 'read', [id_bom], {'fields': ['bom_line_ids']})
    #print(f"id bom 1: {item['id_bom']}")
    bom_line_ids = bom_data['bom_line_ids'] if bom_data else []
    bom_lines = models.execute_kw(db, uid, password, 'mrp.bom.line', 'read', [bom_line_ids], {'fields': fields6})
    return bom_lines

def get_bom_prd_qty(id_bom):
   
    result = [bm for bm in boms if bm['id'] == id_bom]
    return result[0]['product_qty']


#print(f"id bom 2: {item['id_bom']}")

#print('bom_line = ',bom_lines)

for bom in boms:
    combined_item = {**bom,}
    combined_item['product_id'] = bom['product_id'][0]
    result2.append(combined_item)

selected_id =[]
def pdp(request):
    selected_prds =[]
    selected_boms =[]
    
    if request.method == "POST":
        global selected_id
        selected_id = request.POST.get('articles')
        print(f"PDP : {selected_id}")

    selected_prds = [art for art in product_couvetutre if str(art['id']) in selected_id] 
    selected_boms = [bom for bom in boms if str(bom['product_id'][0]) in selected_id]
    data = {
       'article_pdp':selected_prds,
       'boms':selected_boms

    }
   
    return render(request, 'pdp.html', data)

def Can_prd(request,*args,**kwargs):
    products = Product.objects.all()
    boms1 = Bom.objects.all()
    prds = []
    for prd in products:
        for bom in boms1:
            
            if bom.product_id.id== prd.id:
                bomlines = Bom_lines.objects.filter(bom_id=bom.id).values('product_id', 'product_qty')
                
                elem = []
                for bl in bomlines:
                    art = Product.objects.get(id=bl['product_id'])
                    qty = art.stock*bom.product_qty/bl['product_qty']
                    elem.append(qty)
               
                x= {'code':prd.code,'name':prd.name,'bom':bom.code,'qty':min(elem)}    
                prds.append(x)
    context = {
        'products' : prds,
        'nom':'Produits de la boutique',
        } 
    return render(request,'can_prd.html',context)


def Stock_Min1(request,*args,**kwargs):
    global result_prd
    stock_min = []
    Stock_mins = []
    for art_prd in  result_prd:
        boms_prd = [bom for bom in boms if bom['product_id'][0] == art_prd['id']]
        boms_cpts = []
        for bom_prd in boms_prd:
            bomlines_prd = get_bom_lines1(bom_prd['id'])
            for bom_line_prd in bomlines_prd:
                item = {'id':bom_line_prd['product_id'][0],'qty':bom_line_prd['product_qty'],'bom_qty':bom_prd['product_qty']}
                boms_cpts.append(item)
        #print('brut composant',len(boms_cpts))
        boms_cpts_clean = list({obj['id']: obj for obj in boms_cpts}.values())
        #print('cleand composant',len(boms_cpts_clean))
        for cpt in boms_cpts_clean:
            qty_cpt = cpt['qty']*art_prd['product_min_qty']/cpt['bom_qty']
            prd = get_product(cpt['id'])[0]
            composant = {'code':prd['default_code'],'name':prd['name'],'qty':qty_cpt}
            stock_min.append(composant)

    cmp_data_sum = {}

    for component in stock_min:
        cmp_id = component['code']
        cmp_qty = component['qty']
        
        # Si le cmp_id existe déjà, ajouter à la quantité existante
        if cmp_id in cmp_data_sum:
            cmp_data_sum[cmp_id]['cmp_qty'] += cmp_qty
        else:
            # Sinon, initialiser les informations pour ce cmp_id
            cmp_data_sum[cmp_id] = {
                'code': component['code'],
                'name': component['name'],
                'cmp_qty': cmp_qty
            }

        # Convertir le dictionnaire en liste d'objets (dictionnaires)
        Stock_mins = list(cmp_data_sum.values())
    
    #print('st min',Stock_mins)
    
    Stock_mins.sort(key=lambda ap: ap['code'])
    context = {
        'products' : Stock_mins,
        'nom':'Produits de la boutique',
        }
    
    

    return render(request,'stock_min.html',context)

def Stock_Min10(request,*args,**kwargs):
    products = Product.objects.all()
    boms = Bom.objects.all()
    boms_lines = Bom_lines.objects.all()
    stock_min = []
    Stock_mins = []
    for bom in boms:
        for bom_line in boms_lines:
            if bom.id == bom_line.bom_id.id:
                z= bom_line.product_qty*bom.product_id.stock_min/bom.product_qty
                x= {'id_article':bom_line.product_id.code,'name':bom_line.product_id.name,'qty':z}
                stock_min.append(x)
    
    cmp_data_sum = {}

    for component in stock_min:
        cmp_id = component['id_article']
        cmp_qty = component['qty']
        
        # Si le cmp_id existe déjà, ajouter à la quantité existante
        if cmp_id in cmp_data_sum:
            cmp_data_sum[cmp_id]['cmp_qty'] += cmp_qty
        else:
            # Sinon, initialiser les informations pour ce cmp_id
            cmp_data_sum[cmp_id] = {
                'code': component['id_article'],
                'name': component['name'],
                'cmp_qty': cmp_qty
            }

        # Convertir le dictionnaire en liste d'objets (dictionnaires)
        Stock_mins = list(cmp_data_sum.values())
        
    

    context = {
        'products' : Stock_mins,
        'nom':'Produits de la boutique',
        }
    
    

    return render(request,'stock_min.html',context)



stock_min_erp = []

def stock_min(request,*args,**kwargs):
    global result_prd
    for art_prd in  result_prd:
        boms_prd = [bom for bom in boms if bom['product_id'][0] == art_prd['id']]
        boms_cpts = []
        for bom_prd in boms_prd:
            elem = []
            bomlines_prd = get_bom_lines1(bom_prd['id'])
            for bom_line_prd in bomlines_prd:
                cpt_id_prd = bom_line_prd['product_id'][0]
                cpt_qty_prd = get_product(cpt_id_prd)[0]['virtual_available']
                item = {'id':bom_line_prd['product_id'][0],'qty':bom_line_prd['product_qty']}
                boms_cpts.append(item)

            boms_cpts_clean = list({obj['id']: obj for obj in boms_cpts}.values())


            """  qty = cpt_qty_prd*bom_prd['product_qty']/bom_line_prd['product_qty']
                elem.append(qty)
            x= {'code':art_prd['default_code'],'name':art_prd['name'],'stock_v':art_prd['virtual_available'],'ecart':art_prd['virtual_available']-art_prd['product_min_qty'],'bom':bom_prd['code'],'qty':min(elem)}    
            stock_min_erp.append(x)

    stock_min_erp.sort(key=lambda ap: (ap['code'],ap['bom'])) """
        
    

    context = {
        'products' : stock_min_erp,
        'nom':'Produits de la boutique',
        }
    
    return render(request,'stock_min.html',context)

def production(request):
    prds_prd = []
    global result_prd
    
    for art_prd in  result_prd:
        for bom_prd in boms:
            if art_prd['id']==bom_prd['product_id'][0]:
                elem = []
                bomlines_prd = get_bom_lines1(bom_prd['id'])
                for bom_line_prd in bomlines_prd:
                    cpt_id_prd = bom_line_prd['product_id'][0]
                    
                    cpt_qty_prd = get_product(cpt_id_prd)[0]['virtual_available']
                    
                    qty = cpt_qty_prd*bom_prd['product_qty']/bom_line_prd['product_qty']
                    elem.append(qty)
                x= {'code':art_prd['default_code'],'name':art_prd['name'],'stock_v':art_prd['virtual_available'],'ecart':art_prd['virtual_available']-art_prd['product_min_qty'],'bom':bom_prd['code'],'qty':min(elem)}    
                prds_prd.append(x)

    prds_prd.sort(key=lambda ap: (ap['code'],ap['bom']))            
    #print('production',prds_prd)
    data = {
        'products' : prds_prd,
        } 
   
    return render(request, 'can_prd.html', data)



pdp_items=[]

def login(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        global uid
        uid = common.authenticate(db, username, password, {})
        print(uid)
        if uid:
            print('log in ',username,' ',password)
            #login(request, user)  # Connecter l'utilisateur
            global Stock_min
            global models
            models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')
            Stock_min = models.execute_kw(
                db, uid, password,
                'stock.rule', 'search_read',  # Odoo model name and method
                [[('product_id.categ_id.parent_id.name', 'ilike', 'DISJONCTEUR'),('product_id.sale_ok', '=', True)]],  # Domain for filtering the records (empty list fetches all)
                {'fields': ['product_min_qty','product_id']}  # Fields you want to retrieve
            )
            global Articles
            Articles = models.execute_kw(
                db, uid, password,
                'product.product', 'search_read',  # Odoo model name and method
                [[('categ_id.parent_id.name', 'ilike', 'DISJONCTEUR'),('sale_ok', '=', True)]],  # Domain for filtering the records (empty list fetches all)
                {'fields': ['id','default_code','name','qty_available','virtual_available']}  # Fields you want to retrieve
            )

            #'bom_line_ids', '!=', False
            dom = [('bom_line_ids', '!=', False)]
            global Articles_MP
            Articles_MP = models.execute_kw(
                db, uid, password,
                'product.product', 'search_read',  # Odoo model name and method
                [dom],  # Domain for filtering the records (empty list fetches all)
                {'fields': ['id','default_code','name','qty_available','virtual_available']}  # Fields you want to retrieve
            )
            global Articles_semulation
            Articles_semulation = models.execute_kw(
                db, uid, password,
                'product.product', 'search_read',  # Odoo model name and method
                [[('categ_id.parent_id.name', 'ilike', 'DISJONCTEUR'),('sale_ok', '=', True)]],  # Domain for filtering the records (empty list fetches all)
                {'fields': ['id','default_code','name']}  # Fields you want to retrieve
            )

            domain1 = [('product_id.categ_id.parent_id.name', 'ilike', 'DISJONCTEUR')]

            # Define which fields you want to retrieve (optional)
            fields1 = [ 'id','code','product_qty', 'product_id']

            context1 = {'lang': 'en_US'}  # Example context
            global boms
            boms = models.execute_kw(db, uid, password, 'mrp.bom', 'search_read', [domain1], {'fields': fields1, 'context': context1})

            return redirect('produits:index')  # Rediriger vers la page d'accueil
        else:
            # Message d'erreur en cas d'identifiants incorrects
            messages.error(request, "Nom d'utilisateur ou mot de passe incorrect")
            
        
        # Authentifier l'utilisateur
        #user = authenticate(request, username=username, password=password)
        
        
    
    return render(request, 'login.html')

def appros(request):
    global db
    global uid
    global password
    global models
    appros_gl = []
    
    if request.method == "POST":
        global pdp_items
        pdp_items = json.loads(request.POST.get('my_list'))
    for item in pdp_items:
        bom_qty= get_bom_prd_qty(int(item['id_bom']))
        for line in get_bom_lines1(int(item['id_bom'])):            
            product_id = line['product_id'][0]  # Product name
            product_qty = line['product_qty']*float(item['qty'])/bom_qty
            x1 = {'product_id':product_id,'product_qty':product_qty}
            appros_gl.append(x1)

    print(appros_gl)

    #print('appros_group',appros_group)
    cmp_data_sum = {}

    for component in appros_gl:
        cmp_id = component['product_id']
        cmp_qty = component['product_qty']
        
        # Si le cmp_id existe déjà, ajouter à la quantité existante
        if cmp_id in cmp_data_sum:
            cmp_data_sum[cmp_id]['cmp_qty'] += cmp_qty
        else:
            # Sinon, initialiser les informations pour ce cmp_id
            # ['id','default_code','name','qty_available','virtual_available']
            #print('id cmp=',cmp_id)
            cmp_data_sum[cmp_id] = {
                'cmp_id': cmp_id,
                'code': get_product(cmp_id)[0]['default_code'],
                'name': get_product(cmp_id)[0]['name'],
                'qty_available': get_product(cmp_id)[0]['qty_available'],
                'virtual_available': get_product(cmp_id)[0]['virtual_available'],
                'cmp_qty': cmp_qty,
                'ecar':get_product(cmp_id)[0]['virtual_available']- cmp_qty
            }

    # Convertir le dictionnaire en liste d'objets (dictionnaires)
    result_list_appro = list(cmp_data_sum.values())
    result_list_appro.sort(key=lambda ap: ap['code'])
    
    data = {
      'appros':result_list_appro

    }
   
    return render(request, 'appros.html', data)

def get_appros(request):
    if request.method == 'POST':
        # Get the JSON list sent from AJAX
        my_list = json.loads(request.POST.get('my_list'))
        
        # Do something with the list (e.g., print it)
        print(f"PDP : {my_list}")
        boms_code = [bc["id"] for bc in my_list]
        print(f"boms code : {boms_code}")
        boms = Bom.objects.filter(id__in=boms_code)
        bom_lines = Bom_lines.objects.filter(bom_id__in=boms_code)
        print(f"boms : {boms}")
        for bom in boms:
            #x = [h for h in my_list if h["id"] == bom.id]
            x = next((b for b in my_list if b["id"] == str(bom.id)), None)
            print("hhhh",x['id'],"bom id",bom.id)

        appros = []

        for bom in boms:
             for bom_line in bom_lines:
                 if bom.id == bom_line.bom_id.id:
                     # x = list(filter(lambda y: y["id"] == bom.id, my_list))
                     x = next((b for b in my_list if b["id"] == str(bom.id)), None)
                     print("hhhh",x,"bom id",bom.id)
                     z = bom_line.product_qty/bom.product_qty*int(x['qty'])
                     appro ={'cmp_id':bom_line.product_id.id,'code':bom_line.product_id.code,'name':bom_line.product_id.name,'cmp_qty':z}
                     appros.append(appro)
        

        # print('appros',appros)
       
        # category_totals = defaultdict(int)
        # for appro in appros:
        #     category_totals[appro['cmp_id']] += appro['cmp_qty']
        
        cmp_data_sum = {}

        for component in appros:
            cmp_id = component['cmp_id']
            cmp_qty = component['cmp_qty']
            
            # Si le cmp_id existe déjà, ajouter à la quantité existante
            if cmp_id in cmp_data_sum:
                cmp_data_sum[cmp_id]['cmp_qty'] += cmp_qty
            else:
                # Sinon, initialiser les informations pour ce cmp_id
                cmp_data_sum[cmp_id] = {
                    'cmp_id': cmp_id,
                    'code': component['code'],
                    'name': component['name'],
                    'cmp_qty': cmp_qty
                }

        # Convertir le dictionnaire en liste d'objets (dictionnaires)
        result_list = list(cmp_data_sum.values())


        
        
        
        # print("appros :", category_totals)
        # Respond back to the front-end
        return JsonResponse(result_list, safe=False)
    
    return JsonResponse({'message': 'Invalid request'}, status=400)

def Test(request,*args,**kwargs):

    products = Product.objects.all()
    boms = Bom.objects.all()
    boms_lines = Bom_lines.objects.all()
    context = {
        'products' : products,
        'nom':'Produits de la boutique',
        'boms':boms,
        'boms_lines':boms_lines
        } 
    return render(request,'test.html',context)


def Can_prd(request,*args,**kwargs):
    products = Product.objects.all()
    boms1 = Bom.objects.all()
    prds = []
    for prd in products:
        for bom in boms1:
            
            if bom.product_id.id== prd.id:
                bomlines = Bom_lines.objects.filter(bom_id=bom.id).values('product_id', 'product_qty')
                
                elem = []
                for bl in bomlines:
                    art = Product.objects.get(id=bl['product_id'])
                    qty = art.stock*bom.product_qty/bl['product_qty']
                    elem.append(qty)
               
                x= {'code':prd.code,'name':prd.name,'bom':bom.code,'qty':min(elem)}    
                prds.append(x)
    context = {
        'products' : prds,
        'nom':'Produits de la boutique',
        } 
    return render(request,'can_prd.html',context)






def select_author_book(request):
    authors = Author.objects.all()
    return render(request, 'select_author_book.html', {'authors': authors})

# class CreatProduct(View):
#     def get(self, request,*args,**kwargs):
#         return render(request,'produits/create_product.html')
    
#     def post(self, request,*args,**kwargs ):
#         try:

#             nom = request.POST.get('nom')
#             description = request.POST.get('description')
#             prix = request.POST.get('prix')
#             image = request.FILES.get('image')
        

#             produit = Produit.objects.create(nom=nom,description=description,prix= prix,image=image)
            
#             if produit:
#                 return HttpResponse('Produit enregistré avec succès')
#         except Exception as e:
#             return HttpResponse('Erreur lors l\'enregisterement du produit')


class CreatProduct(View):
    def get(self, request,*args,**kwargs):
         form = ProduitForm()
         return render(request,'produits/create_product.html',{'form':form})
     

    def post(self, request,*args,**kwargs ):
        form = ProduitForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            messages.success(request,'Produit enregistré avec succès')
            return redirect('produits:index')
        else:
            messages.error(request,'Erreur lors de l\'enrigestrement')
            return render(request,'produits/create_product.html',{'form':form})






from django.http import JsonResponse
from .models import Book

def get_books(request):
    author_id = request.GET.get('author_id')
    books = Book.objects.filter(author_id=author_id).values('id', 'title')
    return JsonResponse(list(books), safe=False)


def get_boms(request):
    product_id = request.GET.get('product_id')
    boms = Bom.objects.filter(product_id=product_id).values('id', 'code')
    return JsonResponse(list(boms), safe=False)

def get_bom_qty(request):
    id = request.GET.get('id')
    bom = Bom.objects.filter(id=id).values('id','product_qty')
    return JsonResponse(list(bom), safe=False)

    


def get_bom_lines(request):
    bom_id = request.GET.get('bom_id')
    bom_lines = Bom_lines.objects.filter(bom_id=bom_id).values('product_id', 'product_qty')
    return JsonResponse(list(bom_lines), safe=False)

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def get_appro(request):
    x = json.loads(request.GET.get('list_products'))
    #appro = list(x)
    f"Liste reçue : {x}"
    #bom_lines = Bom_lines.objects.filter(bom_id=bom_id).values('product_id', 'product_qty')
    return JsonResponse(list(x), safe=False)



def process_list(request):
    if request.method == 'POST':
        # Get the JSON list sent from AJAX
        my_list = json.loads(request.POST.get('my_list'))
        
        # Do something with the list (e.g., print it)
        print(f"Liste reçue : {my_list}")
        

        
        # Respond back to the front-end
        return JsonResponse(my_list, safe=False)
    
    return JsonResponse({'message': 'Invalid request'}, status=400)

def get_product_suggestions(request):
    if 'term' in request.GET:
        # Exemple : Simuler une liste de produits
        products = ['Produit 1', 'Produit 2', 'Produit 3', 'Produit 4', 'Produit 5']
        val = request.GET['term']
        products = Product.objects.all().values('code','name')
       
        # Filtrer les produits en fonction de la saisie de l'utilisateur
        suggestions = ['['+product['code']+'] '+product['name'] for product in products if request.GET['term'].lower() in product['code'].lower()]
        
        # Retourner les suggestions sous forme de JSON
        return JsonResponse(suggestions, safe=False)