from __future__ import annotations

import json
from typing import Any

from xfintech.serde.common.dataformat import DataFormat
from xfintech.serde.common.error import (
    SerialiserFailedError,
    SerialiserInputTypeError,
    SerialiserNotSupportedError,
)
from xfintech.serde.common.serialiserlike import SerialiserLike


class PythonSerialiser(SerialiserLike):
    """
    描述:
    - PythonDict序列化模块。
    - DICT -> BYTES 的单向转换，适用于配置和轻量级数据交换。

    方法:
    - serialise(data, format, **kwargs): 通用序列化方法，仅支持 JSON 格式。
    - to_json(data, **kwargs): 将数据编码为 JSON 字节流，编码默认 "utf-8"。

    例子:
    ```python
        from xfintech.serde.serialiser.python import PythonSerialiser
        from xfintech.serde.common.dataformat import DataFormat

        # 使用通用序列化方法（推荐）
        bytes = PythonSerialiser.serialise(
            data,
            format=DataFormat.JSON,
        )
    ```
    """

    @staticmethod
    def serialise(
        data: Any,
        format: DataFormat | str,
        **kwargs: Any,
    ) -> bytes:
        if not isinstance(data, dict):
            msg = f"PythonSerialiser.serialise expects dict, got {type(data)}"
            raise SerialiserInputTypeError(msg)
        format = DataFormat.from_any(format)
        if format == DataFormat.JSON:
            return PythonSerialiser.to_json(data, **kwargs)
        else:
            msg = f"Unsupported DataFormat for serialization: {format}"
            raise SerialiserNotSupportedError(msg)

    @staticmethod
    def to_json(
        data: Any,
        **kwargs: Any,
    ) -> bytes:
        encoding = kwargs.pop("encoding", "utf-8")
        kwargs.setdefault("ensure_ascii", False)
        kwargs.setdefault("indent", 4)
        kwargs.setdefault("sort_keys", True)
        try:
            payload = json.dumps(
                data,
                **kwargs,
            )
            return payload.encode(encoding)
        except Exception as e:
            msg = f"Failed to serialize data: {e}"
            raise SerialiserFailedError(msg) from e
