from datetime import datetime, timezone

from mrp.models import (
    AgentInfo,
    Attachment,
    Blob,
    BlobMetadata,
    CapabilitiesResult,
    CapabilityInfo,
    DiscoveredAgent,
    DiscoverResult,
    Message,
    MessageStatus,
    PollResult,
    SendResult,
    WebhookInfo,
    _parse_dt,
)


class TestParseDt:
    def test_z_suffix(self):
        dt = _parse_dt("2026-03-05T12:00:00Z")
        assert dt.year == 2026
        assert dt.month == 3
        assert dt.day == 5
        assert dt.hour == 12

    def test_offset(self):
        dt = _parse_dt("2026-03-05T12:00:00+00:00")
        assert dt is not None

    def test_none(self):
        assert _parse_dt(None) is None

    def test_passthrough_datetime(self):
        dt = datetime(2026, 3, 5, tzinfo=timezone.utc)
        assert _parse_dt(dt) is dt


class TestAgentInfo:
    def test_from_dict_full(self):
        d = {
            "public_key": "abc123",
            "display_name": "Test Agent",
            "status": "active",
            "metadata": {"key": "value"},
            "capabilities": ["chat", "search"],
            "created_at": "2026-03-05T12:00:00Z",
            "last_active_at": "2026-03-05T13:00:00Z",
        }
        agent = AgentInfo.from_dict(d)
        assert agent.public_key == "abc123"
        assert agent.display_name == "Test Agent"
        assert agent.status == "active"
        assert agent.metadata == {"key": "value"}
        assert agent.capabilities == ["chat", "search"]

    def test_from_dict_optional_none(self):
        d = {
            "public_key": "abc123",
            "status": "active",
            "created_at": "2026-03-05T12:00:00Z",
            "last_active_at": "2026-03-05T12:00:00Z",
        }
        agent = AgentInfo.from_dict(d)
        assert agent.display_name is None
        assert agent.metadata == {}
        assert agent.capabilities == []


class TestAttachment:
    def test_from_dict_and_to_dict(self):
        d = {"blob_id": "blob_123", "content_type": "image/png", "size": 1024, "hash": "abc"}
        att = Attachment.from_dict(d)
        assert att.blob_id == "blob_123"
        assert att.content_type == "image/png"
        assert att.size == 1024

        out = att.to_dict()
        assert out["blob_id"] == "blob_123"
        assert out["content_type"] == "image/png"

    def test_minimal(self):
        d = {"blob_id": "blob_456"}
        att = Attachment.from_dict(d)
        assert att.content_type is None
        out = att.to_dict()
        assert "content_type" not in out


class TestMessage:
    def test_from_dict_full(self):
        d = {
            "message_id": "msg_1",
            "sender_key": "sender",
            "recipient_key": "recipient",
            "content_type": "application/json",
            "body": {"text": "hello"},
            "attachments": [{"blob_id": "b1"}],
            "status": "sent",
            "thread_id": "thread_1",
            "in_reply_to": "msg_0",
            "metadata": {"k": "v"},
            "created_at": "2026-03-05T12:00:00Z",
            "expires_at": "2026-03-12T12:00:00Z",
            "delivered_at": "2026-03-05T12:01:00Z",
        }
        msg = Message.from_dict(d)
        assert msg.message_id == "msg_1"
        assert msg.body == {"text": "hello"}
        assert len(msg.attachments) == 1
        assert msg.thread_id == "thread_1"
        assert msg.delivered_at is not None

    def test_from_dict_minimal(self):
        d = {
            "message_id": "msg_2",
            "sender_key": "s",
            "recipient_key": "r",
            "status": "sent",
            "created_at": "2026-03-05T12:00:00Z",
            "expires_at": "2026-03-12T12:00:00Z",
        }
        msg = Message.from_dict(d)
        assert msg.body is None
        assert msg.attachments == []
        assert msg.thread_id is None
        assert msg.delivered_at is None


class TestSendResult:
    def test_from_dict(self):
        d = {
            "message_id": "msg_1",
            "status": "sent",
            "created_at": "2026-03-05T12:00:00Z",
            "expires_at": "2026-03-12T12:00:00Z",
        }
        r = SendResult.from_dict(d)
        assert r.message_id == "msg_1"
        assert r.status == "sent"


class TestMessageStatus:
    def test_from_dict(self):
        d = {
            "status": "delivered",
            "created_at": "2026-03-05T12:00:00Z",
            "delivered_at": "2026-03-05T12:01:00Z",
            "expires_at": "2026-03-12T12:00:00Z",
        }
        s = MessageStatus.from_dict(d)
        assert s.status == "delivered"
        assert s.delivered_at is not None


class TestPollResult:
    def test_with_messages(self):
        d = {
            "messages": [
                {
                    "message_id": "msg_1",
                    "sender_key": "s",
                    "recipient_key": "r",
                    "status": "sent",
                    "created_at": "2026-03-05T12:00:00Z",
                    "expires_at": "2026-03-12T12:00:00Z",
                }
            ],
            "next_cursor": "abc",
        }
        r = PollResult.from_dict(d)
        assert len(r.messages) == 1
        assert r.next_cursor == "abc"

    def test_empty(self):
        r = PollResult.from_dict({"messages": []})
        assert r.messages == []
        assert r.next_cursor is None


class TestDiscoverResult:
    def test_from_dict(self):
        d = {
            "agents": [
                {
                    "public_key": "pk1",
                    "display_name": "Agent 1",
                    "last_active_at": "2026-03-05T12:00:00Z",
                    "capabilities": ["chat"],
                }
            ],
            "next_cursor": "cur",
            "has_more": True,
        }
        r = DiscoverResult.from_dict(d)
        assert len(r.agents) == 1
        assert r.agents[0].public_key == "pk1"
        assert r.has_more is True
        assert r.next_cursor == "cur"

    def test_has_more_default_false(self):
        d = {"agents": [], "next_cursor": None}
        r = DiscoverResult.from_dict(d)
        assert r.has_more is False


class TestCapabilityInfo:
    def test_from_dict(self):
        d = {"tag": "text:translate", "agent_count": 5}
        c = CapabilityInfo.from_dict(d)
        assert c.tag == "text:translate"
        assert c.agent_count == 5


class TestCapabilitiesResult:
    def test_from_dict(self):
        d = {
            "capabilities": [
                {"tag": "text:translate", "agent_count": 5},
                {"tag": "code:review", "agent_count": 2},
            ]
        }
        r = CapabilitiesResult.from_dict(d)
        assert len(r.capabilities) == 2
        assert r.capabilities[0].tag == "text:translate"
        assert r.capabilities[1].agent_count == 2

    def test_empty(self):
        r = CapabilitiesResult.from_dict({"capabilities": []})
        assert r.capabilities == []


class TestBlob:
    def test_from_dict(self):
        d = {
            "blob_id": "blob_1",
            "hash": "abc123",
            "size": 2048,
            "content_type": "image/png",
            "created_at": "2026-03-05T12:00:00Z",
            "expires_at": "2026-03-12T12:00:00Z",
        }
        b = Blob.from_dict(d)
        assert b.blob_id == "blob_1"
        assert b.size == 2048


class TestBlobMetadata:
    def test_creation(self):
        m = BlobMetadata(content_type="text/plain", size=100, hash="xyz")
        assert m.content_type == "text/plain"


class TestWebhookInfo:
    def test_from_dict(self):
        d = {
            "webhook_id": "wh_1",
            "url": "https://example.com/hook",
            "events": ["message.received"],
            "created_at": "2026-03-05T12:00:00Z",
        }
        w = WebhookInfo.from_dict(d)
        assert w.webhook_id == "wh_1"
        assert w.url == "https://example.com/hook"
