"""
描述:
- DeserialiserLike 协议的单元测试。
- 测试协议的结构、实现和运行时类型检查。
"""

from __future__ import annotations

from typing import Any

from xfintech.serde.common.dataformat import DataFormat
from xfintech.serde.common.deserialiserlike import DeserialiserLike

# =============================================================================
# Protocol Structure Tests
# =============================================================================


def test_deserialiserlike_is_protocol():
    """测试 DeserialiserLike 是一个协议类"""
    from typing import Protocol

    assert issubclass(DeserialiserLike.__class__, type(Protocol))


def test_deserialiserlike_has_deserialise_method():
    """测试 DeserialiserLike 定义了 deserialise 方法"""
    assert hasattr(DeserialiserLike, "deserialise")


def test_deserialiserlike_method_signature():
    """测试 deserialise 方法签名"""
    import inspect

    sig = inspect.signature(DeserialiserLike.deserialise)
    params = list(sig.parameters.keys())
    assert "data" in params
    assert "format" in params
    assert "kwargs" in params


# =============================================================================
# Implementation Tests - Valid Implementations
# =============================================================================


def test_valid_implementation_with_staticmethod():
    """测试使用 staticmethod 的有效实现"""

    class ValidDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"result": "test"}

    instance = ValidDeserialiser()
    assert isinstance(instance, DeserialiserLike)


def test_valid_implementation_with_classmethod():
    """测试使用 classmethod 的有效实现"""

    class ValidDeserialiser:
        @classmethod
        def deserialise(cls, data: Any, format: Any, **kwargs: Any) -> Any:
            return {"result": "test"}

    instance = ValidDeserialiser()
    assert isinstance(instance, DeserialiserLike)


def test_valid_implementation_with_instance_method():
    """测试使用实例方法的有效实现"""

    class ValidDeserialiser:
        def deserialise(self, data: Any, format: Any, **kwargs: Any) -> Any:
            return {"result": "test"}

    instance = ValidDeserialiser()
    assert isinstance(instance, DeserialiserLike)


def test_valid_implementation_can_call_deserialise():
    """测试有效实现可以调用 deserialise"""

    class ValidDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"deserialised": True}

    deserialiser = ValidDeserialiser()
    result = deserialiser.deserialise(b"data", DataFormat.JSON)
    assert result == {"deserialised": True}


def test_valid_implementation_with_kwargs():
    """测试有效实现支持 kwargs"""

    class ValidDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            encoding = kwargs.get("encoding", "utf-8")
            return {"encoding": encoding}

    deserialiser = ValidDeserialiser()
    result = deserialiser.deserialise(b"data", DataFormat.JSON, encoding="ascii")
    assert result == {"encoding": "ascii"}


def test_valid_implementation_with_complex_logic():
    """测试有效实现包含复杂逻辑"""
    import json

    class ComplexDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            if format == DataFormat.JSON:
                return json.loads(data)
            elif format == DataFormat.CSV:
                return {"type": "csv"}
            else:
                return {"type": "unknown"}

    deserialiser = ComplexDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)
    result = deserialiser.deserialise(b'{"key": "value"}', DataFormat.JSON)
    assert result == {"key": "value"}


# =============================================================================
# Implementation Tests - Invalid Implementations
# =============================================================================


def test_invalid_implementation_missing_method():
    """测试缺少 deserialise 方法的实现"""

    class InvalidDeserialiser:
        pass

    instance = InvalidDeserialiser()
    assert not isinstance(instance, DeserialiserLike)


def test_invalid_implementation_wrong_method_name():
    """测试方法名错误的实现"""

    class InvalidDeserialiser:
        @staticmethod
        def deserialize(data: Any, format: Any, **kwargs: Any) -> Any:
            return {}

    instance = InvalidDeserialiser()
    assert not isinstance(instance, DeserialiserLike)


def test_property_implementation_is_valid():
    """测试使用 property 的实现也是有效的"""

    class PropertyDeserialiser:
        @property
        def deserialise(self):
            return lambda data, format, **kwargs: {}

    instance = PropertyDeserialiser()
    # Python's Protocol accepts properties with callable values
    assert isinstance(instance, DeserialiserLike)


# =============================================================================
# Type Checking Tests
# =============================================================================


def test_isinstance_with_valid_class():
    """测试 isinstance 检查有效类"""

    class MyDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {}

    assert isinstance(MyDeserialiser(), DeserialiserLike)


def test_isinstance_with_invalid_class():
    """测试 isinstance 检查无效类"""

    class NotDeserialiser:
        def other_method(self):
            pass

    assert not isinstance(NotDeserialiser(), DeserialiserLike)


def test_isinstance_with_builtin_types():
    """测试 isinstance 检查内置类型"""
    assert not isinstance(str(), DeserialiserLike)
    assert not isinstance(int(), DeserialiserLike)
    assert not isinstance(list(), DeserialiserLike)
    assert not isinstance(dict(), DeserialiserLike)


def test_isinstance_with_none():
    """测试 isinstance 检查 None"""
    assert not isinstance(None, DeserialiserLike)


# =============================================================================
# Inheritance Tests
# =============================================================================


def test_can_inherit_from_protocol():
    """测试可以继承协议"""

    class BaseDeserialiser(DeserialiserLike):
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"base": True}

    instance = BaseDeserialiser()
    assert isinstance(instance, DeserialiserLike)


def test_inherited_class_can_override():
    """测试继承类可以重写方法"""

    class BaseDeserialiser(DeserialiserLike):
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"base": True}

    class DerivedDeserialiser(BaseDeserialiser):
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"derived": True}

    derived = DerivedDeserialiser()
    assert isinstance(derived, DeserialiserLike)
    assert derived.deserialise(b"", DataFormat.JSON) == {"derived": True}


# =============================================================================
# Return Type Tests
# =============================================================================


def test_can_return_dict():
    """测试可以返回字典"""

    class DictDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {"key": "value"}

    deserialiser = DictDeserialiser()
    result = deserialiser.deserialise(b"", DataFormat.JSON)
    assert isinstance(result, dict)


def test_can_return_dataframe():
    """测试可以返回 DataFrame（模拟）"""

    class DataFrameDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            # Return a mock DataFrame-like object
            class MockDataFrame:
                pass

            return MockDataFrame()

    deserialiser = DataFrameDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)


def test_can_return_list():
    """测试可以返回列表"""

    class ListDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return [1, 2, 3]

    deserialiser = ListDeserialiser()
    result = deserialiser.deserialise(b"", DataFormat.CSV)
    assert isinstance(result, list)


def test_can_return_none():
    """测试可以返回 None"""

    class NoneDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return None

    deserialiser = NoneDeserialiser()
    result = deserialiser.deserialise(b"", DataFormat.JSON)
    assert result is None


# =============================================================================
# Edge Cases Tests
# =============================================================================


def test_implementation_with_default_arguments():
    """测试带默认参数的实现"""

    class DeserialiserWithDefaults:
        @staticmethod
        def deserialise(data: Any, format: Any = DataFormat.JSON, **kwargs: Any) -> Any:
            return {"default": True}

    deserialiser = DeserialiserWithDefaults()
    assert isinstance(deserialiser, DeserialiserLike)


def test_implementation_with_extra_methods():
    """测试包含额外方法的实现"""

    class RichDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            return {}

        @staticmethod
        def validate(data: Any) -> bool:
            return True

    deserialiser = RichDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)


def test_implementation_with_attributes():
    """测试包含属性的实现"""

    class DeserialiserWithState:
        def __init__(self):
            self.counter = 0

        def deserialise(self, data: Any, format: Any, **kwargs: Any) -> Any:
            self.counter += 1
            return {"count": self.counter}

    deserialiser = DeserialiserWithState()
    assert isinstance(deserialiser, DeserialiserLike)


def test_callable_object_as_implementation():
    """测试可调用对象作为实现"""

    class CallableDeserialiser:
        def deserialise(self, data: Any, format: Any, **kwargs: Any) -> Any:
            return {"callable": True}

    instance = CallableDeserialiser()
    assert isinstance(instance, DeserialiserLike)


# =============================================================================
# Real-World Usage Tests
# =============================================================================


def test_parquet_deserialiser_implementation():
    """测试 Parquet 反序列化器实现"""

    class ParquetDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            if format != DataFormat.PARQUET:
                raise ValueError(f"Unsupported format: {format}")
            # Simulate parquet deserialization
            return {"parquet": "data"}

    deserialiser = ParquetDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)
    result = deserialiser.deserialise(b"parquet_bytes", DataFormat.PARQUET)
    assert result == {"parquet": "data"}


def test_csv_deserialiser_implementation():
    """测试 CSV 反序列化器实现"""

    class CSVDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            if format != DataFormat.CSV:
                raise ValueError(f"Unsupported format: {format}")
            # Simulate CSV deserialization
            return [["col1", "col2"], ["val1", "val2"]]

    deserialiser = CSVDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)
    result = deserialiser.deserialise(b"csv_bytes", DataFormat.CSV)
    assert result == [["col1", "col2"], ["val1", "val2"]]


def test_json_deserialiser_implementation():
    """测试 JSON 反序列化器实现"""
    import json

    class JSONDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            if format != DataFormat.JSON:
                raise ValueError(f"Unsupported format: {format}")
            if isinstance(data, bytes):
                data = data.decode("utf-8")
            return json.loads(data)

    deserialiser = JSONDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)
    result = deserialiser.deserialise(b'{"test": 123}', DataFormat.JSON)
    assert result == {"test": 123}


def test_multi_format_deserialiser():
    """测试多格式反序列化器"""
    import json

    class MultiFormatDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            if format == DataFormat.JSON:
                if isinstance(data, bytes):
                    data = data.decode("utf-8")
                return json.loads(data)
            elif format == DataFormat.CSV:
                return {"type": "csv"}
            elif format == DataFormat.PARQUET:
                return {"type": "parquet"}
            else:
                raise ValueError(f"Unsupported format: {format}")

    deserialiser = MultiFormatDeserialiser()
    assert isinstance(deserialiser, DeserialiserLike)

    # Test each format
    json_result = deserialiser.deserialise(b'{"key": "value"}', DataFormat.JSON)
    assert json_result == {"key": "value"}

    csv_result = deserialiser.deserialise(b"csv_data", DataFormat.CSV)
    assert csv_result == {"type": "csv"}

    parquet_result = deserialiser.deserialise(b"parquet_data", DataFormat.PARQUET)
    assert parquet_result == {"type": "parquet"}


def test_deserialiser_with_encoding_option():
    """测试支持编码选项的反序列化器"""

    class EncodingDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            encoding = kwargs.get("encoding", "utf-8")
            if isinstance(data, bytes):
                return data.decode(encoding)
            return data

    deserialiser = EncodingDeserialiser()
    result = deserialiser.deserialise(b"test", DataFormat.CSV, encoding="utf-8")
    assert result == "test"


def test_deserialiser_with_error_handling():
    """测试包含错误处理的反序列化器"""

    class SafeDeserialiser:
        @staticmethod
        def deserialise(data: Any, format: Any, **kwargs: Any) -> Any:
            try:
                if format == DataFormat.JSON:
                    import json

                    return json.loads(data)
                return None
            except Exception:
                return {"error": "deserialization failed"}

    deserialiser = SafeDeserialiser()
    result = deserialiser.deserialise(b"invalid json", DataFormat.JSON)
    assert result == {"error": "deserialization failed"}


# =============================================================================
# Protocol Attribute Tests
# =============================================================================


def test_protocol_module():
    """测试协议所属模块"""
    assert DeserialiserLike.__module__ == "xfintech.serde.common.deserialiserlike"


def test_protocol_name():
    """测试协议名称"""
    assert DeserialiserLike.__name__ == "DeserialiserLike"
