from __future__ import annotations

from typing import Any
from unittest.mock import MagicMock

import pytest
import requests

from cirtusai import Attachment, AuthenticationError, CirtusClient


def test_authenticate_populates_profile_and_token(
    mock_session, mock_response_factory, auth_payload, identity_payload
) -> None:
    mock_session.post.return_value = mock_response_factory(json_data=auth_payload)
    mock_session.request.return_value = mock_response_factory(json_data=identity_payload)

    client = CirtusClient(
        base_url="http://testserver",
        api_key="cai_example_key",
        session=mock_session,
        auto_authenticate=False,
    )

    token = client.authenticate()
    assert token == "token123"
    profile = client.get_identity()
    assert profile.name == "Agent"
    assert profile.assets[0].address == "agent@example.com"
    assert mock_session.headers["Authorization"] == "Bearer token123"


def test_list_messages_returns_typed_objects(mock_session, mock_response_factory, auth_payload) -> None:
    mock_session.post.return_value = mock_response_factory(json_data=auth_payload)
    mock_session.request.return_value = mock_response_factory(
        json_data={
            "items": [
                {
                    "id": 1,
                    "folder": "inbox",
                    "subject": "Hello",
                    "sender": "sender@example.com",
                    "recipient": "agent@example.com",
                    "preview": "Body",
                    "created_at": "2025-01-01T00:00:00+00:00",
                    "unread": True,
                }
            ]
        }
    )

    client = CirtusClient(
        base_url="http://testserver",
        api_key="cai_example_key",
        session=mock_session,
    )

    messages = client.list_messages(unread=True, limit=10)
    assert len(messages) == 1
    assert messages[0].subject == "Hello"
    mock_session.request.assert_called_with(
        "GET",
        "http://testserver/api/mail/messages",
        timeout=10.0,
        params={"folder": "inbox", "limit": "10", "unread": "true"},
    )


def test_send_message_serialises_attachments(mock_session, mock_response_factory, auth_payload) -> None:
    mock_session.post.return_value = mock_response_factory(json_data=auth_payload)
    mock_session.request.return_value = mock_response_factory(json_data={"message": "Message queued for delivery."})

    client = CirtusClient(
        base_url="http://testserver",
        api_key="cai_example_key",
        session=mock_session,
    )

    attachment = Attachment(filename="demo.txt", content="YmFzZTY0", size=6, content_type="text/plain")
    client.send_message(
        to=["dest@example.com"],
        subject="Greetings",
        content="Body",
        attachments=[attachment],
    )
    mock_session.request.assert_called_with(
        "POST",
        "http://testserver/api/mail/send",
        timeout=10.0,
        json={
            "to": ["dest@example.com"],
            "subject": "Greetings",
            "content": "Body",
            "attachments": [
                {"filename": "demo.txt", "content": "YmFzZTY0", "size": 6, "content_type": "text/plain"}
            ],
        },
    )


def test_request_raises_authentication_error_on_401(mock_session, mock_response_factory, auth_payload) -> None:
    mock_session.post.return_value = mock_response_factory(json_data=auth_payload)
    mock_session.request.return_value = mock_response_factory(status_code=401, json_data={"detail": "invalid"})

    client = CirtusClient(
        base_url="http://testserver",
        api_key="cai_example_key",
        session=mock_session,
    )

    with pytest.raises(AuthenticationError):
        client.list_messages()
