"""
@autor:Yue
@date::14:26
@file:dealbody.py
@project:appQutoInfo
@project:appQutoInfo

"""
import base64
from blueprints.tools.rwKeyData import rwKeyData

import json,re,os,random,datetime
#from requests_toolbelt import MultipartEncoder
from requests_toolbelt import MultipartEncoder
from urllib.parse import  urlencode,quote_plus,unquote
from blueprints.tools import debugtalk
#from urllib.parse import  quote_plus
import urllib
from blueprints.settings import *

def deal_globalParam(config,param):
    temp_param=param

    if isinstance(param,dict):
        tbody=param.get('body')
        #print(param)
        if tbody and isinstance(tbody,dict):
            for k, v in tbody.items():
                try:

                    #param.get('type')in ['msg','account','hetong'] and

                    if isinstance(v,str)  and( ((param.get('type') in ['fengkong'] and  k=='exData') or k=='extData') or\
                            ( '[' in v and ']' in v ) or
                             ('/middle_office/user/ext/' in param.get('url'))   \
                            or (('json' in param.get('header').get('Content-Type') or 'json' in param.get('header').get('content-type')))) \
                                and ( '/external/quota/auth_amount_audit/notify'!=param.get('url') and '/middle_office/quota/order_audit/notify'!= param.get('url')
                                      and '/middle_office/risk/audit/result'!=param.get('url')):


                            # ('json' in param.get('header').get('Content-Type') or 'json' in param.get('header').get('content-type')):


                        v=v.replace("'",'\"').replace('\r\n','').replace('\\t','')
                        # if k=='template':
                        #     print('%'*20,v,type(v))
                        v=json.loads(v)
                        # print(k,'***=====**',v,type(v))
                    tbody[k]=v
                    #print('***' * 20, v)
                except Exception as e:
                    #print(e,k,v)
                    pass
            param['body']=tbody
            #print('###@@@'*20,param['body'])
        param=json.dumps(param)

    param_url =  re.findall(r'{{(.*?)}}',param) #or re.findall(r'"{(.*?)}"', param)
    #print(param_url)
    if param_url:
        for i in param_url:

            ii = '{{' + i + '}}'
            i = i.lower()
            #print(ii,i, rwKeyData().readKeyData('sqldata', i.split('_')[0]))

            try:
                if len(i.split('_'))>1 and rwKeyData().readKeyData('sqldata', i.split('_')[0]):

                    fillParam=eval(rwKeyData().readKeyData('sqldata', i.split('_')[0]))[eval(i.split('_')[1])]

                    fillParam=str(fillParam)

                    #print('fillParam==',fillParam)

                else:
                    #print('=======', param_url, i, config, fillParam)
                    fillParam = rwKeyData().readKeyData('baseinfo', i) or \
                                rwKeyData().readKeyData('globalvar', i)or \
                                rwKeyData().readKeyData('channnel',i) or \
                                eval('{0}.{1}'.format(config.__name__,i))

                if fillParam:
                    if 'http' in fillParam:
                        #print('+++',i, fillParam,{'namespace':eval('{0}.{1}'.format(config.__name__,'namespace'))})
                        fillParam = fillParam.format(namespace=eval('{0}.{1}'.format(config.__name__,'namespace')))
                    #print(i,'+++',fillParam)
                    param = param.replace(ii, fillParam)
                    #print('final======',param)

            except Exception as e:
                pass
                #print('++++++',e)
    #print("param=====",param)
    if isinstance(temp_param,dict):
        return json.loads(param)
    else:
        return param




def setGloablValue(keydata,casefile):
    productid=keydata.readKeyData('baseinfo','productid')
    if productid==str(4):
        keydata.writeKeyData('globalvar','biztype',0)


    nextstep=casefile.get("nextstep")

    if nextstep:
        #print(nextstep)
        nextstep = json.loads(nextstep.replace("'",'\"'))
        counter=int(keydata.readKeyData('baseinfo','counter'))
        keydata.writeKeyData('baseinfo','counter',counter+1)

        for i in nextstep:
            #print(i)
            if 'term' in i:
                try:

                    terms=keydata.readKeyData('baseinfo','terms')
                    keydata.writeKeyData('baseinfo', 'term', json.loads(terms)[counter + 1])
                except:
                    keydata.writeKeyData('baseinfo','term',json.loads(terms)[0])
            if i=='amount':


                try:
                    amounts=keydata.readKeyData('baseinfo', 'amounts')
                    keydata.writeKeyData('baseinfo', 'amount', json.loads(amounts)[counter + 1])
                except:
                    keydata.writeKeyData('baseinfo', 'amount', json.loads(amounts)[0])

            if i=='productid':
                try:
                    productids=keydata.readKeyData('baseinfo', 'productids')

                    keydata.writeKeyData('baseinfo', 'productid', json.loads(productids)[counter+1])
                    #print(productids)
                except Exception as e:
                    #print(e)
                    keydata.writeKeyData('baseinfo', 'productid', json.loads(productids)[0])


def setup_step(config,casejson):
    setup=casejson.get('setup')
    if setup:
        for k,v in setup.items():
            try:
                if 'config' in v:
                    ruleconfig = re.findall(r"config=(.*)'", v)
                    # print(ruleconfig[0], config.__name__, v)

                    v = v.replace('config={0}'.format(ruleconfig[0]), config.__name__)
                # print(k,v)
                tttttt = eval('debugtalk.{0}'.format(v))
            # print(body, eval('debugtalk.{0}'.format(v)))
            except:
                # pass
                raise Exception("执行rule规则出错，确定debugtalk.py文件中是否存在可执行函数:{0}".format(v))




class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj,datetime.datetime):
            return obj.strftime("%Y-%m-%d")
        else:
            return json.JSONEncoder.default(self,obj)



def globalParamReplace(config,body,globalvalue='fundId'):
    '''
    当body中全局变量不是第一级时，需要进行处理
    eg：
    body={'a':1,"b":["c":"%s"]}
    :param config:
    :param body:
    :param replaveValue:
    :return:
    '''
    #flag=1   ##flag=1，表示body为dict，为0，表示为str,现预留
    if isinstance(body,dict):
        #print(body)
        body=json.dumps(body,cls=DateEncoder)
        #flag=1

    if 'fundcorpid'.lower() in body.lower() or globalvalue.lower() in body.lower():
        # fundcorpidvalue = re.findall(r'"fundCorpId":.*?,', body) or \
        #                   re.findall(r'\'fundCorpId\':.*?,', body) \
        #                   or re.findall(r'"fundId":.*?,', body) \
        #                   or re.findall(r'\'fundId\':.*?,', body)
        fundcorpidvalue=re.findall(r'"{0}":.*?,'.format(globalvalue), body) or re.findall(r'\'{0}\':.*?,'.format(globalvalue), body)
        if fundcorpidvalue:
            replace_fundcorpidvalue = fundcorpidvalue[0][0:-1]
            if '%s' in replace_fundcorpidvalue:
                if globalvalue=='fundId':
                    fundingCorpId = rwKeyData(config).readKeyData('channnel', 'fundcorpid')
                rev = replace_fundcorpidvalue.split(':')[0]
                temp_body = body.replace(replace_fundcorpidvalue, '{0}:{1}'.format(rev, fundingCorpId))
                # print("=======",replace_fundcorpidvalue,rev,temp_body)
                try:
                    body = json.loads(temp_body)
                    return body
                except:
                    return temp_body
    return json.loads(body)

def fillDateAnddealHeader(config,Alldata,casejson=None,filldata=None):
    '''

    :param casejson: json用例
    :param filldata: 通过sql得到的值，当body存在%s时，才会进行填充操作
    :return:
    '''
    f=0


    casejson = deal_globalParam(config, casejson)
    header = casejson.get("header") or casejson.get('Headers')
    if not header or not header.get("Content-Type"):
        casejson.setdefault("header", {"Content-Type": "application/x-www-form-urlencoded"})
        header = casejson.get("header")
    #print(casejson)
    try:
        body=casejson.get(Alldata)
    except:
        raise  Exception('传参必须是【body，header，param，url】之一')

    #print("%%%%=============",body)
    if isinstance(body,dict) and body.get('token'):
        body['token']=rwKeyData(config).readKeyData('globalvar',body.get('token'))

    if header.get('Authorization') and header.get('Authorization') == '%s':
        #dealmobile=str(filldata[0 ]if len(filldata)>0 else 0)+str(':0000')
        #print(dealmobile)
        phone_no=rwKeyData(config).readKeyData("baseinfo","phone_no")
        dealmobile=str(phone_no)+str(':0000')
        rwKeyData(config).writeKeyData('globalvar','logindata','phone={0}'.format(phone_no))
        header['Authorization'] = 'Verification '+bytes.decode(base64.b64encode(dealmobile.encode()))


    if body and isinstance(body,dict):

        if body.get('channelId') and body.get('channelId')=='%s' and casejson.get('channelId') in['opapi']:
            channelId=rwKeyData(config).readKeyData('channnel','channnelID')
            body['channelId']=channelId if channelId else body['channelId']
        if body.get('fundCorpId') and body.get('fundCorpId')=='%s' and casejson.get('type') in ['opapi','clotho']:
            fundingCorpId=rwKeyData(config).readKeyData('channnel','fundcorpid')
            body['fundCorpId']=fundingCorpId if fundingCorpId else body['fundCorpId']
        elif body.get('fundingCorpId') and body.get('fundingCorpId')=='%s' and casejson.get('type') in ['opapi','clotho']:
            fundingCorpId = rwKeyData(config).readKeyData('channnel', 'fundcorpid')
            body['fundingCorpId'] = fundingCorpId if fundingCorpId else body['fundingCorpId']
        #print('***'*20,body)
        try:
            t=json.dumps(body)
        except:
            t = str(body)

        #print("body=======",t)
        c=re.findall("%s",t)



        if c and filldata:

            if len(c)>len(filldata):
                filldata=filldata+list(0 for i in range(len(c)-len(filldata)))
            else:
                filldata=filldata[:len(c)]
            try:
                for index,k in enumerate(body):

                    if not '%s' in body[k] and isinstance(body[k],str):
                        continue
                    if k=='signArgs':
                        filldata[f]=[{"signAccountId":3,"signArgs":[{"pagenum":"1","signx":"0.2","signy":"0.5"}]},{"signAccountId":4,"signArgs":[{"pagenum":"1","signx":"0.6","signy":"0.5"}]}]
                    if isinstance(body[k],(str,)) and body[k]=='%s':
                        body[k]=filldata[f]
                    else:
                        raise Exception('跳转到tuple填充')
                    f+=1

                casejson[Alldata] = body

            except:
                #print("####"*30)
                body=t%tuple(filldata)

                try:

                    casejson[Alldata]=json.loads(body)

                except:
                    casejson[Alldata] = json.loads(json.dumps(body))
                    #print('11=====', type(body), body)
            #print(casejson)
            #print('2=====',type(body), body)
            return casejson


    elif body and isinstance(body,str):
        c = re.findall("%s", body)
        #print("**" * 20, filldata, len(c), casejson.get('commit'))
        if len(c)>=1:

            if len(c)>len(filldata):
                filldata=filldata+list(0 for i in range(len(c)-len(filldata)))
            if len(c)<len(filldata):
                filldata=filldata[0:len(c)]

            body = body % tuple(filldata)
            try:
                casejson[Alldata] = json.loads(body)
            except:
                casejson[Alldata] = body
        else:
            if re.findall(r"{{(.+?)}}",body):
                t=re.findall(r"{{(.+?)}}",body)
                print(len(t),len(filldata),filldata,t)
                if len(t) > len(filldata):
                    filldata = filldata + list(0 for i in range(len(c) - len(filldata)))
                if len(t) < len(filldata):
                    filldata = filldata[0:len(t)]
                    #print(filldata)

                for index,i in enumerate(t):
                    #print('{{'+i+"}}",str(filldata[index]))
                    body=body.replace('{{'+i+"}}",str(filldata[index]))
                    #body.format(**{i:filldata[index]})
                    #print("++++",body)
                casejson[Alldata] = body





        return casejson

    #print(casejson)
    return casejson








def fillBodyAnddealHeader_feiqi(config,casejson=None,filldata=None):
    '''

    :param casejson: json用例
    :param filldata: 通过sql得到的值，当body存在%s时，才会进行填充操作
    :return:
    '''
    f=0
    header = casejson.get("header") or casejson.get('Headers')
    if not header or not header.get("Content-Type"):
        casejson.setdefault("header", {"Content-Type": "application/x-www-form-urlencoded"})
        header = casejson.get("header")

    casejson = dealrules(config, casejson, filldata)
    casejson = deal_globalParam(config, casejson)

    body=casejson.get("body")
    #print(type(body),body,casejson)
    #print("fillBodyAnddealHeader body==",type(body),body)

    #print('****'*10,header)

    #print(body,type(body))
    if isinstance(body,dict) and body.get('token'):
        body['token']=rwKeyData(config).readKeyData('globalvar',body.get('token'))

    if header.get('Authorization') and header.get('Authorization') == '%s':
        #dealmobile=str(filldata[0 ]if len(filldata)>0 else 0)+str(':0000')
        #print(dealmobile)
        phone_no=rwKeyData(config).readKeyData("baseinfo","phone_no")
        dealmobile=str(phone_no)+str(':0000')
        rwKeyData(config).writeKeyData('globalvar','logindata','phone={0}'.format(phone_no))
        header['Authorization'] = 'Verification '+bytes.decode(base64.b64encode(dealmobile.encode()))


    if body and isinstance(body,dict):

        if body.get('channelId') and body.get('channelId')=='%s' and casejson.get('channelId') in['opapi']:
            channelId=rwKeyData(config).readKeyData('channnel','channnelID')
            body['channelId']=channelId if channelId else body['channelId']
        if body.get('fundCorpId') and body.get('fundCorpId')=='%s' and casejson.get('type') in ['opapi','clotho']:
            fundingCorpId=rwKeyData(config).readKeyData('channnel','fundcorpid')
            body['fundCorpId']=fundingCorpId if fundingCorpId else body['fundCorpId']
        elif body.get('fundingCorpId') and body.get('fundingCorpId')=='%s' and casejson.get('type') in ['opapi','clotho']:
            fundingCorpId = rwKeyData(config).readKeyData('channnel', 'fundcorpid')
            body['fundingCorpId'] = fundingCorpId if fundingCorpId else body['fundingCorpId']

        try:
            t=json.dumps(body)
        except:
            t = str(body)

        #print("body=======",t)
        c=re.findall("%s",t)



        if c and filldata:

            if len(c)>len(filldata):
                filldata=filldata+list(0 for i in range(len(c)-len(filldata)))
            else:
                filldata=filldata[:len(c)]
            try:
                for index,k in enumerate(body):
                    #print(index,'===',k,type(body[k]))

                    if not '%s' in body[k]:
                        continue
                    if k=='signArgs':
                        filldata[f]=[{"signAccountId":3,"signArgs":[{"pagenum":"1","signx":"0.2","signy":"0.5"}]},{"signAccountId":4,"signArgs":[{"pagenum":"1","signx":"0.6","signy":"0.5"}]}]
                    if isinstance(body[k],(str,)) and body[k]=='%s':
                        body[k]=filldata[f]
                    else:
                        raise Exception('跳转到tuple填充')
                    f+=1
                casejson['body'] = body

            except:
                body=t%tuple(filldata)
                #print('1=====', type(body), body)
                try:

                    casejson['body']=json.loads(body)
                    #print('11=====', type(body), body)
                except:
                    casejson['body'] = json.loads(json.dumps(body))
                    #print('11=====', type(body), body)
            #print(casejson)
            #print('2=====',type(body), body)
            return casejson


    elif body and isinstance(body,str):
        c = re.findall("%s", body)
        #print("**" * 20, filldata, len(c), casejson.get('commit'))
        if len(c)>=1:

            if len(c)>len(filldata):
                filldata=filldata+list(0 for i in range(len(c)-len(filldata)))
            if len(c)<len(filldata):
                filldata=filldata[0:len(c)]

            body = body % tuple(filldata)
            try:
                casejson['body'] = json.loads(body)
            except:
                casejson['body'] = body
        return casejson

    return casejson

def dealrules(config,Alldata,casejson=None,filldata=None):
    '''
    当json用例中存在rule时，则body的填充数据改成由rule规则得到，rule的格式是：{k:v}
    :param config:
    :param casejson:
    :param filldata:
    :return:
    '''
    rw=rwKeyData(config)
    rules=casejson.get('rule')
    #print('fffffff')

    body=casejson.get(Alldata)

    if rules and isinstance(body,dict):

        for k,v in rules.items():
            #print(k,v,len(k.split(',')))


            if body.get(k) :
                try:
                    #print(k,v)
                    if body[k]=='%s':
                        if 'config' in v:
                            ruleconfig=re.findall(r"config=(.*)'",v)
                            #print(ruleconfig[0], config.__name__, v)

                            v=v.replace('config={0}'.format(ruleconfig[0]),config.__name__)

                        #print("++++++",v)
                        body[k]=eval('debugtalk.{0}'.format(v))
                #print(body, eval('debugtalk.{0}'.format(v)))
                except:
                    raise Exception("执行rule规则出错，确定debugtalk.py文件中是否存在可执行函数:{0}".format(v))
            ##当k的格式是k1,k2,k3...，则需要进行循环
            elif len(k.split(','))>1:

                #try:
                    #print('body=====', body)


                    bodys=k.split(',')
                    tempbodys=bodys[:]
                    #print('=====', rw.readKeyData('circleData','circledata'),type(rw.readKeyData('circleData','circledata')))
                    try:
                        fillbody=eval(rw.readKeyData('circleData','circledata'))

                    except:
                        #print(v)
                        eval('debugtalk.{0}'.format(v))
                        #print(rw.readKeyData('circleData', 'circleflag'))
                        fillbody = eval(rw.readKeyData('circleData', 'circledata'))


                    #参数值
                    fillbodycount=int(rw.readKeyData('circleData','circleparam'))
                    #参数计数器
                    fillbodylength=int(rw.readKeyData('circleData','circleflag'))
                    bodys=fillbody[fillbodylength]

                    #print(fillbody,fillbodylength,bodys)

                    #rw.writeKeyData('circleData','circleflag',fillbodylength-1)
                    for index,i in enumerate(tempbodys):
                        #print(index,i)
                        if i:
                            body[i]=bodys[index]
                            #print(bodys[index],i)
                    casejson[Alldata]=body

                    # rw.writeKeyData('circleData','circleflag',fillbodylength)
                    #
                    # print(rw.readKeyData('circleData','circleflag'))
            else:
                try:
                    #print(k,v)
                    tttttt=eval('debugtalk.{0}'.format(v))
                    print(body, eval('debugtalk.{0}'.format(v)))
                except:
                    #pass
                    raise Exception("执行rule规则出错，确定debugtalk.py文件中是否存在可执行函数:{0}".format(v))

        return casejson
    return casejson



def dealbodyHeaderType(config,casejson=None,filldata=None):
    '''
    当header类型不同时，需要进行处理
    :param config: 得到需要上传的文件路径
    :param casejson:
    :param filldata:
    :return:
    '''
    #cj=fillBodyAnddealHeader(config,casejson,filldata)
    casejson = dealrules(config,'body', casejson, filldata)
    casejson=dealrules(config,'param', casejson, filldata)

    #print('dealbodyHeaderType==',casejson)

    if casejson.get('url'):

        #print(count,filldata)
        count = len(re.findall(r'%s', str(casejson.get('url')))) or len(
            re.findall(r'{{(.*)}}', str(casejson.get('url'))))
        casejson = fillDateAnddealHeader(config,'url', casejson, filldata)

        # print(re.findall(r'{{(.*)}}', str(casejson.get('url'))))
        # print(casejson.get('url'))
        if count:
            filldata = filldata[count:]
        #print('url===',filldata,count)
    if casejson.get('header'):
        count = len(re.findall(r'%s', str(casejson.get('header'))))
        casejson = fillDateAnddealHeader(config, 'header', casejson, filldata)
        #print(casejson)

        if count:
            filldata = filldata[count:]
    if casejson.get('param'):
        count = len(re.findall(r'%s', str(casejson.get('param'))))
        casejson = fillDateAnddealHeader(config, 'param', casejson, filldata)

        #print(filldata,count)
        if count:
            if filldata:
                filldata = filldata[:count]
            else:
                filldata=[0 for i in range(count)]
    if casejson.get('body'):
        #filldata = filldata
        count = len(re.findall(r'%s', str(casejson.get('body'))))
        casejson=fillDateAnddealHeader(config,'body',casejson,filldata)
        if count:
            try:
                filldata = filldata[count:]
            except:
                pass
    #print('body===', filldata)
    #print(casejson)
    cj=casejson

    body=cj.get("body")
    isurl=casejson.get('isurl')


    #print("body===",body,type(body))
    header = cj.get("header") or cj.get("Headers")

    #print("***" * 10, header)
    headerType=header.get("Content-Type")

    if not headerType:
        header["Content-Type"]='application/x-www-form-urlencoded'
        headerType = header.get("Content-Type")

    #staticfile和absstaticfile主要用于multipart/form-data的情况
    staticfile=[i for i in os.listdir(config.staticdir) if os.path.isfile(os.path.join(config.staticdir,i))]

    #print("staticfile==", staticfile,len(staticfile))

    absstaticfile=os.path.join(config.staticdir,staticfile[random.randint(0,len(staticfile)-1)])

    #print("staticfile==", staticfile,absstaticfile )

    if body:
        #除了application/json，其他类型都需要考虑到dict和list的情况
        if re.findall(r"urlencoded",headerType):
            #print(type(body),body)
            try:
                #print("***",body)
                t=urlencode(body)
                #print(unquote(t))

                return cj

                return urlencode(body),header
            except:
                #print(casejson)
                #print(type(body),body.replace("'",'\"'))
                try:
                    body=json.loads(body.replace("'",'\"'))
                except:
                    #print(body)
                    body = json.loads(body)
                return cj
                return urlencode(body), header
                #return quote_plus(body),header


        if re.findall(r"json",headerType):
            if isurl:
                return cj
                return urlencode(body),header
            return cj
            return body,header


        if re.findall(r"multipart",headerType):
            if isinstance(body,dict):
                abody={}
                #abody.setdefault("file",((staticfile,)))
                for k,v in body.items():
                    if k in ("jpg","png","mp3","txt"):
                        abody.setdefault(v, ((staticfile,open(absstaticfile,"rb"))))
                    else:
                        abody.setdefault(k,str(v))

                m=MultipartEncoder(abody)
                cj['body'] = m
                header["Content-Type"]=m.content_type
                return cj
                return m,header

            if isinstance(body,list):
                abody = []
                for index in body:
                    for k, v in index.items():
                        if k in ("jpg", "png", "mps", "txt"):
                            abody.append((v, ((staticfile, open(absstaticfile,"rb")))))
                        else:
                            abody.append((k, str(v)))
                #print("==",abody)
                m = MultipartEncoder(abody)
                cj['body']=m
                header["header"] = m.content_type
                return cj

                return m, header

    return cj

def requesturl(config,casejson):
    #eval("{0}.{1}".format(config,casejson))
    type=casejson.get("type","dss_url")
    #print(type)
    try:
        if casejson.get("url"):
            #print(eval("config.{0}".format(type)))
            return eval("config.{0}".format(type)),type
        else:
            return eval("config.{0}".format(type)), type
    except Exception as e:
        raise Exception("未能根据type：{0},找到对应的请求域名".format(type),e)
    #return config





if __name__ == '__main__':
    casejson="http://dadadsadsa?{{pay}}"
    #casejson={"body":{"a":"{{usered}}","b":"%s"},"header":{"Content-Type": "urlencoded"},"type":"hetong","rule":[{"a":"aa('aa')"}]}
    #casejson1={"body":[{"html":"aaaafile"},{"html":"aaaafile1"},{"a":"%s"},{"a":"%s"}],"header":{"Content-Type":"multipart"},"url":"aa"}
    #casejson={}
    # b,h=requesturl(testConfig,casejson)
    # print(b,h)
    # print(urlencode(casejson.get("body")))
    # casejson='/Users/dm/Desktop/python_script/autoInterface/testCase/passportapi/367.json'
    # with open(casejson,'r+',encoding='utf-8') as f:
    #     casejson=json.load(f)
    #     #print(casejson)
    casejson={'rule':{'a,b':'getCircle([1,2],[3])'},'body':{'a':"%s","b":'%s'}}


    t=dealrules(testConfig,casejson,[11,22,33])
    print(t)

    # t=deal_globalParam(testConfig,casejson)
    # print(t)

    # a,b=dealbodyHeaderType(testConfig,casejson,(2,3,1))
    #
    # print(a,b)

    #print(testConfig.dss_url)
    #print(requesturl(testConfig,casejson))








