"""
通用工具函数模块

提供项目中常用的工具函数，包括 UUID 生成、时间处理、数据验证等。
"""

import hashlib
import uuid
from datetime import datetime, timezone
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union


def generate_uuid() -> str:
    """
    生成唯一的 UUID 字符串

    Returns:
        UUID 字符串
    """
    return str(uuid.uuid4())


def validate_uuid(uuid_str: str) -> bool:
    """
    验证字符串是否为有效的 UUID

    Args:
        uuid_str: 要验证的字符串

    Returns:
        是否为有效的UUID
    """
    try:
        uuid.UUID(uuid_str)
        return True
    except (ValueError, TypeError):
        return False


def generate_short_id(length: int = 8) -> str:
    """
    生成短 ID（基于 UUID）

    Args:
        length: ID 长度

    Returns:
        短 ID 字符串
    """
    return str(uuid.uuid4()).replace("-", "")[:length]


def get_current_timestamp() -> str:
    """
    获取当前 UTC 时间戳（ISO 8601 格式）

    Returns:
        时间戳字符串
    """
    return datetime.now(timezone.utc).isoformat()


def get_current_datetime() -> datetime:
    """
    获取当前 UTC 时间

    Returns:
        datetime 对象
    """
    return datetime.now(timezone.utc)


def timestamp_to_datetime(timestamp: str) -> Optional[datetime]:
    """
    将时间戳字符串转换为 datetime 对象

    Args:
        timestamp: ISO 8601 格式的时间戳字符串

    Returns:
        datetime 对象，如果转换失败则返回 None
    """
    try:
        return datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
    except (ValueError, AttributeError):
        return None


def datetime_to_timestamp(dt: datetime) -> str:
    """
    将 datetime 对象转换为时间戳字符串

    Args:
        dt: datetime 对象

    Returns:
        ISO 8601 格式的时间戳字符串
    """
    return dt.isoformat()


def format_datetime(dt: datetime, format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """
    格式化 datetime 对象

    Args:
        dt: datetime 对象
        format_str: 格式化字符串

    Returns:
        格式化后的时间字符串
    """
    return dt.strftime(format_str)


def calculate_md5(text: str) -> str:
    """
    计算文本的 MD5 哈希值

    Args:
        text: 输入文本

    Returns:
        MD5 哈希值（32位十六进制字符串）
    """
    return hashlib.md5(text.encode("utf-8")).hexdigest()


def calculate_sha256(text: str) -> str:
    """
    计算文本的 SHA256 哈希值

    Args:
        text: 输入文本

    Returns:
        SHA256 哈希值（64位十六进制字符串）
    """
    return hashlib.sha256(text.encode("utf-8")).hexdigest()


def sanitize_string(text: str, max_length: Optional[int] = None) -> str:
    """
    清理字符串（去除首尾空格、控制字符等）

    Args:
        text: 输入文本
        max_length: 最大长度限制

    Returns:
        清理后的字符串
    """
    if not text:
        return ""

    # 去除首尾空格
    text = text.strip()

    # 替换控制字符（保留换行和制表符）
    text = "".join(char if char >= " " or char in "\n\t" else " " for char in text)

    # 限制长度
    if max_length and len(text) > max_length:
        text = text[:max_length]

    return text


def truncate_string(text: str, max_length: int, suffix: str = "...") -> str:
    """
    截断字符串并添加后缀

    Args:
        text: 输入文本
        max_length: 最大长度
        suffix: 后缀字符串

    Returns:
        截断后的字符串
    """
    if not text or len(text) <= max_length:
        return text

    return text[: max_length - len(suffix)] + suffix


def validate_email(email: str) -> bool:
    """
    验证邮箱地址格式

    Args:
        email: 邮箱地址

    Returns:
        是否有效
    """
    import re

    pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    return bool(re.match(pattern, email))


def validate_url(url: str) -> bool:
    """
    验证 URL 格式

    Args:
        url: URL 地址

    Returns:
        是否有效
    """
    import re

    pattern = r"^https?://[^\s/$.?#].[^\s]*$"
    return bool(re.match(pattern, url, re.IGNORECASE))


def safe_get(data: Dict[str, Any], key: str, default: Any = None) -> Any:
    """
    安全获取字典值（支持嵌套键）

    Args:
        data: 字典数据
        key: 键路径（点分隔，如 'user.profile.name'）
        default: 默认值

    Returns:
        值或默认值
    """
    keys = key.split(".")
    value = data
    for k in keys:
        if isinstance(value, dict) and k in value:
            value = value[k]
        else:
            return default
    return value


def merge_dicts(*dicts: Dict[str, Any]) -> Dict[str, Any]:
    """
    合并多个字典（后面的字典会覆盖前面的）

    Args:
        *dicts: 要合并的字典

    Returns:
        合并后的字典
    """
    result = {}
    for d in dicts:
        if d:
            result.update(d)
    return result


def chunk_list(data: List[Any], chunk_size: int) -> List[List[Any]]:
    """
    将列表分块

    Args:
        data: 输入列表
        chunk_size: 每块大小

    Returns:
        分块后的列表
    """
    return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]


def flatten_list(nested_list: List[List[Any]]) -> List[Any]:
    """
    扁平化嵌套列表

    Args:
        nested_list: 嵌套列表

    Returns:
        扁平化后的列表
    """
    return [item for sublist in nested_list for item in sublist]


def remove_duplicates(items: List[Any], key: Optional[str] = None) -> List[Any]:
    """
    去除列表中的重复项

    Args:
        items: 输入列表
        key: 如果是字典列表，指定用于比较的键

    Returns:
        去重后的列表
    """
    if not items:
        return []

    if key is None:
        # 简单类型去重
        seen = set()
        result = []
        for item in items:
            if item not in seen:
                seen.add(item)
                result.append(item)
        return result
    else:
        # 字典列表根据指定键去重
        seen = set()
        result = []
        for item in items:
            if isinstance(item, dict):
                value = item.get(key)
                if value not in seen:
                    seen.add(value)
                    result.append(item)
        return result


def dict_to_query_string(params: Dict[str, Any]) -> str:
    """
    将字典转换为 URL 查询字符串

    Args:
        params: 参数字典

    Returns:
        查询字符串
    """
    from urllib.parse import urlencode

    return urlencode(params)


def parse_query_string(query_string: str) -> Dict[str, Union[str, List[str]]]:
    """
    解析 URL 查询字符串

    Args:
        query_string: 查询字符串

    Returns:
        参数字典
    """
    from urllib.parse import parse_qs

    parsed = parse_qs(query_string)
    return {k: v[0] if len(v) == 1 else v for k, v in parsed.items()}


def bytes_to_human_readable(size_bytes: int) -> str:
    """
    将字节数转换为人类可读的格式

    Args:
        size_bytes: 字节数

    Returns:
        人类可读的大小字符串
    """
    units = ["B", "KB", "MB", "GB", "TB", "PB"]
    size = float(size_bytes)
    unit_index = 0

    while size >= 1024 and unit_index < len(units) - 1:
        size /= 1024
        unit_index += 1

    return f"{size:.2f} {units[unit_index]}"


def is_empty(value: Any) -> bool:
    """
    检查值是否为空

    Args:
        value: 要检查的值

    Returns:
        是否为空
    """
    if value is None:
        return True
    if isinstance(value, (str, list, dict, tuple, set)):
        return len(value) == 0
    return False


def coalesce(*values: Any) -> Any:
    """
    返回第一个非空值

    Args:
        *values: 要检查的值

    Returns:
        第一个非空值，如果都为空则返回 None
    """
    for value in values:
        if not is_empty(value):
            return value
    return None


def retry_on_exception(
    func: Callable,
    max_retries: int = 3,
    delay: float = 1.0,
    exceptions: Tuple[Type[Exception], ...] = (Exception,),
):
    """
    重试装饰器包装的函数

    Args:
        func: 要重试的函数
        max_retries: 最大重试次数
        delay: 重试间隔（秒）
        exceptions: 要捕获的异常类型

    Returns:
        函数执行结果
    """
    import time

    for attempt in range(max_retries + 1):
        try:
            return func()
        except exceptions as e:
            if attempt == max_retries:
                raise
            time.sleep(delay)


def format_error_message(error: Exception, include_traceback: bool = False) -> str:
    """
    格式化错误消息

    Args:
        error: 异常对象
        include_traceback: 是否包含堆栈跟踪

    Returns:
        格式化后的错误消息
    """
    import traceback

    message = f"{type(error).__name__}: {str(error)}"

    if include_traceback:
        tb = traceback.format_exc()
        message += f"\n\nTraceback:\n{tb}"

    return message


def ensure_list(value: Union[Any, List[Any]]) -> List[Any]:
    """
    确保值是列表类型

    Args:
        value: 输入值

    Returns:
        列表
    """
    if value is None:
        return []
    if isinstance(value, list):
        return value
    return [value]


def ensure_dict(value: Union[Dict, Any]) -> Dict[str, Any]:
    """
    确保值是字典类型

    Args:
        value: 输入值

    Returns:
        字典
    """
    if value is None:
        return {}
    if isinstance(value, dict):
        return value
    return {}
