

from base_class import *
from base_class import BaseVariableFunction
import urllib.parse
import shutil
import random
import json
baseclass = BaseVariableFunction(__file__)

old_print = print


def timestamped_print(*args, **kwargs):
    old_print(datetime.datetime.utcnow().replace(
        microsecond=0), *args, **kwargs)


print = timestamped_print

print('\n'*5)
print(f"{'{:<6}'.format('ENTER')} {baseclass.scriptfilename} ----------------NOTE-----------NOTE---------------")
baseclass.makedirpath(baseclass.dalao_transfer_solanafm_path)


def request_onetime(req_dict_total, key_idx,  loop):
    requests_dict = req_dict_total.get(key_idx)
    if requests_dict is None:
        return
    elif requests_dict['isrequseting'] == True:
        return
    elif requests_dict['need_remove'] == True:
        print(f"key_idx {key_idx} need_remove\n", end='')
        if req_dict_total.get(key_idx) is not None:
            print(f"remove  {cur_conadd} {key_idx}\n", end='')
            del req_dict_total[key_idx]
        return
    requests_dict['isrequseting'] = True

    cur_conadd = requests_dict["req_params"]["address"]
    print(f"enter key_idx={key_idx} cur_conadd={cur_conadd}\n", end='')

    req_response = None
    arr_cur_txhash = requests_dict["arr_txhash"]

    req_url = "https://api.solana.fm/v0/transfers"
    payload = {
        "transactionHashes": arr_cur_txhash
    }
    try:
        req_response = requests.post(
            req_url,  json=payload, timeout=requests_dict['timeout'], headers=baseclass.solana_fm_headers)
        time.sleep(0.2)

    except Exception as e:
        print(f"cur_conadd= {cur_conadd} errmsg={ str(e)}")
        if (" Max retries exceeded" in str(e)):
            time.sleep(2+random.random())
        requests_dict['timeout'] = 15
        requests_dict['isrequseting'] = False
        return
    requests_dict["req_response"] = req_response
    write_tokens_path_name = baseclass.dalao_transfer_solanafm_path / \
        f"{cur_conadd}.json"
    # 请求结果不成功
    if requests_dict["req_response"].status_code != 200:
        print(
            f"cur_conadd= {cur_conadd} response status_code= {requests_dict['req_response'].status_code}")
        if requests_dict["req_response"].status_code == 429:
            time.sleep(0.6)
        elif requests_dict["req_response"].status_code == 400:
            print("error 400 payload=",payload )
            raise Exception("400 error")
             

        requests_dict['isrequseting'] = False

        return

    # 如果請求結果為成功
    tokenresponse = json.loads(
        requests_dict["req_response"].text)
    # 結果不正常  continue
    if tokenresponse["status"] != "success":
        print(f"key_idx= {key_idx} response is 200 but status not success")
        requests_dict["remainder_retry_times"] -= 1
        requests_dict['isrequseting'] = False
        if requests_dict["remainder_retry_times"] < 0:
            raise Exception(f"key_idx={key_idx} retrytimes<0")
        return

    # 結果正常 獲取txlist
    txlist = None
    txlist = tokenresponse["result"]
    if (txlist == None or len(txlist) == 0):
        print(f"loop={loop} add={cur_conadd} txlist={txlist} arr_cur_txhash={arr_cur_txhash}")

        requests_dict["need_remove"] = True
        if req_dict_total.get(key_idx) is not None:
            print(f"remove {cur_conadd} {key_idx}\n", end='')
            del req_dict_total[key_idx]
        requests_dict['isrequseting'] = False
        return

    print(
        f"loop={loop} add={cur_conadd}  txhash_len={len(arr_cur_txhash)} real_len={len(txlist)} diflen={len(arr_cur_txhash) -len(txlist)  }")
    if True:
        # 如果此次請求結果不是最大offset，請求了全部結果，保存文本
        requests_dict["need_remove"] = True
        if req_dict_total.get(key_idx) is not None:
            print(f"remove {cur_conadd} {key_idx}\n", end='')
            del req_dict_total[key_idx]

        if (len(txlist) == 0):
            requests_dict['isrequseting'] = False
            return

        cur_file = []
        if not write_tokens_path_name.exists():
            print(f"loop={loop} {cur_conadd} 第一次文件\n", end='')

        else:
            with write_tokens_path_name.open(mode="r") as f:
                cur_file = json.load(f)

        cur_file = cur_file + txlist
        print(f"{cur_conadd} 全部写入\n", end='')
        with write_tokens_path_name.open(mode='w') as f:
            json.dump(cur_file, f)

        requests_dict['isrequseting'] = False
        return

    return


def getonetran(address_list):

    print(f"enter getonetran  ")
    req_dict_total = {}
    number_key_idx = 0
    for address in (address_list):
        arr_txhash = obj_dalao_2_txhash[address]
        while (len(arr_txhash) > 0):
            cur_arr_txhash = arr_txhash[0:50]
            arr_txhash = arr_txhash[50:]
            number_key_idx += 1
            key_idx = str(number_key_idx)
            req_dict = {
                "req_params": {"address": address, },
                "timeout": 10,

                "key_idx": key_idx,
                "arr_txhash": cur_arr_txhash,
                "remainder_retry_times": 3,
                "isrequseting": False,
                "need_remove": False,
            }
            req_dict_total[key_idx] = req_dict

    loop = 0
    while (len(req_dict_total.keys()) > 0):
        loop += 1
        # 獲取可以同步請求的address長度 ，traders 長都可能小於 requests_dict定義的長度
        # grequest_len 為 requests_dict長度和實際tokencontracts長度取最小值
        print(
            f"remainder_address_len :{len(req_dict_total.keys())}")

        temp_split_req_dict_total_list = list(req_dict_total.keys())
        temp_split_req_dict_total_list = temp_split_req_dict_total_list[0:10]

        temp_req_dict_total_keys_list = []
        for key_idx in temp_split_req_dict_total_list:
            temp_req_dict_total_keys_list.append(key_idx)
        # 進行異步請求
        i = 0

        for key_idx in temp_req_dict_total_keys_list:
            i += 1
            request_onetime(req_dict_total,  key_idx,   loop)
            time.sleep(0.2)

        time.sleep(0.3)

    return


def get_3trans_byScan(address_list):

    # 此方法獲取 從bscapi獲取的 的3trans
    # 有 requests_3trans_dict 和requests_tokenadd_dict兩種類型對應contractaddress和address
    # 使用grequests 進行異步請求獲取
    # offsettimes_max 為請求的數據次數，最大總數為 offsettimes_max*offset (offset 為params的offset)
    # param_sort 為請求參數params 的sort
    print("enter get_3trans_byScan_()")
    contractadd_tokentx_list = copy.deepcopy(address_list)
    getonetran(address_list=contractadd_tokentx_list,
               )

    return


df = pd.read_excel(baseclass.dalao_total_ana_fm_path /
                 "anaing_dalao.xlsx", dtype=object)

temp_arr_str_dalaoaddress = df['add'].tolist()
temp_arr_str_dalaoaddress.append(baseclass.mywalletaddress)
obj_dalao_2_txhash = {

}
arr_str_dalaoaddress = []
for str_dalaoaddress in temp_arr_str_dalaoaddress:

    if not (baseclass.dalao_tran_txhash_path/f"txhash_{str_dalaoaddress}.csv").exists():
        continue
    arr_str_dalaoaddress.append(str_dalaoaddress)
    df = pd.read_csv(baseclass.dalao_tran_txhash_path /
                     f"txhash_{str_dalaoaddress}.csv", dtype=object)
    arr_txhash = df["txhash"].tolist()
    obj_dalao_2_txhash[str_dalaoaddress] = arr_txhash
    arr_exist_txhash = []
    dalao_transfere_fm_file = baseclass.dalao_transfer_solanafm_path / \
        f"{str_dalaoaddress}.json"
    if not dalao_transfere_fm_file.exists():
        continue
    try:
        with dalao_transfere_fm_file.open(mode='r',encoding='utf-8') as f:
            arr_obj_dalao_transaction = json.load(f)
    except Exception as e:
        print(f"json_read_error str_dalaoaddress={str_dalaoaddress}")
        raise
    for obj_dalao_transaction in arr_obj_dalao_transaction:
        txhash = obj_dalao_transaction["transactionHash"]
        arr_exist_txhash.append(txhash)
    arr_txhash = list(set(arr_txhash) - set(arr_exist_txhash))
    print("arr_txhash=",str_dalaoaddress,len(arr_txhash))
    if len(arr_txhash)==0:
        del obj_dalao_2_txhash[str_dalaoaddress]
        arr_str_dalaoaddress.remove(str_dalaoaddress)
        
        continue
    obj_dalao_2_txhash[str_dalaoaddress] = arr_txhash

# print(f"arr_str_dalaoaddress_len= {len(arr_str_dalaoaddress)}")
get_3trans_byScan(address_list=arr_str_dalaoaddress,
                  )


print(f"{'{:<6}'.format('END')} {baseclass.scriptfilename} ----------------NOTE-----------NOTE---------------")
