"""End-to-end tests for GmailConnector against a real Gmail account.

Requires a valid .env with GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REFRESH_TOKEN.
"""

from mail_connector import GmailConnector


def test_list_labels():
    g = GmailConnector()
    labels = g.list_labels()

    assert isinstance(labels, list)
    assert len(labels) > 0
    assert "id" in labels[0]
    assert "name" in labels[0]


def test_list_messages():
    g = GmailConnector()
    messages = g.list_messages(max_results=3)

    assert isinstance(messages, list)
    assert len(messages) > 0
    assert "id" in messages[0]
    assert "threadId" in messages[0]


def test_get_message():
    g = GmailConnector()
    messages = g.list_messages(max_results=1)
    msg = g.get_message(messages[0]["id"])

    assert isinstance(msg, dict)
    assert "id" in msg
    assert "payload" in msg
    assert "body_text" in msg


def test_modify_message_labels():
    """Modify labels on a message and restore original state."""
    g = GmailConnector()
    messages = g.list_messages(max_results=1)
    msg_id = messages[0]["id"]

    # Save original labels
    original = g.get_message(msg_id)
    original_labels = set(original.get("labelIds", []))

    # Add STARRED, verify
    result = g.modify_message(msg_id, add_label_ids=["STARRED"])
    assert "STARRED" in result.get("labelIds", [])

    # Remove STARRED, restore
    result = g.modify_message(msg_id, remove_label_ids=["STARRED"])
    restored_labels = set(result.get("labelIds", []))
    assert restored_labels == original_labels


def test_mark_as_read_unread():
    """Mark a message as read then unread, restoring original state."""
    g = GmailConnector()
    messages = g.list_messages(max_results=1)
    msg_id = messages[0]["id"]

    original = g.get_message(msg_id)
    was_unread = "UNREAD" in original.get("labelIds", [])

    # Mark as read
    result = g.mark_as_read(msg_id)
    assert "UNREAD" not in result.get("labelIds", [])

    # Mark as unread
    result = g.mark_as_unread(msg_id)
    assert "UNREAD" in result.get("labelIds", [])

    # Restore original state
    if not was_unread:
        g.mark_as_read(msg_id)


def test_trash_untrash():
    """Trash a message and restore it."""
    g = GmailConnector()
    messages = g.list_messages(max_results=1)
    msg_id = messages[0]["id"]

    # Trash
    result = g.trash(msg_id)
    assert "TRASH" in result.get("labelIds", [])

    # Untrash
    result = g.untrash(msg_id)
    assert "TRASH" not in result.get("labelIds", [])


def _find_message_with_attachment() -> tuple[GmailConnector, str]:
    """Find a message that has attachments, for use in attachment tests."""
    g = GmailConnector()
    messages = g.list_messages(query="has:attachment", max_results=1)
    assert messages, "No messages with attachments found in mailbox"
    return g, messages[0]["id"]


def test_list_attachments():
    """list_attachments returns metadata for a message with attachments."""
    g, msg_id = _find_message_with_attachment()
    attachments = g.list_attachments(msg_id)

    assert isinstance(attachments, list)
    assert len(attachments) > 0
    att = attachments[0]
    assert "filename" in att
    assert "mimeType" in att
    assert "size" in att
    assert "attachmentId" in att
    assert att["filename"]  # non-empty


def test_download_attachment():
    """download_attachment returns non-empty bytes."""
    g, msg_id = _find_message_with_attachment()
    attachments = g.list_attachments(msg_id)
    assert attachments, "No attachments found"

    data = g.download_attachment(msg_id, attachments[0]["attachmentId"])
    assert isinstance(data, bytes)
    assert len(data) > 0


def test_send_message():
    """Send an email to self and verify it appears in the mailbox."""
    g = GmailConnector()
    result = g.send_message("me", "mail_connector E2E test", "Automated test — safe to delete.")

    assert isinstance(result, dict)
    assert "id" in result

    # Clean up: trash the sent message
    g.trash(result["id"])
