"""FunctionParser, FunctionDataSerializer and IdentityDataSerializer — callable adapters
that let consumers use plain functions in place of ABC implementations.
"""

from messageprocessorutil import FunctionDataSerializer, FunctionParser, IdentityDataSerializer


def test_function_parser_passes_data_and_event_type_to_callable():
    received = {}

    def parse(data, event_type):
        received["data"] = data
        received["event_type"] = event_type
        return "parsed-request"

    result = FunctionParser(parse).parse({"id": 1}, "OrderCreated")

    assert result == "parsed-request"
    assert received == {"data": {"id": 1}, "event_type": "OrderCreated"}


def test_function_data_serializer_passes_result_to_callable():
    def serialize(result):
        return {"wrapped": result}

    assert FunctionDataSerializer(serialize).serialize(42) == {"wrapped": 42}


def test_function_data_serializer_passes_error_args_to_fn_error():
    received = {}

    def fn_error(input_obj, exception, original_payload):
        received["input_obj"] = input_obj
        received["exception"] = exception
        received["original_payload"] = original_payload
        return {"handled": True}

    exc = ValueError("boom")
    result = FunctionDataSerializer(lambda r: {}, fn_error=fn_error).serialize_error(
        input_obj="req", exception=exc, original_payload={"id": 1}
    )

    assert result == {"handled": True}
    assert received == {"input_obj": "req", "exception": exc, "original_payload": {"id": 1}}


def test_function_data_serializer_passes_parser_error_args_to_fn_parser_error():
    received = {}

    def fn_parser_error(data, exception):
        received["data"] = data
        received["exception"] = exception
        return {"parse_error": True}

    exc = ValueError("bad bytes")
    result = FunctionDataSerializer(lambda r: {}, fn_parser_error=fn_parser_error).serialize_parser_error(
        data=b"bad", exception=exc
    )

    assert result == {"parse_error": True}
    assert received == {"data": b"bad", "exception": exc}


def test_function_data_serializer_falls_back_to_identity_error_when_no_fn_error():
    exc = ValueError("boom")
    result = FunctionDataSerializer(lambda r: {}).serialize_error(
        input_obj="req", exception=exc, original_payload={}
    )

    assert result == {"error": "ValueError", "message": "boom"}


def test_function_data_serializer_falls_back_to_identity_parser_error_when_no_fn_parser_error():
    exc = ValueError("bad bytes")
    result = FunctionDataSerializer(lambda r: {}).serialize_parser_error(data=b"bad", exception=exc)

    assert result == {"error": "ValueError", "message": "bad bytes"}


def test_identity_data_serializer_returns_result_unchanged():
    data = {"key": "value", "nested": [1, 2, 3]}

    assert IdentityDataSerializer().serialize(data) is data


def test_identity_data_serializer_serialize_error_returns_exception_dump():
    exc = RuntimeError("something went wrong")
    result = IdentityDataSerializer().serialize_error(input_obj="req", exception=exc, original_payload={})

    assert result == {"error": "RuntimeError", "message": "something went wrong"}


def test_identity_data_serializer_serialize_parser_error_returns_exception_dump():
    exc = RuntimeError("invalid bytes")
    result = IdentityDataSerializer().serialize_parser_error(data=b"bad", exception=exc)

    assert result == {"error": "RuntimeError", "message": "invalid bytes"}
