from django.shortcuts import render

# Create your views here.
from inventory.views import LabelQuery
import redis
from django.http import JsonResponse
import datetime
from utils.views import time_key_check
from django.conf import settings
from django.db import connection
from django.utils.translation import gettext_lazy as _


from inventory.views import sK
#sK = 'fgfdvgu$#&3t@j'



rd = redis.StrictRedis(connection_pool=settings.LABEL_CHECK_POOL)   # redis 连接池
ex=12*3600                                                          # redis 默认过期时间 12小时

def bottlecap_check(enterprise_id, product_id, label_pk_id, bottle=None):
    # 瓶盖绑定是完整 
    """
    瓶盖绑定是完整    
    :param enterprise_id:企业id
    :param product_id: 产品id
    :param label_pk_id: 主箱标id
    :param : bottle 瓶标号码
    """
    cid=str(enterprise_id)
    pk=str(label_pk_id)
    e=''   
    if cid=='1':
        # 酒鬼酒  
        s="select bottle_cnt from z_bottle_cap_product where product_id="+str(product_id)
        if bottle:
            # 检查当前瓶
            sb="select (select count(*) from z_bottlecap_binding where bottle='"+bottle+"')"+\
                " + (select count(*) from label.bottlecap where bottle='"+bottle+"')"
        else:
            # 检查箱标
            sb="select (select count(*) from z_bottlecap_binding where label_pk_id="+pk+")"+\
                " + (select count(*) from label.bottlecap where label_pk_id="+pk+")"
    else:                
        s="select cap_cnt from mes_bottlecapproduct where product_id="+str(product_id)
        if bottle:
            sb="select count(*) from mes_bottlcap where company_id="+cid+" and label_pk_id="+pk+" and is delete=false"
        else:
            sb="select count(*) from mes_bottlcap where company_id="+cid+" and label_code='"+bottle+"' and is_delete=false"
    cur=connection.cursor()    
    cur.execute(s)
    
    r=cur.fetchone()
    if r:
        # 当前产品需要检查瓶盖绑定
        cnt=r[0]
        cur.execute(sb)
        rr=cur.fetchone()   
        if bottle:
            if not rr[0]:
                e=_('当前瓶标未绑定瓶盖')
        else:
            if rr[0]!=cnt:        
                e=_("瓶盖绑定数据不正确 "+str(rr[0])+"/"+str(cnt))
    cur.close()
    return e


def labelbinding_chek(enterprise_id,product_id,label_pk_id,h_tbs=None,p_tbs=None):
    """
    套标绑定是否完整    
    :param enterprise_id:企业id
    :param product_id: 产品id
    :param label_pk_id: 主箱标id
    :param tbs: 瓶标所在号段数组
    """
    e=''
    cur=connection.cursor()
    cur.execute("select qty_x,qty_h,qty_p from product_product where id="+str(product_id))
    r=cur.fetchone()

    if r[1]:
        # 盒数不为0， 云平台后绑定标签目前除上海易臻外，产品规格没盒瓶三级关系
        pass
    elif r[2]:
        a=[]
        # 为客户生产的套标有箱盒瓶三级标签，有客户如川酒只重新绑定箱盒关系，瓶盒关系不变，瓶盖码也是跟盒标绑定 
        for tb in h_tbs:
            a.append("(select count(*) cnt from "+tb+" where parent_id="+str(label_pk_id)+"  and package_id<>3)")
        s="select sum(cnt) from ("+ " union all ".join(a)+ ") u"
        cur.execute(s)
        rr=cur.fetchone()
        if rr[0]!=r[2]:
            e="套标绑定不完整 "+str(rr[0])+"/"+str(r[2]) 
    cur.close()
    return e


def redis_check(enterprise_id,label_pk_id,label_pkg,label_code,username,vtype_id,agent_id=None):
    """
    企业(工厂)多用户实时扫码,在redis内存储/检查   目前先不考虑垛标检查
    """        
    prfx='c'+str(enterprise_id)+"_"+str(vtype_id)               # 键值前缀    
    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    # 当前扫码时间
    key=prfx+'_label_pk_'+str(label_pk_id)                      # 当前号码主箱标ID键名
    e=''    
    d=rd.hgetall(prfx+'_label_code_'+label_code)   
    if d:       
        print(prfx+'_label_code_'+label_code, d)

        e="此标签 "+label_code+" "+d['time'][-8:]+" 被 "+d['user_name']+" 扫描"
    else:     
        # 遍历主箱标ID键名的列表
        for l in rd.lrange(key, 0, -1):                
            a=l.split(',')      # '209916443259,1,acc,2023-12-14 15:27:30'
            c=a[0]              # 标签号码
            p=a[1]              # 标签类型
            u=a[2]              # 扫码人
            t=a[3]              # 扫码时间
            if str(label_pkg)=='3':
                # 当前标签为箱标，可能会贴两枚标签                  
                if a[1]=='3':                        
                    e="此箱另一枚箱标 "+c+" "+t[-8:]+" 被 "+u+" 扫描"  
                else:
                    e="此箱已拆,箱内的标签 "+c+" "+t[-8:]+" 被 "+u+" 扫描"  
                break
            else:
                # 当前标签为瓶或盒，只贴一个标签                 
                if a[1]=='3':
                    e='不能拆箱,箱标 '+c+" "+t[-8:]+" 被 "+u+" 扫描"                         
                    break                                   
    if not e:      
        # 当前主箱标ID键内列表不存在或者为空，追加到当前主箱标键值列表            
        rd.lpush(key, label_code+","+str(label_pkg)+","+username+","+tm)
        rd.expire(key,ex) 
        # 创建标签号码键值对        
        rd.hmset(prfx+'_label_code_'+label_code,{
            'user_name':username,
            'time':tm,
            'label_pk_id':label_pk_id,
            'label_pkg':label_pkg
        })
        rd.expire(key, ex)
    return e


def redis_action(action,enterprise_id,vtype_id=None,label_code=None):
    """
    企业对redis实时扫码数据可执行的操作
    """
    data={'e':''}
    prfx='c'+str(enterprise_id)+"_"+str(vtype_id)               # 键值前缀
    if action=='flush':
        # 清空当前企业redis内所有相关数据
        pre=prfx+"_label_*"  
        cnt=0
        for key in rd.keys(pre):
            cnt=cnt+rd.delete(key)
        data['cnt']=cnt
    elif action=='delete':
        # 删除标签号码
        cnt=0
        if label_code:
            key=prfx+'_label_code_'+label_code
            d=rd.hgetall(key)   
            if d:
                label_pk_id=d['label_pk_id']
                label_pkg=d['label_pkg']
                u=d['user_name']
                t=d['time']
                p=d['label_pkg']
                # 删除标签号码键值对
                cnt=cnt + rd.delete(key) 
                # 删除主箱标ID列表内的标签号码 。
                key=prfx+'_label_pk_'+str(label_pk_id)                
                cnt=cnt + rd.lrem(key, 
                    count=0, #count=0 删除所有与 value 相等的值
                    value=label_code+","+str(p)+","+u+","+t
                )    
        else:
            data['e']='label_code missing'            
        data['cnt']=cnt
    return data


# 2023-12-15 考虑云平台今后统一使用这一个实时检查接口
def label_online(request,enterprise_id,action,agent_id=None):     
    '''
    GET 方法 用于企业工厂、经销商出入库时多人实时扫码的标签号码检查  
    检查内容：
    1.重复出入库
    2.数据绑定是否完整：箱盒瓶 盖 nfc
    3.出库产品是否与入库时一致(如果已入库)
    4.现场多人多设备重码扫码检查                  
    '''   
    data={'e':''}
    key=request.GET.get('key','')
    tm=request.GET.get('time','')
    k = sK   # 默认使用inventory.views sK
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if action=='check':
        vtype_id=request.GET.get('vtype_id','')
        label_code=request.GET.get('label_code','')
        product_id=request.GET.get('product_id','')
        user_name=request.GET.get('user_name','')
        if not vtype_id or not label_code or not product_id or not user_name:
            data['e']='vtype_id,label,product_id,user_name required'
            return JsonResponse(data)

        # 取标签信息,确定label_pk_id
        q=LabelQuery(enterprise_id,label_code)
        pk=q.infor['label_pk_id']
        if not pk:
            data['e']=_('标签错误')
            return JsonResponse(data)

        if agent_id:
            # 经销商扫码在线检查 先占位
            pass

        e=''
        tb_stk='stkdetails.c'+str(enterprise_id)
        pkg=q.package['id']
        cur=connection.cursor()
        # 是否已入库
        s="select product_id,to_char(tm,'yyyy-mm-dd hh24:mi:ss'),(select name from product_product where id=product_id) "+\
            "from "+tb_stk+" where vtype_id=1 and label_pk_id="+str(pk)+" and is_delete=false"
        cur.execute(s)
        r0=cur.fetchone()
        if str(vtype_id)=='1':
            if r0:
                e="已于 "+r0[1]+" 入库 名称:"+r0[2]
            else:
                # 瓶盖码绑定
                bt=None
                if pkg==1:
                    bt=label_code     
                e=bottlecap_check(enterprise_id, product_id, pk,bottle=bt)  
                if not e:
                    # 套标绑定是否完整
                    h_tbs=[]    # 盒标表
                    p_tbs=[]
                    pkc=q.infor['label_pk_code'] # 主箱标号码
                    if q.infor['carton_codes']:
                        # 有跨段
                        for c in q.infor['carton_codes']:
                            cur.execute("select box_tb,bottle_tb from carton.t"+c+" where code='"+pkc+"'")
                            r=cur.fetchone()
                            if r:
                                if r[0]:
                                    h_tbs.append("label.t"+r[0])
                                else:
                                    h_tbs.append("label.t"+pkc[:4])
                                if r[1]:
                                    b_tbs.append("label.t"+r[1])
                                else:
                                    b_tbs.append("label.t"+pkc[:4])
                    else:
                        # 不跨段
                        if str(enterprise_id)=='1':
                            # 历史原因，酒鬼专用一个跨段表
                            h_tbs=['label.t'+pkc[:4], 'label.lbl_binding_jg']
                            p_tbs=['label.t'+pkc[:4], 'label.lbl_binding_jg']
                        else:
                            h_tbs=['label.t'+pkc[:4]]
                            p_tbs=['label.t'+pkc[:4]]                    
                    e=labelbinding_chek(enterprise_id,product_id,pk,h_tbs,p_tbs)                   
        
        elif str(vtype_id)=='2' :
            # 数据库内是否已有相同的操作记录            
            #s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),label_pkg,"+\
            #    "(select remark from inventory_voucher where id="+str(vtype_id)+"),label_code "+\
            #    "from "+tb_stk+" where vtype_id="+str(vtype_id)+" and is_delete=false "+\
            #    "and label_pk_id="+str(pk)                        
            #cur.execute(s)            
            #for rr in cur.fetchall():
            #    if pkg==3:
            #        if rr[1]==3:
            #            e=_('此箱 '+rr[0]+" 已"+rr[2])
            #        else:
            #            e=_('此箱 '+rr[0]+" 已拆箱"+rr[2])
            #        break
            #    else:
            #        if rr[1]==3:
            #            e=_('此标签所在箱 '+rr[0]+" 已"+rr[2])
            #            break
            #        else:
            #            if rr[3]==label_code:
            #                e=_('此标签 '+rr[0]+" 已"+rr[2])
            #                break
            

            # 2024-01-24 是否已出库，且最后一条记录不是退库
            s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),label_pkg,"+\
                "(select remark from inventory_voucher where id="+str(vtype_id)+"),label_code "+\
                "from "+tb_stk+" s where vtype_id="+str(vtype_id)+" and is_delete=false "+\
                "and label_pk_id="+str(pk)+" "+\
                "and (select vtype_id from "+tb_stk+" where label_pk_id="+str(pk)+" order by tm desc limit 1)<>4 "+\
                "order by tm desc limit 1"
            cur.execute(s)            
            rr=cur.fetchone()
            if rr:           
                if pkg==3:
                    if rr[1]==3:
                        e=_('此箱 '+rr[0]+" 已"+rr[2])
                    else:
                        e=_('此箱 '+rr[0]+" 已拆箱"+rr[2])                    
                else:
                    if rr[1]==3:
                        e=_('此标签所在箱 '+rr[0]+" 已"+rr[2])                        
                    else:
                        if rr[3]==label_code:
                            e=_('此标签 '+rr[0]+" 已"+rr[2])

            if e:
                data['e']=e
                return JsonResponse(data)
            else:
                # 只要不是扫码入库，就要检查前端传过来的产品名称是否正确                       
                if r0:
                    if str(r0[0])!=str(product_id):
                        e=_(r0[1]+" 入库产品名为 "+r0[2])
                else:
                    e=_('产品尚未入库')
        if e:
            data['e']=e
            cur.close()
            return JsonResponse(data)
        # 现声重复扫码，做redis检查
        e=redis_check(enterprise_id,pk,pkg,label_code,user_name,vtype_id,agent_id=None)       
        if e:
            data['e']=e
        cur.close()
    elif action=='flush':
        vtype_id=request.GET.get('vtype_id','')
        if vtype_id:
            data=redis_action(action,enterprise_id,vtype_id)
        else:
            data['e']=_('vtype id missing')
            data['cnt']=0
    elif action=='delete':        
        label_code=request.GET.get('label_code','')
        vtype_id=request.GET.get('vtype_id','')
        if label_code and vtype_id:
            d=redis_action(action,enterprise_id,vtype_id,label_code)
            data['cnt']=d['cnt']
        else:
            data['e']='label code and vtype id required'
    
    return JsonResponse(data)
