# 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 coreason_manifest.spec.v2.definitions import ManifestMetadata
from coreason_manifest.spec.v2.recipe import (
    AgentNode,
    GraphTopology,
    PolicyConfig,
    RecipeDefinition,
    RecipeInterface,
)


def test_edge_case_empty_strings() -> None:
    """Test Case: Empty Strings should be allowed (e.g. for dynamic clearing or minimal policies)."""
    policy = PolicyConfig(
        safety_preamble="",
        legal_disclaimer="",
    )
    assert policy.safety_preamble == ""
    assert policy.legal_disclaimer == ""

    # Check serialization
    data = policy.model_dump()
    assert data["safety_preamble"] == ""
    assert data["legal_disclaimer"] == ""


def test_edge_case_long_strings() -> None:
    """Test Case: Very long strings (10KB) should be handled without truncation or error."""
    long_text = "A" * 10240  # 10KB
    policy = PolicyConfig(
        safety_preamble=long_text,
        legal_disclaimer=long_text,
    )
    assert len(policy.safety_preamble or "") == 10240
    assert len(policy.legal_disclaimer or "") == 10240


def test_edge_case_special_characters() -> None:
    """Test Case: Special characters (newlines, markdown, unicode) should be preserved."""
    special_text = """
    # Markdown Header
    - Bullet point
    Emoji: 🤖
    """
    policy = PolicyConfig(
        safety_preamble=special_text,
        legal_disclaimer="Signature: ✍️",
    )
    assert "Markdown Header" in (policy.safety_preamble or "")
    assert "🤖" in (policy.safety_preamble or "")
    assert "✍️" in (policy.legal_disclaimer or "")


def test_edge_case_explicit_none() -> None:
    """Test Case: Explicit None should behave same as default."""
    policy = PolicyConfig(
        safety_preamble=None,
        legal_disclaimer=None,
    )
    assert policy.safety_preamble is None
    assert policy.legal_disclaimer is None

    # Ensure they are serialized as null or omitted depending on config (default: include explicit None)
    # Pydantic v2 default behavior for explicit None is usually to include it unless exclude_none=True
    data = policy.model_dump()
    assert data["safety_preamble"] is None
    assert data["legal_disclaimer"] is None


def test_complex_case_mixed_policy() -> None:
    """Test Case: Full Recipe with PolicyConfig having mixed fields (legacy + new)."""
    policy = PolicyConfig(
        max_retries=5,
        timeout_seconds=300,
        budget_cap_usd=100.0,
        sensitive_tools=["tool_a", "tool_b"],
        allowed_mcp_servers=["github"],
        safety_preamble="Do no harm.",
        legal_disclaimer="Generated by Coreason.",
    )

    recipe = RecipeDefinition(
        metadata=ManifestMetadata(name="Complex Governance Recipe"),
        interface=RecipeInterface(),
        policy=policy,
        topology=GraphTopology(
            nodes=[AgentNode(id="start", agent_ref="agent-1")],
            edges=[],
            entry_point="start",
        ),
    )

    # Verify integration
    assert recipe.policy is not None
    assert recipe.policy.max_retries == 5
    assert recipe.policy.budget_cap_usd == 100.0
    assert recipe.policy.safety_preamble == "Do no harm."

    # Verify serialization
    json_str = recipe.model_dump_json()
    assert "Do no harm." in json_str
    assert "Generated by Coreason." in json_str
    assert "100.0" in json_str


def test_complex_case_inheritance_simulation() -> None:
    """Test Case: Simulating inheritance logic (manual merge).

    Scenario: A parent policy exists, and a child recipe wants to override only the disclaimer.
    """
    parent_policy = PolicyConfig(safety_preamble="Parent Safety", legal_disclaimer="Parent Disclaimer", max_retries=3)

    # Child overrides disclaimer but keeps safety
    child_overrides = {"legal_disclaimer": "Child Disclaimer"}

    # Simulate merge (Pydantic copy/update)
    merged_policy = parent_policy.model_copy(update=child_overrides)

    assert merged_policy.safety_preamble == "Parent Safety"
    assert merged_policy.legal_disclaimer == "Child Disclaimer"
    assert merged_policy.max_retries == 3
