import json
import os
from typing import Any, Union


def to_json(data: Any, indent: Union[int, None] = None) -> str:
    """
    将Python对象转换为JSON字符串
    :param data: 要转换的Python对象
    :param indent: 缩进空格数，None表示不格式化. 默认为None
    :return: JSON格式的字符串
    :raise TypeError: 当对象不可序列化时抛出 TypeError
    """
    try:
        return json.dumps(data, ensure_ascii=False, indent=indent)
    except TypeError as e:
        raise TypeError(f"数据无法序列化为JSON: {e}") from e


def from_json(json_str: str) -> Any:
    """
    将JSON字符串解析为Python对象
    :param json_str: JSON格式的字符串
    :return: 解析后的Python对象
    :raise TypeError : 当输入不是字符串时抛出
    :raise json.JSONDecodeError: 当JSON格式无效时抛出
    """
    if not isinstance(json_str, str):
        raise TypeError("输入必须是字符串类型")
    
    try:
        return json.loads(json_str)
    except json.JSONDecodeError as e:
        raise json.JSONDecodeError(f"JSON解析失败: {e.msg}", e.doc, e.pos) from e


def read_json(json_file: str) -> Any:
    """
    从JSON文件读取数据
    :param json_file: JSON文件路径
    :return: 从文件中读取的Python对象
    :raise FileNotFoundError: 当文件不存在时抛出
    :raise json.JSONDecodeError: 当文件内容不是有效JSON时抛出
    :raise IOError: 当文件读取失败时抛出
    """
    if not os.path.exists(json_file):
        raise FileNotFoundError(f"JSON文件不存在: {json_file}")
    
    try:
        with open(json_file, 'r', encoding='utf-8') as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        raise json.JSONDecodeError(f"文件 {json_file} 包含无效JSON: {e.msg}", e.doc, e.pos) from e
    except IOError as e:
        raise IOError(f"读取文件 {json_file} 失败: {e}") from e


def write_json(json_file: str, data: Any, ensure_path: bool = True, indent: Union[int, None] = None):
    """
    将数据写入JSON文件
    :param json_file: JSON文件路径
    :param data: 要写入的数据
    :param ensure_path: 是否自动创建目录. Defaults to True.
    :param indent: 缩进空格数，None表示不格式化，默认是None
    :return: None
    :raise TypeError: 当数据无法序列化时抛出
    :raise IOError: 当文件写入失败时抛出
    :raise OSError: 当目录创建失败时抛出
    """
    # 自动创建目录
    if ensure_path:
        os.makedirs(os.path.dirname(os.path.abspath(json_file)), exist_ok=True)
    
    try:
        with open(json_file, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=indent)
    except TypeError as e:
        raise TypeError(f"数据无法序列化为JSON: {e}") from e
    except IOError as e:
        raise IOError(f"写入文件 {json_file} 失败: {e}") from e


def is_valid_json(json_str: str) -> bool:
    """
    检查字符串是否为有效的JSON格式
    :param json_str: 待检查的字符串
    :return: 如果是有效JSON返回True，否则返回False
    """
    try:
        json.loads(json_str)
        return True
    except (json.JSONDecodeError, TypeError):
        return False


def update_json_file(json_file: str, updates: dict, ensure_path: bool = True) -> None:
    """
    更新JSON文件中的数据
    :param json_file: JSON文件路径
    :param updates: 要更新的数据字典
    :param ensure_path: 是否自动创建目录, 默认True
    :return: None
    :raise FileNotFoundError: 当文件不存在时抛出
    :raise json.JSONDecodeError: 当原文件内容无效时抛出
    :raise TypeError: 当更新数据无法序列化时抛出
    """
    # 读取现有数据
    if os.path.exists(json_file):
        existing_data = read_json(json_file)
        if not isinstance(existing_data, dict):
            raise TypeError("现有文件数据必须是字典类型才能进行更新")
    else:
        existing_data = {}
    
    # 更新数据
    existing_data.update(updates)
    
    # 写回文件
    write_json(json_file, existing_data, ensure_path)