from __future__ import annotations

import json

import httpx

from tests.conftest import json_response, make_client

mock_mailbox = {
    "object": "mailbox",
    "id": "mbx_123",
    "domain_id": "dom_456",
    "address": "hello@example.com",
    "display_name": "Hello",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
}


class TestCreate:
    def test_sends_post_mailboxes_with_body(self) -> None:
        def handler(request: httpx.Request) -> httpx.Response:
            assert request.method == "POST"
            assert request.url.path == "/v1/mailboxes"
            body = json.loads(request.content)
            assert body == {
                "domain_id": "dom_456",
                "address": "hello@example.com",
                "display_name": "Hello",
            }
            return json_response(mock_mailbox)

        client = make_client(handler)
        mailbox = client.mailboxes.create({
            "domain_id": "dom_456",
            "address": "hello@example.com",
            "display_name": "Hello",
        })
        assert mailbox["id"] == "mbx_123"
        assert mailbox["address"] == "hello@example.com"

    def test_creates_mailbox_without_display_name(self) -> None:
        without_name = {**mock_mailbox, "display_name": None}

        def handler(request: httpx.Request) -> httpx.Response:
            body = json.loads(request.content)
            assert body == {
                "domain_id": "dom_456",
                "address": "hello@example.com",
            }
            return json_response(without_name)

        client = make_client(handler)
        mailbox = client.mailboxes.create({
            "domain_id": "dom_456",
            "address": "hello@example.com",
        })
        assert mailbox["display_name"] is None


class TestList:
    def test_sends_get_mailboxes(self) -> None:
        response = {
            "data": [mock_mailbox],
            "pagination": {"next_cursor": None, "has_more": False},
        }

        def handler(request: httpx.Request) -> httpx.Response:
            assert request.method == "GET"
            assert request.url.path == "/v1/mailboxes"
            return json_response(response)

        client = make_client(handler)
        result = client.mailboxes.list()
        assert len(result["data"]) == 1
        assert result["data"][0]["id"] == "mbx_123"

    def test_sends_domain_id_filter(self) -> None:
        response = {
            "data": [],
            "pagination": {"next_cursor": None, "has_more": False},
        }

        def handler(request: httpx.Request) -> httpx.Response:
            assert str(request.url.params.get("domain_id")) == "dom_456"
            return json_response(response)

        client = make_client(handler)
        client.mailboxes.list({"domain_id": "dom_456"})

    def test_sends_cursor_and_limit(self) -> None:
        response = {
            "data": [],
            "pagination": {"next_cursor": None, "has_more": False},
        }

        def handler(request: httpx.Request) -> httpx.Response:
            assert str(request.url.params.get("cursor")) == "cur_xyz"
            assert str(request.url.params.get("limit")) == "10"
            return json_response(response)

        client = make_client(handler)
        client.mailboxes.list({"cursor": "cur_xyz", "limit": 10})


class TestGet:
    def test_sends_get_mailboxes_id(self) -> None:
        def handler(request: httpx.Request) -> httpx.Response:
            assert request.method == "GET"
            assert request.url.path == "/v1/mailboxes/mbx_123"
            return json_response(mock_mailbox)

        client = make_client(handler)
        mailbox = client.mailboxes.get("mbx_123")
        assert mailbox["id"] == "mbx_123"
        assert mailbox["address"] == "hello@example.com"


class TestUpdate:
    def test_sends_patch_mailboxes_id_with_body(self) -> None:
        updated = {**mock_mailbox, "display_name": "Updated Name"}

        def handler(request: httpx.Request) -> httpx.Response:
            assert request.method == "PATCH"
            assert request.url.path == "/v1/mailboxes/mbx_123"
            body = json.loads(request.content)
            assert body == {"display_name": "Updated Name"}
            return json_response(updated)

        client = make_client(handler)
        mailbox = client.mailboxes.update("mbx_123", {"display_name": "Updated Name"})
        assert mailbox["display_name"] == "Updated Name"

    def test_sends_null_to_clear_display_name(self) -> None:
        updated = {**mock_mailbox, "display_name": None}

        def handler(request: httpx.Request) -> httpx.Response:
            body = json.loads(request.content)
            assert body == {"display_name": None}
            return json_response(updated)

        client = make_client(handler)
        mailbox = client.mailboxes.update("mbx_123", {"display_name": None})
        assert mailbox["display_name"] is None


class TestDelete:
    def test_sends_delete_mailboxes_id(self) -> None:
        def handler(request: httpx.Request) -> httpx.Response:
            assert request.method == "DELETE"
            assert request.url.path == "/v1/mailboxes/mbx_123"
            return httpx.Response(204)

        client = make_client(handler)
        result = client.mailboxes.delete("mbx_123")
        assert result is None


