from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
import json
from django.shortcuts import redirect, render, HttpResponse

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
from .models import Category_user_set
url = 'https://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 = []


# 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']:
                prd_id = item2['id']
                prd_code = item2['default_code']
                prd_name = item2['name']
                prd_avb_st = item2['qty_available']
                prd_vrt_st = item2['virtual_available']
                prd_min = item1['product_min_qty']
                prd_ecart = prd_vrt_st-prd_min
                if prd_min==0:
                    prd_couvrt = 0
                else:
                    if prd_ecart <0:
                        prd_couvrt = 0
                    else:
                        prd_couvrt = prd_vrt_st/prd_min*100

                combined_item = {'id':prd_id,'default_code':prd_code,'name':prd_name,'qty_available':prd_avb_st,'virtual_available':prd_vrt_st,'product_min_qty':prd_min,'ecar':prd_ecart,'couvert':prd_couvrt}
                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):
    global Articles_MP
    art = [art for art in Articles_MP if id_prd == art['id']]
    return art

cat_imporation = ""
cat_imporation_id = 0

def get_cat_pf(user_id):
    cat = Category_user_set.objects.get(user=user_id)
    return cat.cat_parent_pf
def get_cat_mp(user_id):
    cat = Category_user_set.objects.get(user=user_id)
    return cat.cat_parent_mp
    
def get_cat_impo(user_id):
    cat = Category_user_set.objects.get(user=user_id)
    return cat.cat_imporation

def get_user_cats(user_id):
    cat = Category_user_set.objects.get(user=user_id)
    return cat

def get_bom_lines(id_bom):
    fields6 = ['product_id', 'product_qty']
    bom_data = models.execute_kw(db, uid, password, 'mrp.bom', 'read', [id_bom], {'fields': ['bom_line_ids']})
    
    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_lines1(id_bom,gamme):
    fields6 = ['product_id', 'product_qty']
    bom_data = models.execute_kw(db, uid, password, 'mrp.bom', 'read', [id_bom], {'fields': ['bom_line_ids']})
    dom = [('product_id.categ_id', '=', gamme)]
    bom_line_ids = bom_data['bom_line_ids'] if bom_data else []
    dom99 = [bom_line_ids]
    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):
    global boms
    result = [bm for bm in boms if bm['id'] == id_bom]
    return result[0]['product_qty']






selected_id =[]

def pdp(request):
    form = ArticleFilterForm(request.GET or None)
    selected_prds =[]
    selected_boms =[]
    
    if request.method == "POST":
        global selected_id
        selected_id = request.POST.get('articles')
       

    selected_prds = [art for art in product_couvetutre if str(art['id']) in selected_id] 
    global boms
    selected_boms = [bom for bom in boms if str(bom['product_id'][0]) in selected_id]
    list_boms = []
    for bom in selected_boms:
        combined_item = {**bom,}
        cp = can_product(request,bom['id'])
        combined_item['can_prd']=cp
        list_boms.append(combined_item)
    
    pdp_list = []
    for sp in selected_prds:
        for bm in list_boms:
             if sp['id']==bm['product_id'][0]:
                combined_item = {**sp,**bm,}
                #print('car prd',bm['can_prd'],' ecar prd',sp['ecar'])
                combined_item['ecart_pdp']=bm['can_prd']-abs(sp['ecar'])
                pdp_list.append(combined_item)

    #print('pdp list=',pdp_list)
    
    if form.is_valid():
        if form.cleaned_data['default_code']:
            pdp_list = [art for art in pdp_list 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['can_prd']:
            pdp_list = [art for art in pdp_list if art['can_prd']>0] 
    pdp_list.sort(key=lambda ap:(ap['default_code'],ap['code']))
    data = {
       'article_pdp':pdp_list,
       'boms':list_boms
    }
   
    return render(request, 'pdp.html', data)




def Stock_Min(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_lines(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)
       
        boms_cpts_clean = list({obj['id']: obj for obj in boms_cpts}.values())
        
        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())
    
   
    
    Stock_mins.sort(key=lambda ap: ap['code'])
    context = {
        'products' : Stock_mins,
        'nom':'Produits de la boutique',
        }
    
    

    return render(request,'stock_min.html',context)





stock_min_erp = []


def can_product(request,bom_id):
    form = ArticleFilterForm(request.GET or None)
    elem = []
    global boms
    bom = [bm for bm in boms if bom_id == bm['id']]
    bomlines_prd = get_bom_lines(bom_id)
    if form.is_valid():
        if form.cleaned_data['gamme']:
            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']
                cate_ids = get_product(cpt_id_prd)[0]['categ_id']
                global cat_imporation_id
                print('gamme',cate_ids[0],' cat_imporation_id',cat_imporation_id)
                if cate_ids[0]==cat_imporation_id:
                    qty = cpt_qty_prd*bom[0]['product_qty']/bom_line_prd['product_qty']
                    elem.append(qty)
        else:
            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[0]['product_qty']/bom_line_prd['product_qty']
                elem.append(qty)
    else:
        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[0]['product_qty']/bom_line_prd['product_qty']
            elem.append(qty)
    
    return min(elem)


def production(request):
    form = ArticleFilterForm(request.GET or None)
    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_lines(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']
                    if form.is_valid():
                        if form.cleaned_data['gamme']:
                            global uid
                            
                            cate_ids = get_product(cpt_id_prd)[0]['categ_id']
                            global cat_imporation_id
                            print('gamme',cate_ids[0],' cat_imporation_id',cat_imporation_id)
                            if cate_ids[0]==cat_imporation_id:
                                qty = cpt_qty_prd*bom_prd['product_qty']/bom_line_prd['product_qty']
                                elem.append(qty)
                    else:
                        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']))            
    
    data = {
        'products' : prds_prd,
        } 
   
    return render(request, 'can_prd.html', data)



pdp_items=[]

def refresh_data(request):
    
    global uid
    uid = common.authenticate(db, username, password, {})
            
            
            

    global models
    global categories
    models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')
    champs = ['id','name','parent_id']
    context1 = {'lang': 'en_US'}
    categories = models.execute_kw(db, uid, password, 'product.category', 'search_read', [], {'fields': champs, 'context': context1})
    
    global cat_imporation
    print('user id=',uid)
    cat_imporation = get_cat_impo(uid)
    print('cat_imporation id=',cat_imporation)
    global cat_imporation_id
    cat_imporation_id = get_cat_impo_id(cat_imporation)
    print('cat_imporation_id id=',cat_imporation_id)
    global Stock_min
    

    



    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', get_cat_pf(uid)),('product_id.sale_ok', '=', True),('product_min_qty', '>', 0)]],  # 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', get_cat_pf(uid)),('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
    )
    
    print(get_cat_mp(uid))
    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','categ_id']}  # Fields you want to retrieve
    )
    
    domain1 = [('product_id.categ_id.parent_id.name', 'ilike', get_cat_pf(uid))]

    
    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})
    global result2

    

    for bom in boms:
        combined_item = {**bom,}
        combined_item['product_id'] = bom['product_id'][0]
        result2.append(combined_item)
    return redirect('produits:index')


def get_category_pf(cat_name):
    catrgory = [cat for cat in categories if cat_name == cat['name']]
    return catrgory[0]['id']

def get_category_mp(cat_name):
    catrgory = [cat for cat in categories if cat_name == cat['name']]
    return catrgory[0]['id']

def get_cat_impo_id(cat_name):
    global categories
    catrgory = [cat for cat in categories if cat_name == cat['name']]
    return catrgory[0]['id']

categories = []

def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        
        user = authenticate(request, username=username, password=password)
        if user is not None:
            
            login(request, user)  # Connecter l'utilisateur
            global uid
            uid = common.authenticate(db, username, password, {})
            
            
            

            global models
            global categories
            models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')
            champs = ['id','name','parent_id']
            context1 = {'lang': 'en_US'}
            categories = models.execute_kw(db, uid, password, 'product.category', 'search_read', [], {'fields': champs, 'context': context1})
            
            global cat_imporation
            print('user id=',uid)
            cat_imporation = get_cat_impo(uid)
            print('cat_imporation id=',cat_imporation)
            global cat_imporation_id
            cat_imporation_id = get_cat_impo_id(cat_imporation)
            print('cat_imporation_id id=',cat_imporation_id)
            global Stock_min
            

            



            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', get_cat_pf(uid)),('product_id.sale_ok', '=', True),('product_min_qty', '>', 0)]],  # 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', get_cat_pf(uid)),('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
            )
            
            print(get_cat_mp(uid))
            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','categ_id']}  # Fields you want to retrieve
            )
            
            domain1 = [('product_id.categ_id.parent_id.name', 'ilike', get_cat_pf(uid))]

           
            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})
            global result2

            

            for bom in boms:
                combined_item = {**bom,}
                combined_item['product_id'] = bom['product_id'][0]
                result2.append(combined_item)
            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_lines(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)

    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:
            cmp_data_sum[cmp_id] = {
                'cmp_id': cmp_id,
                'cmp_qty': cmp_qty
            }

    # Convertir le dictionnaire en liste d'objets (dictionnaires)
    result_list_appro = list(cmp_data_sum.values())
    result_list_appros = []
    for rst in result_list_appro:
        app = {
                'code': get_product(rst['cmp_id'])[0]['default_code'],
                'name': get_product(rst['cmp_id'])[0]['name'],
                'qty_available': get_product(rst['cmp_id'])[0]['qty_available'],
                'virtual_available': get_product(rst['cmp_id'])[0]['virtual_available'],
                'cmp_qty':rst['cmp_qty'],
                'ecar':get_product(rst['cmp_id'])[0]['virtual_available']- rst['cmp_qty']
            
            }

        result_list_appros.append(app)
    
    result_list_appros.sort(key=lambda ap: ap['code'])
    
    data = {
      'appros':result_list_appros

    }
   
    return render(request, 'appros.html', data)

