from __future__ import annotations

from datetime import datetime, timezone

import pytest

from mrp.models import DiscoveredAgent
from mrp_mcp.state import SessionState


def _now():
    return datetime.now(timezone.utc)


def _agent(pk="pk-abc", name="TestBot", caps=None):
    return DiscoveredAgent(
        public_key=pk,
        display_name=name,
        last_active_at=_now(),
        capabilities=caps or ["text:chat"],
    )


class TestSessionState:
    def test_add_contact(self, state):
        agent = _agent()
        contact = state.add_contact(agent)
        assert contact.public_key == "pk-abc"
        assert contact.display_name == "TestBot"
        assert "pk-abc" in state.contacts

    def test_add_contact_indexes_by_display_name(self, state):
        state.add_contact(_agent(pk="pk-1", name="Alpha Bot"))
        assert "alpha bot" in state.aliases
        assert state.aliases["alpha bot"] == "pk-1"

    def test_add_contact_with_alias(self, state):
        state.add_contact(_agent(pk="pk-1", name="Bot"), alias="mybot")
        assert "mybot" in state.aliases
        assert state.aliases["mybot"] == "pk-1"

    def test_resolve_by_public_key(self, state):
        state.add_contact(_agent(pk="pk-123"))
        assert state.resolve_recipient("pk-123") == "pk-123"

    def test_resolve_by_display_name(self, state):
        state.add_contact(_agent(pk="pk-123", name="TranslatorBot"))
        assert state.resolve_recipient("TranslatorBot") == "pk-123"

    def test_resolve_case_insensitive(self, state):
        state.add_contact(_agent(pk="pk-123", name="TranslatorBot"))
        assert state.resolve_recipient("translatorbot") == "pk-123"
        assert state.resolve_recipient("TRANSLATORBOT") == "pk-123"

    def test_resolve_by_alias(self, state):
        state.add_contact(_agent(pk="pk-123", name="Bot"), alias="translator")
        assert state.resolve_recipient("translator") == "pk-123"

    def test_resolve_by_substring(self, state):
        state.add_contact(_agent(pk="pk-123", name="TranslatorBot"))
        assert state.resolve_recipient("Translator") == "pk-123"

    def test_resolve_unknown_raises(self, state):
        with pytest.raises(ValueError, match="Unknown recipient"):
            state.resolve_recipient("nobody")

    def test_update_existing_contact(self, state):
        state.add_contact(_agent(pk="pk-1", name="OldName"))
        state.add_contact(_agent(pk="pk-1", name="NewName"))
        assert state.contacts["pk-1"].display_name == "NewName"
        assert "newname" in state.aliases

    def test_add_contact_without_display_name(self, state):
        agent = _agent(pk="pk-1", name=None)
        contact = state.add_contact(agent)
        assert contact.display_name is None
        # Should still be findable by public key
        assert state.resolve_recipient("pk-1") == "pk-1"

    def test_multiple_contacts(self, state):
        state.add_contact(_agent(pk="pk-a", name="Alpha"))
        state.add_contact(_agent(pk="pk-b", name="Beta"))
        assert len(state.contacts) == 2
        assert state.resolve_recipient("Alpha") == "pk-a"
        assert state.resolve_recipient("Beta") == "pk-b"

    def test_unread_queue(self, state):
        assert state.unread == []
        assert state.last_poll_cursor is None
