import os, sys
import ping3
import random
import socket
import hashlib
import logging
sys.path.append(os.path.dirname(os.path.dirname(sys.path[0])))  # 上级目录
from amazon_spider.conf.fidle_length import inner_item_fidle


def convert_str(data):
    """covert data.

    :param data:
    :return: string
    """

    if isinstance(data, bytes):
        return data.decode()
    if isinstance(data, dict):
        return dict(map(convert_str, data.items()))
    if isinstance(data, tuple):
        return map(convert_str, data)
    if isinstance(data, list):
        return data[0].decode()
    return data


def md5(src: str, algorithm: str = "md5", digits: int = 32) -> str:
    """md5 algorithms.

    :param src: original string.
    :param algorithm: algorithm method.
    :param digits: 16 length or 32 length.
    :return: string.
    """

    algorithm = hashlib.new(algorithm)
    algorithm.update(src.encode('utf8'))
    if digits == 16:
        return algorithm.hexdigest()[8:24]
    else:
        return algorithm.hexdigest()


def random_request_priority(request):
    """random request priority.

    :param request: request.
    :return: priority.
    """

    priority = request.priority
    if 0 <= priority <= 200:
        priority = random.randint(100, 200)
        request.priority = priority


def singleton(cls, *args, **kw):
    """singleton mode.

    :param cls: classname
    :param args: args.
    :param kw: kwargs.
    :return:
    """

    instances = {}

    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return _singleton


def field_length_dispose(inner_item):
    for k, v in inner_item_fidle.items():
        if inner_item.get(k):
            if len(inner_item.get(k)) > v:
                inner_item[k] = inner_item[k][0:v]
    return inner_item


def cleanup_file_descriptors():
    # 示例：关闭当前进程所有打开的文件
    pid = os.getpid()
    fd_dir = f"/proc/{pid}/fd"
    for fd in os.listdir(fd_dir):
        try:
            fd_path = os.path.join(fd_dir, fd)
            if os.path.islink(fd_path):  # 确保是符号链接
                os.close(int(fd))  # 关闭文件描述符
                logging.info(f"已关闭文件描述符: {fd}")
        except Exception as e:
            logging.info(f"关闭文件描述符 {fd} 失败: {e}")

def is_internet_available(host="www.baidu.com"):
    """
    使用 ping 命令检测网络连通性。
    默认使用 Google 的公共 DNS 服务器 (8.8.8.8) 进行测试。
    """
    ping3.EXCEPTIONS = True
    try:
        ip_address = socket.gethostbyname(host)
        response_time = ping3.ping(ip_address)
        logging.info(f"网络连接正常，Ping {host} 成功")
        return True
    except ping3.errors.HostUnknown:  # Specific error is catched.
        logging.info("Host unknown error raised.")
        return False
    except ping3.errors.PingError:  # All ping3 errors are subclasses of `PingError`.
        logging.info("A ping error raised.")
        return False
    except ping3.errors.Timeout:
        logging.info("A ping Timeout error raised.")
        return False
    except Exception as e:
        logging.info(f"ping error {e}")
        return False
        # if not response_time:
        #     logging.info(f"网络连接异常，Ping {host} 失败 {response_time}")
        #     return False
        # else:
        #     logging.info(f"网络连接正常，Ping {host} 成功")
        #     return True


# is_internet_available()