import json

import pytest

from a2a_agent.protocol import AgentCard
from a2a_agent.protocol import Message
from a2a_agent.protocol import PairingReply
from a2a_agent.protocol import PairingRequest
from a2a_agent.protocol import Task
from a2a_agent.protocol import build_file_part
from a2a_agent.protocol import parse_file_part


def test_task_round_trip_maps_from_key() -> None:
    task = Task(
        id="task-001",
        from_="commander",
        to="device-b",
        status="pending",
        messages=[
            Message(
                role="user",
                parts=[{"type": "text", "text": "check project"}],
            )
        ],
    )

    payload = task.to_json()
    raw = json.loads(payload)

    assert raw["from"] == "commander"
    assert "from_" not in raw
    assert "share" not in raw
    assert "control" not in raw
    restored = Task.from_json(payload)
    assert restored == task
    assert restored.control is None


def test_task_round_trip_with_control() -> None:
    task = Task(
        id="task-control",
        from_="commander",
        to="device-b",
        status="pending",
        messages=[],
        control="install-autostart",
    )

    raw = task.to_dict()

    assert raw["control"] == "install-autostart"
    assert Task.from_dict(raw) == task
    assert Task.from_json(task.to_json()) == task


def test_task_from_legacy_json_keeps_control_absent() -> None:
    payload = json.dumps(
        {
            "id": "task-legacy",
            "from": "commander",
            "to": "device-b",
            "status": "pending",
            "messages": [],
        }
    )

    restored = Task.from_json(payload)

    assert restored.control is None
    assert "control" not in restored.to_dict()


def test_task_round_trip_with_share() -> None:
    share = {
        "host": "nas.example.com",
        "port": 5001,
        "user": "a2a-worker",
        "password": "secret",
        "folder": "/a2a-share",
        "insecure": True,
    }
    task = Task(
        id="task-001",
        from_="commander",
        to="device-b",
        status="pending",
        messages=[
            Message(
                role="user",
                parts=[{"type": "text", "text": "check project"}],
            )
        ],
        share=share,
    )

    payload = task.to_json()
    raw = json.loads(payload)

    assert raw["share"] == share
    assert Task.from_json(payload) == task


def test_agent_card_round_trip() -> None:
    card = AgentCard(name="Device B")

    assert AgentCard.from_json(card.to_json()) == card


def test_pairing_messages_round_trip() -> None:
    request = PairingRequest(code="ABC234")
    reply = PairingReply(
        ok=True,
        room="team",
        device_name="device-b",
        token="token",
        broker={"host": "broker.example.com", "port": 1883, "tls": False},
        share={
            "host": "nas.example.com",
            "port": 5001,
            "user": "a2a-worker",
            "password": "secret",
            "folder": "/a2a-share",
            "insecure": True,
        },
    )

    assert PairingRequest.from_json(request.to_json()) == request
    assert PairingReply.from_json(reply.to_json()) == reply


def test_task_rejects_unknown_status() -> None:
    with pytest.raises(ValueError):
        Task(
            id="task-001",
            from_="commander",
            to="device-b",
            status="unknown",
            messages=[],
        )


def test_file_part_build_and_parse() -> None:
    part = build_file_part("photo.jpg", "task-001/photo.jpg", 123)

    assert part == {
        "type": "file",
        "name": "photo.jpg",
        "path": "task-001/photo.jpg",
        "size": 123,
    }
    assert parse_file_part(part).name == "photo.jpg"


def test_file_part_rejects_absolute_or_parent_paths() -> None:
    with pytest.raises(ValueError):
        build_file_part("photo.jpg", "/a2a-share/photo.jpg", 123)
    with pytest.raises(ValueError):
        build_file_part("photo.jpg", "../photo.jpg", 123)
