from __future__ import annotations

import unittest
from datetime import datetime, timezone

from govoplan_core.core.modules import ModuleContext, ModuleManifest
from govoplan_core.core.postbox import (
    CAPABILITY_POSTBOX_ACCESS,
    CAPABILITY_POSTBOX_DELIVERY,
    CAPABILITY_POSTBOX_DIRECTORY,
    CAPABILITY_POSTBOX_EVIDENCE,
    CAPABILITY_POSTBOX_MESSAGES,
    PostboxAccessProvider,
    PostboxDeliveryProvider,
    PostboxDeliveryReceiptSummaryRef,
    PostboxDirectoryProvider,
    PostboxEvidenceProvider,
    PostboxMessagesProvider,
    postbox_access_provider,
    postbox_delivery_provider,
    postbox_directory_provider,
    postbox_evidence_provider,
    postbox_messages_provider,
)
from govoplan_core.core.registry import PlatformRegistry


class _PostboxProvider:
    def list_visible_postboxes(self, session, *, tenant_id, actor):
        del session, tenant_id, actor
        return ()

    def resolve_postbox(self, session, *, tenant_id, target, materialize=False):
        del session, tenant_id, target, materialize
        return None

    def delivery_catalog(self, session, *, tenant_id):
        del session, tenant_id
        return None

    def explain_access(self, session, *, tenant_id, postbox_id, actor, action):
        del session, tenant_id, postbox_id, actor, action
        return None

    def list_messages(
        self,
        session,
        *,
        tenant_id,
        postbox_ids,
        actor,
        limit=100,
        offset=0,
    ):
        del session, tenant_id, postbox_ids, actor, limit, offset
        return ()

    def get_message(self, session, *, tenant_id, message_id, actor):
        del session, tenant_id, message_id, actor
        return None

    def mark_message(self, session, *, tenant_id, message_id, actor, state):
        del session, tenant_id, message_id, actor, state
        return None

    def create_message(self, session, *, tenant_id, postbox_id, actor, request):
        del session, tenant_id, postbox_id, actor, request
        return None

    def reply_to_message(self, session, *, tenant_id, message_id, actor, request):
        del session, tenant_id, message_id, actor, request
        return None

    def deliver(self, session, request):
        del session, request
        return None

    def link_evidence(self, session, *, tenant_id, message_id, attachment):
        del session, tenant_id, message_id, attachment
        return None

    def delivery_receipt_summaries(
        self,
        session,
        *,
        tenant_id,
        producer_module,
        delivery_ids,
    ):
        del session, tenant_id, producer_module, delivery_ids
        return {}


class PostboxContractTests(unittest.TestCase):
    def test_protocols_and_registry_helpers_resolve_without_module_imports(self) -> None:
        provider = _PostboxProvider()
        self.assertIsInstance(provider, PostboxDirectoryProvider)
        self.assertIsInstance(provider, PostboxAccessProvider)
        self.assertIsInstance(provider, PostboxMessagesProvider)
        self.assertIsInstance(provider, PostboxDeliveryProvider)
        self.assertIsInstance(provider, PostboxEvidenceProvider)
        self.assertEqual(
            "delivery-1",
            PostboxDeliveryReceiptSummaryRef(
                delivery_id="delivery-1",
                message_id="message-1",
                postbox_id="postbox-1",
                delivery_status="accepted",
                accepted_at=datetime.now(timezone.utc),
            ).delivery_id,
        )

        registry = PlatformRegistry()
        registry.register(
            ModuleManifest(
                id="postbox_contract_test",
                name="Postbox contract test",
                version="test",
                capability_factories={
                    name: lambda context: provider
                    for name in (
                        CAPABILITY_POSTBOX_DIRECTORY,
                        CAPABILITY_POSTBOX_ACCESS,
                        CAPABILITY_POSTBOX_MESSAGES,
                        CAPABILITY_POSTBOX_DELIVERY,
                        CAPABILITY_POSTBOX_EVIDENCE,
                    )
                },
            )
        )
        registry.configure_capability_context(
            ModuleContext(registry=registry, settings=object())
        )

        self.assertIs(provider, postbox_directory_provider(registry))
        self.assertIs(provider, postbox_access_provider(registry))
        self.assertIs(provider, postbox_messages_provider(registry))
        self.assertIs(provider, postbox_delivery_provider(registry))
        self.assertIs(provider, postbox_evidence_provider(registry))

        empty = PlatformRegistry()
        self.assertIsNone(postbox_directory_provider(empty))
        self.assertIsNone(postbox_access_provider(empty))
        self.assertIsNone(postbox_messages_provider(empty))
        self.assertIsNone(postbox_delivery_provider(empty))
        self.assertIsNone(postbox_evidence_provider(empty))


if __name__ == "__main__":
    unittest.main()
