import hashlib
import json
import importlib as im
from datetime import datetime, timedelta


class base_Quant_api():

    def __init__(self, type, portfolioDataPath="", assetClassPath="", now=""):
        mod = im.import_module('lib.' + type + "_api_agent")
        api_agent = getattr(mod, "Api_agent")

        self.__default_msg = {'errorCode': '0', 'errorMsg': ''}
        self.__pt_keys = ["pt_id", "recomm_id", "rp_id", "last_tx_date", "last_recomm_date", "create_date", "fas", "last_check_date"]
        self.__fas_keys = ["fund_id", "weight"]
        self.__api = api_agent(portfolioDataPath, assetClassPath)
        self.__portfolios = {}
        self.__fund_metadata = {}
        self.__debug_info = {}
        self.nowstr  = now

    def now(self):
        if self.nowstr == "":
            return datetime.now()
        else:
            return datetime(int(self.nowstr[:4]), int(self.nowstr[4:6]), int(self.nowstr[6:8]))

    def __debug(self, msg):
        self.__debug_info[datetime.now()] = msg
        return True

    def __gen_rcv_no(self, recomm_id, numbers):
        return "%s-%s-%s" % (datetime.now().strftime("%Y%m%d%H%M%S"), recomm_id, numbers)

    def __verify_pt_data(self, data):
        para = ["fas", "last_recomm_date", "last_tx_date", "pt_id", "recomm_id", "rp_id"]
        for parameter in para:
            if not parameter in data.keys():
                return False
        if len(data["fas"]) == 0:
            return False
        return True

    def __verify_pt_data_dividend(self, data):
        para = ["pt_id", "total_in", "asset"]
        for parameter in para:
            if not parameter in data.keys():
                return False
        if len(data["asset"]) == 0:
            return False            
        return True

    def get_latest_portfolio(self, recomm_id, query_date = ''):
        #self.__debug("Getting portfolio data: %s" % query_key)
        portfolio_data = self.__api.get_latest_portfolio(recomm_id, query_date)
        #self.__debug("%s: %s" % (portfolio_id, json.dumps(portfolio_data)))
        if portfolio_data != None:
            return portfolio_data
        return None
        

    def get_portfolio_by_rpid(self, rp_id):
        #self.__debug("Getting portfolio data: %s" % query_key)
        portfolio_data = self.__api.get_portfolio_by_rpid(rp_id)
        #self.__debug("%s: %s" % (portfolio_id, json.dumps(portfolio_data)))
        if portfolio_data != None:
            return portfolio_data
        return None

    def get_fund_asset_class(self, fund_id):
        self.__debug("Getting fund asset class: %s" % fund_id)
        data = self.__api.get_fund_metadata(fund_id)
        if data != None:
            return data
        return None

    def _rebalance(self, pt):
        pass

    def _dividend(self, pt):
        pass
        

    def show_debug_info(self):
        if not bool(self.__debug_info):
            return True 
        for exec_time in sorted(self.__debug_info):
            print("[%s] %s" % (exec_time.strftime("%Y-%m-%d %H:%M:%S.%f"), self.__debug_info[exec_time]))
        self.__debug_info = {}
        return True
        

    def rebalance(self, pts):
        self.__default_msg = {'errorCode': '0', 'errorMsg': 'Success', 'rebs':[]}
        pt_len = len(pts)
        if pt_len == 0:
            return self.__default_msg
        self.__default_msg['rcv_no'] = self.__gen_rcv_no(pts[0]["recomm_id"], pt_len) # it need to be confirmed.
        for pt in pts:
            if not self.__verify_pt_data(pt):
                self.__debug("Failed to verify pt data")
                self.__default_msg['errorCode'] ="1001"
                self.__default_msg['errorMsg'] = "Failed to verify pts data."
                self.__default_msg['rebs']= []
                break

            else :
                #self._rebalance(pt)
                res = self._rebalance(pt)
                #(rp_id, reason) = self._rebalance(pt)
                
                if res == 0:
                    rp_id = '0'
                    reason = '符合所有條件,無需REB'
                    last_busi_date = None
                    rec_reason = None
                else:
                    (rp_id, reason,last_busi_date,rec_reason) = res

                self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id":rp_id, "reason":reason,
                                                   "last_busi_date":last_busi_date , "rec_reason":rec_reason})
                #self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id": self._rebalance(pt)}) 

        return self.__default_msg


    def dividend(self, pts):
        self.__default_msg = {'errorCode': '0', 'errorMsg': 'Success', 'dividends':[]}
        pt_len = len(pts)
        if pt_len == 0:
            return self.__default_msg
        
        for pt in pts:
            if not self.__verify_pt_data_dividend(pt):
                self.__debug("Failed to verify pt data")
                self.__default_msg['errorCode'] ="1001"
                self.__default_msg['errorMsg'] = "Failed to verify pts data."
                self.__default_msg['rebs']= []
                break
            else :
                res = self._dividend(pt)

                self.__default_msg['dividends'].append({"pt_id":pt["pt_id"],  "redeem":res }) 
                #self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id": self._rebalance(pt)}) 

        return self.__default_msg