# Copyright (c) 2025 CoReason, Inc.
#
# This software is proprietary and dual-licensed.
# Licensed under the Prosperity Public License 3.0 (the "License").
# A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
# For details, see the LICENSE file.
# Commercial use beyond a 30-day trial requires a separate license.
#
# Source Code: https://github.com/CoReason-AI/coreason-manifest

from datetime import datetime

import pytest
from pydantic import TypeAdapter, ValidationError

from coreason_manifest.spec.common.graph_events import (
    GraphEvent,
    GraphEventNodeDone,
    GraphEventNodeStart,
    GraphEventNodeStream,
)


def test_polymorphic_serialization() -> None:
    """
    1. Polymorphic Serialization:
    * Create a list of mixed events (Start, Stream, Done).
    * Serialize to a list of dicts.
    * Use TypeAdapter(list[GraphEvent]).validate_python(data) to parse them back.
    * Assert: The types are correctly restored.
    """
    now = datetime.now().timestamp()

    events: list[GraphEvent] = [
        GraphEventNodeStart(
            run_id="run-1", trace_id="trace-1", node_id="node-1", timestamp=now, payload={"input": "test"}
        ),
        GraphEventNodeStream(
            run_id="run-1", trace_id="trace-1", node_id="node-1", timestamp=now + 1, chunk="Hello", stream_id="default"
        ),
        GraphEventNodeDone(
            run_id="run-1", trace_id="trace-1", node_id="node-1", timestamp=now + 2, output={"result": "Hello World"}
        ),
    ]

    # Serialize
    adapter = TypeAdapter(list[GraphEvent])
    serialized_data = adapter.dump_python(events)

    # Validate/Deserialize
    restored_events = adapter.validate_python(serialized_data)

    assert len(restored_events) == 3
    assert isinstance(restored_events[0], GraphEventNodeStart)
    assert restored_events[0].payload == {"input": "test"}

    assert isinstance(restored_events[1], GraphEventNodeStream)
    assert restored_events[1].chunk == "Hello"

    assert isinstance(restored_events[2], GraphEventNodeDone)
    assert restored_events[2].output == {"result": "Hello World"}


def test_immutability() -> None:
    """
    3. Immutability:
    * Attempt to modify event.chunk after instantiation.
    * Assert: ValidationError.
    """
    now = datetime.now().timestamp()
    event = GraphEventNodeStream(run_id="run-1", trace_id="trace-1", node_id="node-1", timestamp=now, chunk="Hello")

    with pytest.raises(ValidationError):
        event.chunk = "Modified"  # type: ignore
