#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName: ConvertUtils.py
 @DateTime: 2025/3/23 12:12
 @SoftWare: PyCharm
 @Author  ：xsh
"""
import datetime
import json
import yaml
from PyQt5 import Qt

class ConvertUtils:

    @staticmethod
    def toYaml(buffer) -> str:
        """将任意 Python 对象转换为 YAML 字符串"""
        return yaml.dump(buffer, allow_unicode=True, default_flow_style=False, Dumper=ConvertUtils._YamlDumper)

    @staticmethod
    def asYaml(buffer: str):
        """将 YAML 字符串转换为 Python 对象"""
        return yaml.safe_load(buffer)

    @staticmethod
    def toJson(buffer) -> str:
        """将任意 Python 对象转换为 JSON 字符串"""

        return json.dumps(buffer, default=ConvertUtils._convert_to_serializable)

    @staticmethod
    def asJson(buffer: str):
        """将 JSON 字符串转换为 Python 对象"""
        try:
            return json.loads(buffer, object_hook=ConvertUtils._convert_from_serializable)
        except json.JSONDecodeError as e:
            print(f"JSONDecodeError: {e}")
            return None
    @staticmethod
    def convert_to_serializable(obj):
        return ConvertUtils._convert_to_serializable(obj)

    @staticmethod
    def convert_from_serializable(dct):
        return ConvertUtils._convert_from_serializable(dct)

    @staticmethod
    def _convert_to_serializable(obj):
        """将不可序列化的对象转换为可序列化的格式"""
        if isinstance(obj, datetime.datetime):
            return ConvertUtils.DateTimeToString(obj)
        elif isinstance(obj, datetime.date):
            return ConvertUtils.DateToString(obj)
        elif isinstance(obj, datetime.time):
            return ConvertUtils.TimeToString(obj)
        elif isinstance(obj, Qt.QDateTime):
            return ConvertUtils.QDateTimeToString(obj)
        elif isinstance(obj, Qt.QDate):
            return ConvertUtils.QDateToString(obj)
        elif isinstance(obj, Qt.QTime):
            return ConvertUtils.QTimeToString(obj)
        elif isinstance(obj, dict):
            buffer: dict[str, object] = {}
            for key, value in obj.items():
                buffer[f"{key}"] = ConvertUtils._convert_to_serializable(value)
            return buffer
        elif isinstance(obj, list):
            buffer: list[obj] = []
            for value in obj:
                buffer.append(ConvertUtils._convert_to_serializable(value))
            return buffer
        elif isinstance(obj, tuple):
            buffer: list[obj] = []
            for value in obj:
                buffer.append(ConvertUtils._convert_to_serializable(value))
            return tuple(buffer)
        elif isinstance(obj, set):
            buffer: list[obj] = []
            for value in obj:
                buffer.append(ConvertUtils._convert_to_serializable(value))
            return set(buffer)
        else:
            return obj


    @staticmethod
    def _convert_from_serializable(dct):
        if ConvertUtils.is_isoformat_datetime(dct) or isinstance(dct, datetime.datetime):
            return ConvertUtils.StringToDateTime(dct)
        elif ConvertUtils.is_isoformat_date(dct) or isinstance(dct, datetime.date):
            return ConvertUtils.StringToDate(dct)
        elif ConvertUtils.is_isoformat_time(dct) or isinstance(dct, datetime.time):
            return ConvertUtils.StringToTime(dct)
        elif ConvertUtils.is_qt_datetime(dct) or isinstance(dct, Qt.QDateTime):
            return ConvertUtils.StringToQDateTime(dct)
        elif ConvertUtils.is_qt_date(dct) or isinstance(dct, Qt.QDate):
            return ConvertUtils.StringToQDate(dct)
        elif ConvertUtils.is_qt_time(dct) or isinstance(dct, Qt.QTime):
            return ConvertUtils.StringToQTime(dct)
        elif ConvertUtils.is_list_string(dct) or isinstance(dct, list):
            return ConvertUtils._convert_list_from_serializable(dct)
        elif ConvertUtils.is_dict_string(dct) or isinstance(dct, dict):
            return ConvertUtils._convert_dict_from_serializable(dct)
        elif ConvertUtils.is_bool(dct) or isinstance(dct, bool):
            return ConvertUtils.ObjectConvert(dct, bool)
        elif ConvertUtils.is_number(dct) or isinstance(dct, int):
            return ConvertUtils.ObjectConvert(dct, int)
        elif ConvertUtils.is_float(dct) or isinstance(dct, float):
            return ConvertUtils.ObjectConvert(dct, float)
        """将可序列化的格式转换回原始对象"""
        return dct

    @staticmethod
    def _convert_list_from_serializable(data):
        buffer: list[object]
        _buffer: list[object]
        if ConvertUtils.is_list_string(data):
            _buffer = ConvertUtils.ObjectConvert(data, list)
            if not isinstance(_buffer, list):
                return _buffer
        elif isinstance(data, list):
            _buffer = data
        else:
            return data
        buffer = []
        for value in _buffer:
            if isinstance(value, str):
                if ConvertUtils.is_isoformat_datetime(value):
                    buffer.append(ConvertUtils.StringToDateTime(value))
                elif ConvertUtils.is_isoformat_date(value):
                    buffer.append(ConvertUtils.StringToDate(value))
                elif ConvertUtils.is_isoformat_time(value):
                    buffer.append(ConvertUtils.StringToTime(value))
                elif ConvertUtils.is_qt_datetime(value):
                    buffer.append(ConvertUtils.StringToQDateTime(value))
                elif ConvertUtils.is_qt_date(value):
                    buffer.append(ConvertUtils.StringToQDate(value))
                elif ConvertUtils.is_qt_time(value):
                    buffer.append(ConvertUtils.StringToQTime(value))
                elif ConvertUtils.is_list_string(value):
                    buffer.append(ConvertUtils._convert_list_from_serializable(value))
                elif ConvertUtils.is_dict_string(value):
                    buffer.append(ConvertUtils._convert_dict_from_serializable(value))
                elif ConvertUtils.is_bool(value):
                    buffer.append(ConvertUtils.ObjectConvert(value, bool))
                elif ConvertUtils.is_number(value):
                    buffer.append(ConvertUtils.ObjectConvert(value, int))
                elif ConvertUtils.is_float(value):
                    buffer.append(ConvertUtils.ObjectConvert(value, float))
                else:
                    buffer.append(value)
            elif isinstance(value, list):
                buffer.append(ConvertUtils._convert_list_from_serializable(value))
            elif isinstance(value, dict):
                buffer.append(ConvertUtils._convert_dict_from_serializable(value))
            else:
                buffer.append(value)

        return buffer

    @staticmethod
    def _convert_dict_from_serializable(data):
        buffer: dict[str, object]
        _buffer: dict[str, object]
        if isinstance(data, dict):
            _buffer = data
        elif ConvertUtils.is_dict_string(data):
            _buffer = ConvertUtils.ObjectConvert(data, dict)
            if not isinstance(_buffer, dict):
                return _buffer
        else:
            return data
        buffer = {}
        for key, value in _buffer.items():
            if isinstance(value, str):
                if ConvertUtils.is_isoformat_datetime(value):
                    buffer[key] = ConvertUtils.StringToDateTime(value)
                elif ConvertUtils.is_isoformat_date(value):
                    buffer[key] = ConvertUtils.StringToDate(value)
                elif ConvertUtils.is_isoformat_time(value):
                    buffer[key] = ConvertUtils.StringToTime(value)
                elif ConvertUtils.is_qt_datetime(value):
                    buffer[key] = ConvertUtils.StringToQDateTime(value)
                elif ConvertUtils.is_qt_date(value):
                    buffer[key] = ConvertUtils.StringToQDate(value)
                elif ConvertUtils.is_qt_time(value):
                    buffer[key] = ConvertUtils.StringToQTime(value)
                elif ConvertUtils.is_list_string(value):
                    buffer[key] = ConvertUtils._convert_list_from_serializable(value)
                elif ConvertUtils.is_dict_string(value):
                    buffer[key] = ConvertUtils._convert_dict_from_serializable(value)
                elif ConvertUtils.is_bool(value):
                    buffer[key] = ConvertUtils.ObjectConvert(value, bool)
                elif ConvertUtils.is_number(value):
                    buffer[key] = ConvertUtils.ObjectConvert(value, int)
                elif ConvertUtils.is_float(value):
                    buffer[key] = ConvertUtils.ObjectConvert(value, float)
                else:
                    buffer[key] = value
            elif isinstance(value, list):
                buffer[key] = ConvertUtils._convert_list_from_serializable(value)
            elif isinstance(value, dict):
                buffer[key] = ConvertUtils._convert_dict_from_serializable(value)
            else:
                buffer[key] = value
        return buffer

    @staticmethod
    def is_bool(value: str) -> bool:
        """判断字符串是否可以转换为布尔值"""
        if isinstance(value, (int, bool)):
            return True
        if not isinstance(value, str):
            return False
        value = value.strip().lower()
        return value in {"true", "false", "1", "0", "yes", "no"}

    @staticmethod
    def is_float(value: str) -> bool:
        """判断字符串是否可以转换为浮点数"""
        if isinstance(value, (int, float)):
            return True
        try:
            float(value)
            return True
        except ValueError:
            return False

    @staticmethod
    def is_number(value: str) -> bool:
        """判断字符串是否可以转换为数字（整数或浮点数）"""
        if isinstance(value, (int, float)):
            return True
        try:
            float(value)
            return True
        except ValueError:
            return False

    @staticmethod
    def is_list_string(string: str) -> bool:
        """
        判断字符串是否可以转换为list
        :param string: 要检查的字符串
        :return: 如果可以转换为list返回True，否则返回False
        """
        if isinstance(string, list):
            return True
        if not isinstance(string, str) or len(string) <= 0:
            return False
        try:
            data = json.loads(string)
            return isinstance(data, list)
        except json.JSONDecodeError:
            return False

    @staticmethod
    def is_dict_string(string: str) -> bool:
        """
        判断字符串是否可以转换为dict
        :param string: 要检查的字符串
        :return: 如果可以转换为dict返回True，否则返回False
        """
        if isinstance(string, dict):
            return True
        if not isinstance(string, str) or len(string) <= 0:
            return False
        try:
            data = json.loads(string)
            return isinstance(data, dict)
        except json.JSONDecodeError:
            return False
    @staticmethod
    def asBool(value: str) -> bool:
        """判断字符串是否可以转换为布尔值"""
        if ConvertUtils.is_bool(value):
            return value.strip().lower() in {"true", "1", "yes", "True"}
        return False
    @staticmethod
    def asFloat(value: str) -> float:
        """判断字符串是否可以转换为浮点数"""
        if ConvertUtils.is_float(value):
            return float(value)
        return 0.0

    @staticmethod
    def asNumber(value: str) -> int:
        """判断字符串是否可以转换为数字（整数或浮点数）"""
        if ConvertUtils.is_float(value):
            return int(value)
        return 0

    @staticmethod
    def is_isoformat_datetime(value: str) -> bool:
        """检查字符串是否为 ISO 格式的 datetime"""
        if isinstance(value, datetime.datetime):
            return True
        if not isinstance(value, str):
            return False
        try:
            datetime.datetime.fromisoformat(value)
            return True
        except Exception as e:
            return False

    @staticmethod
    def is_isoformat_date(value: str) -> bool:
        """检查字符串是否为 ISO 格式的 date"""
        if isinstance(value, datetime.date):
            return True
        if not isinstance(value, str):
            return False
        try:
            datetime.date.fromisoformat(value)
            return True
        except ValueError:
            return False

    @staticmethod
    def is_isoformat_time(value: str) -> bool:
        """检查字符串是否为 ISO 格式的 time"""
        if isinstance(value, datetime.time):
            return True
        if not isinstance(value, str):
            return False
        try:
            datetime.time.fromisoformat(value)
            return True
        except ValueError:
            return False

    @staticmethod
    def is_qt_datetime(value: str) -> bool:
        if isinstance(value, Qt.QDateTime):
            return True
        if not isinstance(value, str):
            return False
        try:
            """检查字符串是否为 Qt 格式的 QDateTime"""
            return Qt.QDateTime.fromString(value, "yyyy-MM-dd hh:mm:ss").isValid()
        except ValueError:
            return False


    @staticmethod
    def is_qt_date(value: str) -> bool:
        if isinstance(value, Qt.QDate):
            return True
        if not isinstance(value, str):
            return False

        """检查字符串是否为 Qt 格式的 QDate"""
        try:
            return Qt.QDate.fromString(value, "yyyy-MM-dd").isValid()
        except ValueError:
            return False

    @staticmethod
    def is_qt_time(value: str) -> bool:
        if isinstance(value, Qt.QTime):
            return True
        if not isinstance(value, str):
            return False
        """检查字符串是否为 Qt 格式的 QTime"""
        try:
            return Qt.QTime.fromString(value, "hh:mm:ss").isValid()
        except ValueError:
            return False


    class _YamlDumper(yaml.Dumper):
        """自定义 YAML Dumper 以处理日期时间类型"""
        def represent_datetime(self, data):
            return self.represent_scalar('tag:yaml.org,2002:timestamp', data.isoformat())

        def represent_date(self, data):
            return self.represent_scalar('tag:yaml.org,2002:date', data.isoformat())

        def represent_time(self, data):
            return self.represent_scalar('tag:yaml.org,2002:timestamp', data.isoformat())

        def represent_qdatetime(self, data):
            return self.represent_scalar('tag:yaml.org,2002:timestamp', data.toString("yyyy-MM-dd hh:mm:ss"))

        def represent_qdate(self, data):
            return self.represent_scalar('tag:yaml.org,2002:date', data.toString("yyyy-MM-dd"))

        def represent_qtime(self, data):
            return self.represent_scalar('tag:yaml.org,2002:timestamp', data.toString("hh:mm:ss"))

    _YamlDumper.add_representer(datetime.datetime, _YamlDumper.represent_datetime)
    _YamlDumper.add_representer(datetime.date, _YamlDumper.represent_date)
    _YamlDumper.add_representer(datetime.time, _YamlDumper.represent_time)
    _YamlDumper.add_representer(Qt.QDateTime, _YamlDumper.represent_qdatetime)
    _YamlDumper.add_representer(Qt.QDate, _YamlDumper.represent_qdate)
    _YamlDumper.add_representer(Qt.QTime, _YamlDumper.represent_qtime)
    @staticmethod
    def DateTimeToString(value: datetime.datetime) -> str:
        """将 datetime.datetime 对象转换为字符串"""
        return value.strftime("%Y-%m-%d %H:%M:%S")

    @staticmethod
    def StringToDateTime(value: str) -> datetime.datetime:
        """将字符串转换为 datetime.datetime 对象"""
        try:
            return datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
        except Exception as e:
            return datetime.datetime.now()

    @staticmethod
    def DateToString(value: datetime.date) -> str:
        """将 datetime.date 对象转换为字符串"""
        return value.strftime("%Y-%m-%d")

    @staticmethod
    def StringToDate(value: str) -> datetime.date:
        """将字符串转换为 datetime.date 对象"""

        try:
            return datetime.datetime.strptime(value, "%Y-%m-%d").date()
        except Exception as e:
            return datetime.datetime.now().date()

    @staticmethod
    def TimeToString(value: datetime.time) -> str:
        """将 datetime.time 对象转换为字符串"""
        return value.strftime("%H:%M:%S")

    @staticmethod
    def StringToTime(value: str) -> datetime.time:
        """将字符串转换为 datetime.time 对象"""
        try:
            return datetime.datetime.strptime(value, "%H:%M:%S").time()
        except Exception as e:
            return datetime.datetime.now().time()

    @staticmethod
    def QDateTimeToString(value: Qt.QDateTime) -> str:
        """将 Qt.QDateTime 对象转换为字符串"""
        return value.toString("yyyy-MM-dd hh:mm:ss")

    @staticmethod
    def StringToQDateTime(value: str) -> Qt.QDateTime:
        """将字符串转换为 Qt.QDateTime 对象"""
        try:
            return Qt.QDateTime.fromString(value, "yyyy-MM-dd hh:mm:ss")
        except Exception as e:
            return Qt.QDateTime.currentDateTime()

    @staticmethod
    def QDateToString(value: Qt.QDate) -> str:
        """将 Qt.QDate 对象转换为字符串"""
        return value.toString("yyyy-MM-dd")

    @staticmethod
    def StringToQDate(value: str) -> Qt.QDate:
        """将字符串转换为 Qt.QDate 对象"""
        try:
            return Qt.QDate.fromString(value, "yyyy-MM-dd")
        except Exception as e:
            return Qt.QDate.currentDate()

    @staticmethod
    def asPath(value: Qt.QDate) -> str:
        return value.toString("yyyy_MM_dd")

    @staticmethod
    def asString(value: str) -> Qt.QDate:
        try:
            return Qt.QDate.fromString(value, "yyyy_MM_dd")
        except Exception as e:
            return Qt.QDate.currentDate()

    @staticmethod
    def QTimeToString(value: Qt.QTime) -> str:
        """将 Qt.QTime 对象转换为字符串"""
        return value.toString("hh:mm:ss")

    @staticmethod
    def StringToQTime(value: str) -> Qt.QTime:
        """将字符串转换为 Qt.QTime 对象"""
        try:
            return Qt.QTime.fromString(value, "hh:mm:ss")
        except Exception as e:
            return Qt.QTime.currentTime()


    @staticmethod
    def is_serialize(buffer) -> bool:
        """判断对象 buffer 是否可以被 JSON 序列化"""
        try:
            json.dumps(buffer, default=ConvertUtils._convert_to_serializable)
            return True
        except (TypeError, ValueError):
            return False

    @staticmethod
    def serialize(buffer: dict[str, object]) -> dict[str, object]:
        return ConvertUtils.asJson(ConvertUtils.toJson(buffer))
        
    @staticmethod
    def asArray(buffer: list[object]) -> str:
        """将字符串 buffer 转换为数组"""
        return ConvertUtils.toJson(buffer)
        
    @staticmethod
    def toArray(buffer: str) -> list[object]:
        """将字符串 buffer 转换为数组"""
        result = ConvertUtils.asJson(buffer)
        if isinstance(result, list):
            return result
        else:
            return []

    @staticmethod
    def KwargsToDict(kwargs: dict) -> dict[str, object]:
        """
        Convert kwargs dictionary to dict[str, object]

        Args:
            kwargs: Input keyword arguments dictionary

        Returns:
            dict[str, object]: Converted dictionary
        """
        try:
            # kwargs is already a dict, just need to ensure all keys are strings
            return {str(key): value for key, value in kwargs.items()}
        except Exception as e:
            print(f"Error converting kwargs to dict: {e}")
            return {}

    @staticmethod
    def ObjectConvert(buffer: object, result_type: type):
        if buffer is None or result_type is None:
            return None
        try:
            if result_type is int:
                if isinstance(buffer, int):
                    return buffer
                else:
                    return int(buffer)
            elif result_type is float:
                if isinstance(buffer, float):
                    return buffer
                else:
                    return float(buffer)
            elif result_type is str:
                return f"{buffer}"
            elif result_type is bool:
                if isinstance(buffer, bool):
                    return buffer
                else:
                    return f"{buffer}" in (True, 1, 'true', '1', 't', 'y', 'yes', 'True')
            elif result_type is list:
                if isinstance(buffer, str):
                    return json.loads(buffer)
                elif isinstance(buffer, list):
                    return buffer
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to list")
            elif result_type is dict:
                if isinstance(buffer, str):
                    return json.loads(buffer)
                elif isinstance(buffer, dict):
                    return buffer
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to dict")
            elif result_type is datetime.datetime:
                if isinstance(buffer, str):
                    return datetime.datetime.strptime(buffer, "%Y-%m-%d %H:%M:%S")
                elif isinstance(buffer, datetime.datetime):
                    return buffer
                elif isinstance(buffer, Qt.QDateTime):
                    return buffer.toPyDateTime()
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to datetime")
            elif result_type is datetime.date:
                if isinstance(buffer, str):
                    return datetime.datetime.strptime(buffer, "%Y-%m-%d").date()
                elif isinstance(buffer, datetime.date):
                    return buffer
                elif isinstance(buffer, Qt.QDate):
                    return buffer.toPyDate()
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to date")
            elif result_type is datetime.time:
                if isinstance(buffer, str):
                    return datetime.time.fromisoformat(buffer)
                elif isinstance(buffer, datetime.time):
                    return buffer
                elif isinstance(buffer, Qt.QTime):
                    return buffer.toPyTime()
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to time")
            elif result_type is Qt.QDateTime:
                if isinstance(buffer, str):
                    return Qt.QDateTime.fromString(buffer, "yyyy-MM-dd HH:mm:ss")
                elif isinstance(buffer, Qt.QDateTime):
                    return buffer
                elif isinstance(buffer, datetime.datetime):
                    return Qt.QDateTime(buffer.year, buffer.month, buffer.day, buffer.hour, buffer.minute, buffer.second)
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to QDateTime")
            elif result_type is Qt.QDate:
                if isinstance(buffer, str):
                    return Qt.QDate.fromString(buffer, "yyyy-MM-dd")
                elif isinstance(buffer, Qt.QDate):
                    return buffer
                elif isinstance(buffer, datetime.date):
                    return Qt.QDate(buffer.year, buffer.month, buffer.day)
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to QDate")
            elif result_type is Qt.QTime:
                if isinstance(buffer, str):
                    return Qt.QTime.fromString(buffer, "HH:mm:ss")
                elif isinstance(buffer, Qt.QTime):
                    return buffer
                elif isinstance(buffer, datetime.time):
                    return Qt.QTime(buffer.hour, buffer.minute, buffer.second)
                else:
                    raise ValueError(f"Cannot convert {type(buffer)} to QTime")
            else:
                raise ValueError(f"Unsupported result type: {result_type}")
        except Exception as e:
            print(f"Error converting {buffer} to {result_type}: {e}")
            return None