"""Tests for zimba email module."""

import json
from unittest import mock

import pytest

from zimba.email import _walk_parts, search, read


class TestWalkParts:
    def test_plain_text(self):
        parts = [{"ct": "text/plain", "content": "Hello world"}]
        body_parts = []
        attachments = []
        _walk_parts(parts, body_parts, attachments)
        assert body_parts == ["Hello world"]
        assert attachments == []

    def test_html_fallback(self):
        parts = [{"ct": "text/html", "content": "<p>Hello <b>world</b></p>"}]
        body_parts = []
        attachments = []
        _walk_parts(parts, body_parts, attachments)
        assert len(body_parts) == 1
        assert "Hello" in body_parts[0]
        assert "<p>" not in body_parts[0]

    def test_attachment_detection(self):
        parts = [
            {"ct": "text/plain", "content": "body"},
            {"ct": "application/pdf", "filename": "doc.pdf", "part": "2", "s": 1024},
        ]
        body_parts = []
        attachments = []
        _walk_parts(parts, body_parts, attachments)
        assert body_parts == ["body"]
        assert len(attachments) == 1
        assert attachments[0]["filename"] == "doc.pdf"
        assert attachments[0]["part"] == "2"

    def test_nested_multipart(self):
        parts = [{
            "ct": "multipart/mixed",
            "mp": [
                {"ct": "text/plain", "content": "nested body"},
                {"ct": "image/png", "filename": "pic.png", "part": "2", "s": 500},
            ],
        }]
        body_parts = []
        attachments = []
        _walk_parts(parts, body_parts, attachments)
        assert body_parts == ["nested body"]
        assert len(attachments) == 1
        assert attachments[0]["filename"] == "pic.png"

    def test_cd_attachment(self):
        """Test attachment detected by content-disposition."""
        parts = [{"ct": "application/octet-stream", "cd": "attachment", "part": "3", "s": 200}]
        body_parts = []
        attachments = []
        _walk_parts(parts, body_parts, attachments)
        assert len(attachments) == 1
        assert "attachment-3" in attachments[0]["filename"]


class TestSearch:
    def test_search_parses_response(self):
        mock_response = {
            "SearchResponse": {
                "total": 2,
                "m": [
                    {
                        "id": "100",
                        "su": "Test Subject",
                        "d": 1710000000000,
                        "fr": "Preview text",
                        "f": "u",
                        "l": "2",
                        "s": 5000,
                        "e": [{"t": "f", "a": "sender@example.com"}],
                    },
                    {
                        "id": "101",
                        "su": "Another",
                        "d": 1710000001000,
                        "fr": "",
                        "f": "f",
                        "l": "2",
                        "s": 3000,
                        "e": [{"t": "f", "a": "other@example.com"}],
                    },
                ],
            }
        }

        with mock.patch("zimba.email.soap", return_value=mock_response):
            result = search("in:inbox")

        assert result["total"] == 2
        assert len(result["emails"]) == 2
        assert result["emails"][0]["id"] == "100"
        assert result["emails"][0]["from"] == "sender@example.com"
        assert result["emails"][0]["unread"] is True
        assert result["emails"][1]["flagged"] is True


class TestRead:
    def test_read_message(self):
        mock_response = {
            "GetMsgResponse": {
                "m": [{
                    "id": "100",
                    "cid": "50",
                    "su": "Test",
                    "d": 1710000000000,
                    "l": "2",
                    "e": [
                        {"t": "f", "a": "from@example.com"},
                        {"t": "t", "a": "to@example.com"},
                    ],
                    "mp": [{"ct": "text/plain", "content": "Hello"}],
                }]
            }
        }

        with mock.patch("zimba.email.soap", return_value=mock_response):
            result = read("100")

        assert result["id"] == "100"
        assert result["from"] == "from@example.com"
        assert result["to"] == ["to@example.com"]
        assert result["body"] == "Hello"
