'''
Created on 27-Jul-2020

@author: Saurabh Kumar Pandey
This script is the worker which aims at performing the set pin of user in mysql and mongodb
'''
#Standard library import
#this will pull the demographic details from Queue and publish it to the MYSQL or mongodb user linking
import pika,json,datetime,uuid
from datetime import date, timedelta
from lib.create_user_mysql_mongo import mongoUpdateOperator
from lib.log import logger
from configparser import ConfigParser


config_object = ConfigParser()
config_object.read("/opt/rmq-workers/config.ini")
rabbitmq = config_object["rabbitmq"]
application_environment = config_object["environment"]['application']
application_location = config_object["environment"]['location']
prefetch_counter = config_object["prefetch_count"]
accounts_db = config_object["mongo_accounts_db"]

#RabbitMQ connection credentials
try:
    credentials = pika.PlainCredentials(rabbitmq['username'], rabbitmq['password'])
    parameters = pika.ConnectionParameters(rabbitmq['host'], rabbitmq['port'], rabbitmq['vhost'], credentials, socket_timeout=int(rabbitmq['socket_timeout']))                                   
    
    #Connection to a broker on the local machine
    connection = pika.BlockingConnection(parameters)
    channel = connection.channel()    
    exchange_name = 'Set_User_Pin_Xchange'    
    channel.exchange_declare(exchange=exchange_name, exchange_type='fanout', durable=True)
    route_key = queue_name = 'Set_User_Pin_'+ application_location    
    channel.queue_bind(exchange=exchange_name, queue=queue_name, routing_key=route_key)
except Exception as channel_declaration:
    print(channel_declaration)
    response = {'channel_exception': 'Unable to connect to RMQ', 'msg': channel_declaration}
    logger('accounts_worker_log',response)        
          
def updateUserPin(ch, method, properties, content, log_id):
    global userMongoData, refkey
    ''' This content will have userid and pin that needs to be updated to the userser in Mongo, Mysql and Redis'''
    
    if content.get('digilockerid') == None or content.get('digilockerid') == None:
        ch.basic_reject(delivery_tag=method.delivery_tag, requeue=False) 
        return {'status':False, 'msg':'digilockerid not found'}  
     
    userMongoData = {}    
    try:    
        uid = content.get('digilockerid')
        pin = content.get('pin')  
        password = content.get('password')  
        if pin != None:      
            userMongoData = {'pin': pin}   
        if password != None:      
            userMongoData = {'password': password}   
                 
        dataUpdUser = { "operation": "U",
                        "db": accounts_db["accounts_db"], #accounts_services
                        "collection": 'users',
                        "data": userMongoData,
                        "key": {'digilockerid':uid},
                        "multi":'N'}
    
        updateResp =  mongoUpdateOperator(dataUpdUser)      
        noRetryCodes = {2,3}
        
        if updateResp['status'] == True and updateResp['code'] == 1:
            ch.basic_ack(delivery_tag=method.delivery_tag,multiple=False)
            return {'status': True, 'msg' : 'PinUpated'}                 
        elif updateResp['status'] == True and updateResp['code'] in noRetryCodes:
            ch.basic_reject(delivery_tag=method.delivery_tag, requeue=False) 
            return {'status': False, 'msg' : 'PinUpateFailed'} 
        else:
            print(updateResp['code'])
            ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)
            return {'status': False, 'msg' : 'PinUpateFailed'} 
    except Exception as e:
        ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)  
        return {'status': False, 'msg' : 'PinUpateFailed'} 
        

def callback(ch, method, properties, body):
    try:    
        data = json.loads(body)   
        content = data.get('data') or None
        now = datetime.datetime.now()
        formatted_date = now.strftime('%Y-%m-%d %H:%M:%S.%f')    
        log_id = data.get('id') or None      
         
        resp = updateUserPin(ch, method, properties, content, log_id)
        print(resp)
        response = {'pin_resp':resp, 'log_id': log_id}
        logger('accounts_worker_log',response)  
    except Exception as functinal_expn:
        print(functinal_expn)
        response = {'pin_update_error': 'exception raised', 'log_id': log_id, 'msg': functinal_expn}
        logger('accounts_worker_log',response)
        ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)        
        
        
channel.basic_qos(prefetch_count=int(prefetch_counter['accounts-create-pin']))         
try: 
    b = channel.basic_consume(queue=queue_name, on_message_callback = callback)
    channel.start_consuming()   
except Exception as ChannelException:
    print(ChannelException) 
    response = {'channel_exception': 'Unable to connect to RMQ', 'msg': ChannelException}
    logger('accounts_worker_log',response)  
    channel.stop_consuming()
