"""Tests for handler abstract base classes."""

import pytest

from entr_adapter_core.handlers import BaseHandler, RetrievalHandler
from entr_adapter_core.schemas import (
    AdapterResponse,
    DocumentDownloadResponse,
    DocumentPayload,
    RetrievalPayload,
    RetrievalResponse,
    StatusEnum,
)


# -- Concrete test implementations --

class ValidHandler(BaseHandler):
    """A minimal valid handler for testing."""

    async def process(self, payload: DocumentPayload) -> AdapterResponse:
        return AdapterResponse(
            document_id=payload.document_id,
            status=StatusEnum.SUCCESS,
        )


class IncompleteHandler(BaseHandler):
    """Handler missing process() — should fail to instantiate."""
    pass


class ValidRetrievalHandler(RetrievalHandler):
    """A minimal valid retrieval handler for testing."""

    async def list_documents(self, payload: RetrievalPayload) -> RetrievalResponse:
        return RetrievalResponse(
            status=StatusEnum.SUCCESS,
            documents=[],
        )

    async def get_document(self, document_identifier: str) -> DocumentDownloadResponse:
        return DocumentDownloadResponse(
            document_identifier="test.pdf",
            adapter_document_id=document_identifier,
            content_b64="dGVzdA==",
        )


class MissingListHandler(RetrievalHandler):
    """Retrieval handler missing list_documents()."""

    async def get_document(self, document_identifier: str) -> DocumentDownloadResponse:
        return DocumentDownloadResponse(
            document_identifier="test.pdf",
            adapter_document_id=document_identifier,
            content_b64="dGVzdA==",
        )


class MissingGetHandler(RetrievalHandler):
    """Retrieval handler missing get_document()."""

    async def list_documents(self, payload: RetrievalPayload) -> RetrievalResponse:
        return RetrievalResponse(
            status=StatusEnum.SUCCESS,
            documents=[],
        )


# -- BaseHandler tests --

class TestBaseHandler:

    def test_cannot_instantiate_directly(self):
        with pytest.raises(TypeError):
            BaseHandler()

    def test_subclass_missing_process_raises_type_error(self):
        with pytest.raises(TypeError):
            IncompleteHandler()

    def test_valid_subclass_instantiates(self):
        handler = ValidHandler()
        assert isinstance(handler, BaseHandler)

    def test_init_stores_settings(self):
        settings = {"api_key": "test"}
        handler = ValidHandler(settings=settings)
        assert handler.settings == {"api_key": "test"}

    def test_init_stores_retrieval_handler(self):
        retrieval = ValidRetrievalHandler()
        handler = ValidHandler(retrieval_handler=retrieval)
        assert handler.retrieval_handler is retrieval

    def test_init_stores_kwargs(self):
        handler = ValidHandler(custom_param="value", another=42)
        assert handler.kwargs == {"custom_param": "value", "another": 42}

    def test_init_defaults_to_none(self):
        handler = ValidHandler()
        assert handler.settings is None
        assert handler.retrieval_handler is None
        assert handler.kwargs == {}

    @pytest.mark.asyncio
    async def test_process_accepts_payload_returns_response(self):
        handler = ValidHandler()
        payload = DocumentPayload(
            adapter_identifier="test",
            document_id=1,
            data={"key": "value"},
        )
        response = await handler.process(payload)
        assert isinstance(response, AdapterResponse)
        assert response.document_id == 1
        assert response.status == StatusEnum.SUCCESS


# -- RetrievalHandler tests --

class TestRetrievalHandler:

    def test_cannot_instantiate_directly(self):
        with pytest.raises(TypeError):
            RetrievalHandler()

    def test_missing_list_documents_raises_type_error(self):
        with pytest.raises(TypeError):
            MissingListHandler()

    def test_missing_get_document_raises_type_error(self):
        with pytest.raises(TypeError):
            MissingGetHandler()

    def test_valid_subclass_instantiates(self):
        handler = ValidRetrievalHandler()
        assert isinstance(handler, RetrievalHandler)

    @pytest.mark.asyncio
    async def test_list_documents_accepts_payload_returns_response(self):
        handler = ValidRetrievalHandler()
        payload = RetrievalPayload(source_identifier="test-source", date_from="2026-01-01")
        response = await handler.list_documents(payload)
        assert isinstance(response, RetrievalResponse)
        assert response.status == StatusEnum.SUCCESS

    @pytest.mark.asyncio
    async def test_get_document_accepts_str_returns_response(self):
        handler = ValidRetrievalHandler()
        response = await handler.get_document("doc-123")
        assert isinstance(response, DocumentDownloadResponse)
        assert response.adapter_document_id == "doc-123"


# -- Integration: BaseHandler with RetrievalHandler --

class TestHandlerIntegration:

    def test_base_handler_stores_retrieval_handler(self):
        retrieval = ValidRetrievalHandler()
        handler = ValidHandler(
            settings={"env": "test"},
            retrieval_handler=retrieval,
        )
        assert handler.retrieval_handler is retrieval
        assert isinstance(handler.retrieval_handler, RetrievalHandler)
