"""Mock handler reference implementation for testing and new adapter development.

This module provides reference implementations of BaseHandler and RetrievalHandler
that demonstrate the recommended patterns for building ENTR adapter handlers.

MockProcessHandler follows the recommended flow:
    1. Validate — check input payload for required fields
    2. Transform — convert extracted data into target format
    3. Send — simulate sending to an external system (logging only)
    4. Respond — return an AdapterResponse with appropriate status

Other mock handlers demonstrate specific patterns:
    - MockReviewHandler: review_required flow with ReviewSuggestion/ProposedValue
    - MockRetrievalHandler: document listing and downloading
    - MockFailingHandler: unhandled exception behavior (flight recorder testing)
    - MockStatefulHandler: deliberately bad pattern — stores state on self
      (used exclusively in concurrent-request tests to prove state leakage)
"""

import asyncio
import logging

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

logger = logging.getLogger(__name__)


class MockProcessHandler(BaseHandler):
    """Reference implementation demonstrating the recommended handler flow.

    Validates that ``payload.data`` contains an ``invoice_number`` field,
    transforms it to uppercase, logs the simulated send, and returns success.
    """

    async def process(self, payload: DocumentPayload) -> AdapterResponse:
        # 1. Validate
        if "invoice_number" not in payload.data:
            logger.warning("Missing invoice_number in payload data")
            return AdapterResponse(
                document_id=payload.document_id,
                status=StatusEnum.FAILED,
                failure_type="validation_error",
                failure_reason="Missing required field: invoice_number",
            )

        # 2. Transform
        transformed_data = {
            "invoice_number": payload.data["invoice_number"].upper(),
            "amount": payload.data.get("amount"),
            "vendor": payload.data.get("vendor"),
        }
        logger.info("Transformed data for document %d", payload.document_id)

        # 3. Send (simulated)
        logger.info(
            "Sending document %d to target system", payload.document_id
        )

        # 4. Respond
        return AdapterResponse(
            document_id=payload.document_id,
            status=StatusEnum.SUCCESS,
            details=transformed_data,
        )


class MockReviewHandler(BaseHandler):
    """Demonstrates the review_required flow with suggestions."""

    async def process(self, payload: DocumentPayload) -> AdapterResponse:
        logger.info("Review handler processing document %d", payload.document_id)
        return AdapterResponse(
            document_id=payload.document_id,
            status=StatusEnum.REVIEW_REQUIRED,
            review_reason="Ambiguous product match",
            review_suggestions=[
                ReviewSuggestion(
                    field_path="line_items.0.product_id",
                    original_value=payload.data.get("product_id", "UNKNOWN"),
                    proposed_values=[
                        ProposedValue(value="P-100", description="Exact match (95%)"),
                        ProposedValue(value="P-101", description="Fuzzy match (78%)"),
                    ],
                    reason="Multiple product matches found",
                ),
            ],
        )


class MockRetrievalHandler(RetrievalHandler):
    """Demonstrates document listing and downloading with static test data."""

    async def list_documents(
        self, payload: RetrievalPayload
    ) -> RetrievalResponse:
        logger.info("Listing documents for source: %s", payload.source_identifier)
        return RetrievalResponse(
            status=StatusEnum.SUCCESS,
            documents=[
                DocumentIdentifier(
                    document_identifier="doc-001",
                    filename="invoice_2026_001.pdf",
                ),
                DocumentIdentifier(
                    document_identifier="doc-002",
                    filename="invoice_2026_002.pdf",
                ),
            ],
        )

    async def get_document(
        self, document_identifier: str
    ) -> DocumentDownloadResponse:
        logger.info("Downloading document: %s", document_identifier)
        return DocumentDownloadResponse(
            document_identifier=f"{document_identifier}.pdf",
            adapter_document_id=document_identifier,
            content_b64="dGVzdCBjb250ZW50",  # "test content" in base64
        )


class MockFailingHandler(BaseHandler):
    """Raises an unhandled exception — used to test flight recorder on errors."""

    async def process(self, payload: DocumentPayload) -> AdapterResponse:
        logger.info("About to fail for document %d", payload.document_id)
        raise RuntimeError("Simulated unhandled error in handler")


class MockStatefulHandler(BaseHandler):
    """Deliberately bad pattern: stores request state on self.

    Used EXCLUSIVELY in the concurrent-request smoke test to prove that
    state leakage occurs when handlers violate the singleton convention.
    Do NOT use this as a reference for real handlers.
    """

    async def process(self, payload: DocumentPayload) -> AdapterResponse:
        # BAD: storing per-request data on the shared singleton instance
        self.last_document_id = payload.document_id
        # Yield control to allow other concurrent requests to interleave
        await asyncio.sleep(0.01)
        # By now, another request may have overwritten self.last_document_id
        return AdapterResponse(
            document_id=self.last_document_id,
            status=StatusEnum.SUCCESS,
            details={"observed_document_id": self.last_document_id},
        )
