import  base64, json,os
import pandas as pd
import inspect,urllib
import random
import string
from datetime import datetime
import email.utils
from functools import wraps
from WebsocketTest.common.logger import *
from typing import Optional, Union, Literal
import numpy as np
def get_rfc1123_time():
        # 获取当前UTC时间
        now = datetime.utcnow()
        # 将时间格式化为RFC1123格式
        rfc1123_time = email.utils.format_datetime(now)
        return rfc1123_time

def generate_random_string(length=32):
    """
    生成指定长度的随机字符串，该字符串可以从包含小写字母、数字以及'@'符号的字符集中随机选择。
    
    Args:
        length (int): 生成字符串的长度，默认为32。
    
    Returns:
        str: 生成的随机字符串。
    """
    if length < 1:
        raise ValueError("Length must be at least 1.")
    
    # 定义字符池：包含小写字母、数字和 '@' 符号
    chars = string.ascii_lowercase + string.digits + "@"
    
    # 从字符池中随机选择指定数量的字符
    random_chars = random.choices(chars, k=length)
    
    return ''.join(random_chars)

def decode_unicode_escape(data):
    """
    递归地遍历字典或列表，将所有字符串值中的Unicode转义序列解码为原始字符。
    
    Args:
        data (dict or list): 包含Unicode转义序列的JSON对象（字典或列表）。
    
    Returns:
        dict or list: 解码后的JSON对象，其中所有字符串值已被正确解码。
    """
    if isinstance(data, dict):
        return {key: decode_unicode_escape(value) for key, value in data.items()}
    elif isinstance(data, list):
        return [decode_unicode_escape(element) for element in data]
    elif isinstance(data, str):
        try:
            # 使用 json.loads 来解析包含转义字符的字符串
            return json.loads(f'"{data}"')
        except json.JSONDecodeError:
            # 如果字符串不是有效的JSON字符串，则直接返回原字符串
            return data
    else:
        # 对于其他类型的数据，直接返回它们
        return data

def convert_to_json(data):
    """
    将包含Unicode转义序列的JSON数据解码，并返回JSON格式的字符串。
    
    Args:
        data (dict or list): 包含Unicode转义序列的JSON对象（字典或列表）。
    
    Returns:
        str: 解码并格式化后的JSON字符串。
    """
    decoded_data = decode_unicode_escape(data)
    return json.dumps(decoded_data, ensure_ascii=False, indent=4)
    
def encode_base64(
    s: Optional[Union[str, bytes]],
    *,
    input_encoding: Literal['auto', 'str', 'bytes'] = 'auto',
    output_encoding: str = 'utf-8'
) -> Optional[str]:
    """将字符串或字节数据编码为 Base64 格式
    
    Args:
        s: 要编码的输入数据，可以是字符串或字节，None 直接返回 None
        input_encoding: 输入处理模式：
            'auto' - 自动检测类型（默认）
            'str' - 强制作为字符串处理
            'bytes' - 强制作为字节处理
        output_encoding: 输出结果的编码格式（默认utf-8）
    
    Returns:
        Base64 编码后的字符串，如果输入为 None 则返回 None
    
    Raises:
        TypeError: 输入类型不符合要求
        ValueError: 编码失败或模式参数无效
    """
    if s is None:
        return None

    # 输入类型处理
    try:
        if input_encoding == 'str':
            data = s.encode('utf-8') if isinstance(s, str) else s
        elif input_encoding == 'bytes':
            data = s if isinstance(s, bytes) else str(s).encode('utf-8')
        elif input_encoding == 'auto':
            data = s.encode('utf-8') if isinstance(s, str) else s
        else:
            raise ValueError(f"Invalid input_encoding: {input_encoding}")
    except (AttributeError, UnicodeError) as e:
        raise ValueError(f"Input encoding failed: {str(e)}") from e

    if not isinstance(data, bytes):
        raise TypeError(f"Expected bytes or string, got {type(s).__name__}")

    # Base64 编码
    try:
        return base64.b64encode(data).decode(output_encoding)
    except UnicodeError as e:
        raise ValueError(f"Output decoding failed: {str(e)}") from e
def decode_base64(s):
    """将 Base64 编码的字符串解码回原始字符串"""
    return base64.b64decode(s.encode('utf-8')).decode('utf-8') if s is not None else None

def url_decode(str_):
    """
    解码URL编码的字符串。
    
    :param str_: URL编码的字符串
    :return: 解码后的字符串
    """
    return urllib.parse.unquote_plus(str_)  if str_ else None

def check_text_language(text):
    """
    检查文本是纯中文、纯英文还是中文加英文。
    
    :param text: 需要检查的文本
    :return: 文本的语言类型 ('纯中文', '纯英文', '中文+英文', '其他')
    """
    has_chinese = any('\u4e00' <= char <= '\u9fff' for char in text)
    has_english = any('a' <= char <= 'z' or 'A' <= char <= 'Z' for char in text)

    if has_chinese and has_english:
        return "中文+英文"
    elif has_chinese:
        return "纯中文"
    elif has_english:
        return "纯英文"
    else:
        return "其他"
    
def safe_get(data, keys, default=""):
    """ 安全地从嵌套字典中获取值 """
    for key in keys:
        try:
            data = data[key]
        except (KeyError, TypeError):
            return default
    return data

def append_msg_to_excel(file_path, **kwargs):
    try:
        # 检查文件是否存在
        if not os.path.exists(file_path):
            # 如果文件不存在，创建一个新的 DataFrame 并保存为 Excel 文件
            existing_df = pd.DataFrame()
        else:
            # 读取现有数据
            existing_df = pd.read_excel(file_path)

        # 动态构建 new_data 字典
        new_data = {**kwargs}

        # 将新数据转换为 DataFrame
        new_df = pd.DataFrame([new_data])

        # 追加新数据到现有数据
        updated_df = pd.concat([existing_df, new_df], ignore_index=True)

        # 写回 Excel 文件
        updated_df.to_excel(file_path, index=False)
    except Exception as e:
        # 获取当前文件名和方法名
        current_file = inspect.getfile(inspect.currentframe())
        current_function = inspect.currentframe().f_code.co_name
        print(f"An error occurred in file '{current_file}' and function '{current_function}': {e}")

def read_excel(file_path):
    df = pd.read_excel(file_path, header=0, dtype={'debug': str,'debugX': str})
    # 如果确实需要空字符串，先转换类型
    pd.set_option('future.no_silent_downcasting', True)
    df = df.astype(object).fillna("")  # 转换为object类型
    data_dict = df.to_dict(orient='records')
    return data_dict

def exception_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            # 直接使用被装饰函数的名字
            function_name = func.__name__
            file_name = os.path.basename(func.__code__.co_filename)  # 提取文件名
            # 打印异常和函数名
            logging.error( f"异常发生在文件 [{file_name}] 的函数 [{function_name}] 中: {str(e)}",
                exc_info=True  # 自动追加堆栈信息
                )
            # 可选择再次抛出异常或进行其他处理
            raise
    return wrapper
def merge_dicts(a: dict, b: dict) -> dict:
    """合并两个字典，重复key时优先取a中非空的值
    
    Args:
        a: 优先字典（保留其非空值）
        b: 后备字典（当a中的值为空时使用）
    
    Returns:
        合并后的新字典
    """
    return {
        # 遍历所有key（a和b的key取并集）
        k: 
            # 如果key在a中 且 a的value不是空值 → 取a的值
            a.get(k) if k in a and a.get(k) not in (None, "") 
            # 否则 → 取b的值（可能为None）
            else b.get(k)
        # 获取a和b的所有key的并集（避免用a|b需要Python 3.9+）
        for k in set(a) | set(b)
    }

def gen_case_suite(file_path):
    # 生成测试用例套件
    data_dict = read_excel(file_path)
    case_suite = []
    for case in data_dict:
        case_suite.append(case)
    return case_suite