import operator
from Crypto.Cipher import AES
from Crypto.Util import Counter
import base64
from typing import Dict, Any, Union
key = bytes([45, 67, 89, 12, 34, 56, 78, 90, 123, 234, 45, 67, 89, 12, 34, 56])

def aes_ctr_encrypt(plaintext,nonce,key=key):
    # ctr = Counter.new(128, initial_value=int.from_bytes(nonce, byteorder='big'))
    # cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
    # ciphertext = cipher.encrypt(plaintext)
    # return ciphertext

    ctr = Counter.new(128, initial_value=int.from_bytes(nonce, byteorder='big'))
    cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
    ciphertext = cipher.encrypt(plaintext)
    return ciphertext

def aes_ctr_decrypt(nonce, ciphertext,key=key):
    ctr = Counter.new(128, initial_value=int.from_bytes(nonce, byteorder='big'))
    cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
    plaintext = cipher.decrypt(ciphertext)
    return plaintext


def decode__(b64_text):
    decoded_bytes = base64.b64decode(b64_text)
    ascii_byte_list = list(decoded_bytes)
    x_net_header = ascii_byte_list[0] + ascii_byte_list[5] + 4
    the_header = ascii_byte_list[:x_net_header]
    nonce = ascii_byte_list[x_net_header:x_net_header + 16]
    ciphertext = ascii_byte_list[(x_net_header + 16):]
    return the_header, nonce, aes_ctr_decrypt(bytes(nonce), bytes(ciphertext))


def decode_byte_to_dict(bytestext):
    def parse_data(data):
        pos = 0
        result = {}
        while pos < len(data):
            if pos + 1 > len(data):
                break
            key_length = data[pos]
            pos += 1
            if pos + key_length > len(data):
                break
            key = data[pos:pos + key_length].decode('utf-8')
            pos += key_length
            if pos + 2 > len(data):
                break
            value_length_part1 = data[pos]
            value_length_part2 = data[pos + 1]
            value_length = value_length_part1 + value_length_part2 * 256
            pos += 2
            if pos + value_length > len(data):
                break
            value = data[pos:pos + value_length]
            pos += value_length
            if   ("i_c" not in result.keys() and key in ["d", "b", "p", "r", "q", "v", "w"]) or (key.startswith("i_") ):
                value = int.from_bytes(value, byteorder='little')
            else:
                try:
                    value = value.decode('utf-8')
                except:
                    pass
            result[key] = value
        return result

    dicts = parse_data(bytestext)
    if 'f' in dicts:
        dicts['f'] = parse_data(dicts['f'])
    return dicts


def jisuan(a1, a2, func):
    # 将值限制在 32 位范围内
    a1 = a1 & 0xFFFFFFFF
    a2 = a2 & 0xFFFFFFFF
    # 执行指定的位操作
    result = func(a1, a2) & 0xFFFFFFFF
    # 如果结果的最高位是 1，则这是一个负数
    if result & 0x80000000:
        result -= 0x100000000
    return result
def right3(value, shift):
    # js中value>>>shift
    if value < 0:
        value += 2 ** 32
    # 进行右移操作
    return (value >> shift) & (2 ** 32 - 1)


num1 = 1101195530
num2 = 1849170683
num3 = 1011462487
num4 = 1870552039
num5 = 2116561607
num6 = 1297822139
num7 = 495394314
num8 = 684556403
num9 = 1902634096
num10 = 37428903
num11 = 787769321
def encodechat(char, key):
    f1 = jisuan(key,  ord(char), operator.xor)

    a2 = jisuan(f1, 1, operator.lshift)
    a3 = right3(f1, 31)
    a4 = jisuan(a2, a3, operator.or_)
    f1 = jisuan(a4, num1, operator.xor)
    f1 = forfunc(f1, num1)
    f1 = forfunc(f1, num2)
    f1 = forfunc(f1, num3)
    f1 = forfunc(f1, num4)
    f1 = forfunc(f1, num5)
    f1 = forfunc(f1, num6)
    f1 = forfunc(f1, num7)
    f1 = forfunc(f1, num8)

    a2 = jisuan(f1, 1, operator.lshift)
    a3 = right3(f1, 31)
    a4 = jisuan(a2, a3, operator.or_)
    f1 = jisuan(a4, num2, operator.xor)
    f1 = forfunc(f1, num2)
    f1 = forfunc(f1, num3)
    f1 = forfunc(f1, num4)
    f1 = forfunc(f1, num5)
    f1 = forfunc(f1, num6)
    f1 = forfunc(f1, num7)
    f1 = forfunc(f1, num8)
    f1 = forfunc(f1, num9)

    a2 = jisuan(f1, 1, operator.lshift)
    a3 = right3(f1, 31)
    a4 = jisuan(a2, a3, operator.or_)
    f1 = jisuan(a4, num3, operator.xor)
    f1 = forfunc(f1, num3)
    f1 = forfunc(f1, num4)
    f1 = forfunc(f1, num5)
    f1 = forfunc(f1, num6)
    f1 = forfunc(f1, num7)
    f1 = forfunc(f1, num8)
    f1 = forfunc(f1, num9)
    f1 = forfunc(f1, num10)

    a2 = jisuan(f1, 1, operator.lshift)
    a3 = right3(f1, 31)
    a4 = jisuan(a2, a3, operator.or_)
    f1 = jisuan(a4, num4, operator.xor)
    f1 = forfunc(f1, num4)
    f1 = forfunc(f1, num5)
    f1 = forfunc(f1, num6)
    f1 = forfunc(f1, num7)
    f1 = forfunc(f1, num8)
    f1 = forfunc(f1, num9)
    f1 = forfunc(f1, num10)
    f1 = forfunc(f1, num11)

    return f1


def forfunc(a5, keys):
    a6 = jisuan(a5, 65535, operator.and_)
    a7 = jisuan(a5, keys, operator.xor)
    a8 = jisuan(a7, 65535, operator.and_)
    a9 = jisuan(a6, a8, operator.mul)
    a10 = jisuan(a9, 65535, operator.and_)
    a11 = right3(a5, 16)
    a12 = jisuan(a11, 65535, operator.and_)
    a13 = jisuan(a5, keys, operator.xor)
    a14 = right3(a13, 16)
    a15 = jisuan(a12, a14, operator.mul)
    a16 = jisuan(a15, 65535, operator.and_)
    a17 = jisuan(a10, 16, operator.lshift)
    a18 = a5 + a17
    a19 = a18 + a16
    a20 = right3(a19, 0)
    a21 = jisuan(a20, 15, operator.and_)
    a22 = a21 + 1
    a23 = right3(a20, a22)
    a24 = jisuan(a20, a23, operator.xor)
    return a24

def to_signed_32bit(value):
    # 将整数限制在 32 位范围内
    value = value & 0xFFFFFFFF
    # 如果最高位是1，将其解释为负数
    if value & 0x80000000:
        return value - 0x100000000
    else:
        return value

def hex_to_byte_list(hex_num):
    # 确保输入为整数
    if not isinstance(hex_num, int):
        raise ValueError("Input must be an integer")
    byte_list = [
        (hex_num >> 24) & 0xFF,  # 提取最高字节
        (hex_num >> 16) & 0xFF,  # 提取次高字节
        (hex_num >> 8) & 0xFF,  # 提取次低字节
        hex_num & 0xFF  # 提取最低字节
    ]
    return byte_list
def fnv1a_32(data):
    FNV_prime = 16777619
    offset_basis = 2166136261
    hash_value = offset_basis
    for byte in data:
        hash_value ^= byte
        hash_value *= FNV_prime
        # 确保哈希值保持在 32 位范围内
        hash_value &= 0xFFFFFFFF
    return hash_value

def in32(hash_value):
    if hash_value > 2147483647:
        return to_signed_32bit(hash_value)*-1
    else:
        return hash_value


def extendbytes(keystr, key):
    return len(str(keystr)).to_bytes(1, byteorder='little') + keystr.encode() + len(key).to_bytes(2,byteorder='little')  + key


def encode_dict_to_byte(dictcontent):
    bts = bytearray()
    d = dictcontent['d'].to_bytes(8, byteorder='little')
    a = dictcontent['a'].encode()
    b = dictcontent['b'].to_bytes(4, byteorder='little')
    c = dictcontent['c'].encode()
    e = dictcontent['e'].encode()
    p = dictcontent['p'].to_bytes(8, byteorder='little')
    g = dictcontent['g'].encode()
    h = dictcontent['h'].encode()
    n = dictcontent['n'].encode()
    o = dictcontent['o'].encode()
    q = dictcontent['q'].to_bytes(4, byteorder='little')
    r = dictcontent['r'].to_bytes(4, byteorder='little')
    s = dictcontent['s'].encode()
    t = dictcontent['t'].encode()
    u = dictcontent['u'].encode()
    v = dictcontent['v'].to_bytes(1, byteorder='little')
    x = dictcontent['x'].encode()
    z = dictcontent['z'].encode()
    f_i_c = dictcontent['f']['i_c'].to_bytes(1, byteorder='little')
    f_i_e = dictcontent['f']['i_e'].to_bytes(8, byteorder='little')
    f_i_n = dictcontent['f']['i_n'].to_bytes(1, byteorder='little')
    f_i_u = dictcontent['f']['i_u'].to_bytes(4, byteorder='little')
    f_i_r = dictcontent['f']['i_r'].to_bytes(1, byteorder='little')
    f_i_cl = dictcontent['f']['i_cl'].to_bytes(1, byteorder='little')
    f_i_ev = dictcontent['f']['i_ev'].to_bytes(8, byteorder='little')
    f_i_ps = dictcontent['f']['i_ps'].to_bytes(4, byteorder='little')
    f_uqid = dictcontent['f']['uqid'].encode()  # \x00
    f_fw = dictcontent['f']['fw'].encode()
    f_ua = dictcontent['f']['ua'].encode()
    f_rf = dictcontent['f']['rf'].encode()
    f_i_l = dictcontent['f']['i_l'].to_bytes(1, byteorder='little')
    f_z = dictcontent['f']['z'].encode()
    f_x = dictcontent['f']['x'].encode()
    f_i_z = dictcontent['f']['i_z'].to_bytes(1, byteorder='little')
    f_pi = dictcontent['f']['pi'].encode()
    f = bytearray()
    f.extend(extendbytes("i_c", f_i_c))
    f.extend(extendbytes("i_e", f_i_e))
    f.extend(extendbytes("i_n", f_i_n))
    f.extend(extendbytes("i_u", f_i_u))
    f.extend(extendbytes("i_r", f_i_r))
    f.extend(extendbytes("i_cl", f_i_cl))
    f.extend(extendbytes("i_ev", f_i_ev))
    f.extend(extendbytes("i_ps", f_i_ps))
    f.extend(extendbytes("uqid", f_uqid))
    f.extend(extendbytes("fw", f_fw))
    f.extend(extendbytes("ua", f_ua))
    f.extend(extendbytes("rf", f_rf))
    f.extend(extendbytes("i_l", f_i_l))
    f.extend(extendbytes("z", f_z))
    f.extend(extendbytes("x", f_x))
    f.extend(extendbytes("i_z", f_i_z))
    f.extend(extendbytes("pi", f_pi))

    bts.extend(extendbytes("d", d))
    bts.extend(extendbytes("a", a))
    bts.extend(extendbytes("b", b))
    bts.extend(extendbytes("c", c))
    bts.extend(extendbytes("e", e))
    bts.extend(extendbytes("p", p))
    bts.extend(extendbytes("g", g))
    bts.extend(extendbytes("h", h))
    bts.extend(extendbytes("n", n))
    bts.extend(extendbytes("o", o))
    bts.extend(extendbytes("q", q))
    bts.extend(extendbytes("r", r))
    bts.extend(extendbytes("s", s))
    bts.extend(extendbytes("t", t))
    bts.extend(extendbytes("u", u))
    bts.extend(extendbytes("v", v))
    bts.extend(extendbytes("x", x))
    bts.extend(extendbytes("z", z))
    bts.extend(len(str('f')).to_bytes(1, byteorder='little') +  "f".encode() + len(f).to_bytes(2,byteorder='little')  + f)

    return bts




def encode_dict_byte(dictcontent: Dict[str, Any]) -> bytes:
    """
    将字典数据编码为字节序列
    """
    bts = bytearray()

    # 编码各个字段
    if 'd' in dictcontent:
        d = dictcontent['d'].to_bytes(8, byteorder='little')
        bts.extend(extend_bytes("d", d))

    if 'a' in dictcontent:
        a = dictcontent['a'].encode('utf-8')
        bts.extend(extend_bytes("a", a))

    if 'b' in dictcontent:
        b = dictcontent['b'].to_bytes(4, byteorder='little')
        bts.extend(extend_bytes("b", b))

    if 'c' in dictcontent:
        c = dictcontent['c'].encode('utf-8')
        bts.extend(extend_bytes("c", c))

    if 'e' in dictcontent:
        e = dictcontent['e'].encode('utf-8')
        bts.extend(extend_bytes("e", e))

    if 'p' in dictcontent:
        p = dictcontent['p'].to_bytes(4, byteorder='little')  # 注意：示例中是4字节，不是8字节
        bts.extend(extend_bytes("p", p))

    if 'g' in dictcontent:
        g = dictcontent['g'].encode('utf-8')
        bts.extend(extend_bytes("g", g))

    if 'h' in dictcontent:
        h = dictcontent['h'].encode('utf-8')
        bts.extend(extend_bytes("h", h))

    if 'k' in dictcontent:
        k = dictcontent['k'].encode('utf-8')
        bts.extend(extend_bytes("k", k))

    if 'n' in dictcontent:
        n = dictcontent['n'].encode('utf-8')
        bts.extend(extend_bytes("n", n))

    if 'o' in dictcontent:
        o = dictcontent['o'].encode('utf-8')
        bts.extend(extend_bytes("o", o))

    if 'j' in dictcontent:
        j = dictcontent['j'].encode('utf-8')
        bts.extend(extend_bytes("j", j))

    if 'q' in dictcontent:
        q = dictcontent['q'].to_bytes(4, byteorder='little')
        bts.extend(extend_bytes("q", q))

    if 'r' in dictcontent:
        r = dictcontent['r'].to_bytes(4, byteorder='little')
        bts.extend(extend_bytes("r", r))

    if 's' in dictcontent:
        s = dictcontent['s'].encode('utf-8')
        bts.extend(extend_bytes("s", s))

    if 't' in dictcontent:
        t = dictcontent['t'].encode('utf-8')
        bts.extend(extend_bytes("t", t))

    if 'u' in dictcontent:
        u = dictcontent['u'].encode('utf-8')
        bts.extend(extend_bytes("u", u))

    if 'v' in dictcontent:
        v = dictcontent['v'].to_bytes(1, byteorder='little')
        bts.extend(extend_bytes("v", v))

    if 'w' in dictcontent:
        w = dictcontent['w'].to_bytes(8, byteorder='little')
        bts.extend(extend_bytes("w", w))

    if 'x' in dictcontent:
        x = dictcontent['x'].encode('utf-8')
        bts.extend(extend_bytes("x", x))

    if 'z' in dictcontent:
        z = dictcontent['z'].encode('utf-8')
        bts.extend(extend_bytes("z", z))

    # 编码嵌套的f字段
    if 'f' in dictcontent:
        f_data = encode_f_value(dictcontent['f'])
        bts.extend(len("f").to_bytes(1, byteorder='little'))
        bts.extend("f".encode('latin1'))
        bts.extend(len(f_data).to_bytes(2, byteorder='little'))
        bts.extend(f_data)

    return bytes(bts).decode('latin1')


def encode_f_value(f_content: Dict[str, Any]) -> bytes:
    """
    编码嵌套的f字段
    """
    f_bts = bytearray()

    # 编码f字段中的各个子字段
    if 'i_c' in f_content:
        i_c = f_content['i_c'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_c", i_c))

    if 'i_e' in f_content:
        i_e = f_content['i_e'].to_bytes(8, byteorder='little')
        f_bts.extend(extend_bytes("i_e", i_e))

    if 'i_n' in f_content:
        i_n = f_content['i_n'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_n", i_n))

    if 'i_u' in f_content:
        i_u = f_content['i_u'].to_bytes(2, byteorder='little')
        f_bts.extend(extend_bytes("i_u", i_u))

    if 'i_r' in f_content:
        i_r = f_content['i_r'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_r", i_r))

    if 'i_tf' in f_content:
        i_tf = f_content['i_tf'].to_bytes(8, byteorder='little')
        f_bts.extend(extend_bytes("i_tf", i_tf))

    if 'i_bt' in f_content:
        i_bt = f_content['i_bt'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_bt", i_bt))

    if 'i_cl' in f_content:
        i_cl = f_content['i_cl'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_cl", i_cl))

    if 'i_ev' in f_content:
        i_ev = f_content['i_ev'].to_bytes(8, byteorder='little')
        f_bts.extend(extend_bytes("i_ev", i_ev))

    if 'i_ps' in f_content:
        i_ps = f_content['i_ps'].to_bytes(4, byteorder='little')
        f_bts.extend(extend_bytes("i_ps", i_ps))

    if 'uqid' in f_content:
        uqid = f_content['uqid'].encode('utf-8')
        f_bts.extend(extend_bytes("uqid", uqid))

    if 'fw' in f_content:
        fw = f_content['fw'].encode('utf-8')
        f_bts.extend(extend_bytes("fw", fw))

    if 'uv' in f_content:
        uv = f_content['uv'].encode('utf-8')
        f_bts.extend(extend_bytes("uv", uv))

    if 'ur' in f_content:
        ur = f_content['ur'].encode('utf-8')
        f_bts.extend(extend_bytes("ur", ur))

    if 'pr' in f_content:
        pr = f_content['pr'].encode('utf-8')
        f_bts.extend(extend_bytes("pr", pr))

    if 'ua' in f_content:
        ua = f_content['ua'].encode('utf-8')
        f_bts.extend(extend_bytes("ua", ua))

    if 'rf' in f_content:
        rf = f_content['rf'].encode('utf-8')
        f_bts.extend(extend_bytes("rf", rf))

    if 'db' in f_content:
        db = f_content['db'].encode('utf-8')
        f_bts.extend(extend_bytes("db", db))

    if 'db2' in f_content:
        db2 = f_content['db2'].encode('utf-8')
        f_bts.extend(extend_bytes("db2", db2))

    if 'i_l' in f_content:
        i_l = f_content['i_l'].to_bytes(4, byteorder='little')
        f_bts.extend(extend_bytes("i_l", i_l))

    if 'i_z' in f_content:
        i_z = f_content['i_z'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_z", i_z))

    if 'i_fd' in f_content:
        i_fd = f_content['i_fd'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_fd", i_fd))

    if 'i_kp' in f_content:
        i_kp = f_content['i_kp'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_kp", i_kp))

    if 'i_sc' in f_content:
        i_sc = f_content['i_sc'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_sc", i_sc))

    if 'i_sd' in f_content:
        i_sd = f_content['i_sd'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_sd", i_sd))

    if 'i_sf' in f_content:
        i_sf = f_content['i_sf'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_sf", i_sf))

    if 'i_ks' in f_content:
        i_ks = f_content['i_ks'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_ks", i_ks))

    if 'i_ams' in f_content:
        i_ams = f_content['i_ams'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_ams", i_ams))

    if 'i_tm' in f_content:
        i_tm = f_content['i_tm'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_tm", i_tm))

    if 'i_smm' in f_content:
        i_smm = f_content['i_smm'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_smm", i_smm))

    if 'i_abta' in f_content:
        i_abta = f_content['i_abta'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_abta", i_abta))

    if 'i_bsc' in f_content:
        i_bsc = f_content['i_bsc'].to_bytes(8, byteorder='little')
        f_bts.extend(extend_bytes("i_bsc", i_bsc))

    if 'i_ct' in f_content:
        i_ct = f_content['i_ct'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_ct", i_ct))

    if 'i_rc' in f_content:
        i_rc = f_content['i_rc'].to_bytes(1, byteorder='little')
        f_bts.extend(extend_bytes("i_rc", i_rc))

    if 'pi' in f_content:
        pi = f_content['pi'].encode('utf-8')
        f_bts.extend(extend_bytes("pi", pi))

    if 'dm' in f_content:
        dm = f_content['dm'].encode('utf-8')
        f_bts.extend(extend_bytes("dm", dm))

    return bytes(f_bts)


def extend_bytes(field_name: str, value: Union[bytes, bytearray]) -> bytes:
    """
    将字段名和值编码为字节序列
    格式：字段名长度(1字节) + 字段名 + 值长度(2字节小端序) + 值
    """
    bts = bytearray()

    # 字段名长度和字段名
    bts.append(len(field_name))
    bts.extend(field_name.encode('latin1'))

    # 值长度和值
    value_length = len(value)
    bts.extend(value_length.to_bytes(2, byteorder='little'))
    bts.extend(value)

    return bytes(bts)











def extendbytes_to_bytes(keystr: str, value: bytes) -> bytes:
    """
    编码单个字段: 1字节key长度 + key + 2字节value长度 + value
    """
    return (
        len(keystr).to_bytes(1, byteorder='little')
        + keystr.encode()
        + len(value).to_bytes(2, byteorder='little')
        + value
    )


def encode_value(val):
    """
    自动将 int/str 转换为 bytes
    """
    if isinstance(val, int):
        if val > 0xFFFFFFFF:
            return val.to_bytes(8, 'little')
        elif val > 0xFF:
            return val.to_bytes(4, 'little')
        else:
            return val.to_bytes(1, 'little')
    elif isinstance(val, str):
        return val.encode()
    elif isinstance(val, bytes):
        return val
    else:
        return str(val).encode()


def encode_dict_to_bytearray(dictcontent: dict) -> bytearray:
    bts = bytearray()

    for k, v in dictcontent.items():
        if isinstance(v, dict):  # 子字典
            sub = bytearray()
            for kk, vv in v.items():
                sub.extend(extendbytes_to_bytes(kk, encode_value(vv)))
            bts.extend(extendbytes_to_bytes(k, sub))
        else:
            bts.extend(extendbytes_to_bytes(k, encode_value(v)))

    return bts









