"""FastAPI router with bundled adapter endpoints.

Provides ``create_adapter_router()`` which returns an ``APIRouter`` with
all standard ENTR adapter endpoints: /process, /list_documents,
/download_document, and /health.
"""

from __future__ import annotations

import logging
import os
import tomllib
from pathlib import Path
from typing import Any, Dict

from fastapi import APIRouter
from pydantic import BaseModel, Field

from entr_adapter_core.app.dispatcher import Dispatcher
from entr_adapter_core.handlers import BaseHandler
from entr_adapter_core.schemas import (
    AdapterResponse,
    DocumentDownloadPayload,
    DocumentDownloadResponse,
    DocumentPayload,
    RetrievalPayload,
    RetrievalResponse,
    StatusEnum,
)

logger = logging.getLogger(__name__)


class HealthResponse(BaseModel):
    """Response from the /health endpoint."""

    status: str = Field(default="ok")
    handlers: list[str] = Field(
        default_factory=list,
        description="Alphabetically sorted list of registered handler identifiers",
    )


class VersionInfo(BaseModel):
    """Response from the /version endpoint."""

    core_version: str = Field(..., description="The version of the ENTR-Core platform")
    adapter_version: str = Field(..., description="The version of the adapter")
    tenant_name: str = Field(..., description="The name of the tenant")


def create_adapter_router(
    handlers: Dict[str, BaseHandler],
    *,
    settings: Any = None,
) -> APIRouter:
    """Create a FastAPI router with all standard adapter endpoints.

    This is the composable building block for adapters. Use it directly
    when you need custom middleware, additional routes, or custom startup
    logic on your own FastAPI app. For the simpler case, use
    ``create_adapter_app()`` which wraps this router.

    Args:
        handlers: Mapping of adapter identifiers to handler instances.
        settings: Optional settings object. If it has an ``ENV`` attribute,
            debug endpoints are registered only when ``ENV == "local"``.

    Returns:
        A configured ``APIRouter`` with /process, /list_documents,
        /download_document, and /health endpoints.
    """
    dispatcher = Dispatcher(handlers=handlers)
    router = APIRouter()

    # -- Standard endpoints --

    @router.post("/process", response_model=AdapterResponse)
    async def process_document(payload: DocumentPayload) -> AdapterResponse:
        """Process a document payload by dispatching to the matching handler.

        The dispatcher looks up the handler by adapter_identifier, wraps the
        call with FlightRecorder for log capture, and returns the response
        with execution_logs attached.
        """
        return await dispatcher.dispatch_process(payload)

    @router.post("/list_documents", response_model=RetrievalResponse)
    async def list_documents(payload: RetrievalPayload) -> RetrievalResponse:
        """List available documents from an external source.

        Routes to the handler's retrieval_handler based on source_identifier.
        Returns an error response if no retrieval handler is configured.
        """
        return await dispatcher.dispatch_list_documents(
            payload.source_identifier, payload
        )

    @router.post("/download_document", response_model=DocumentDownloadResponse)
    async def download_document(request: DocumentDownloadPayload) -> DocumentDownloadResponse:
        """Download a specific document by identifier.

        Routes to the handler's retrieval_handler based on source_identifier.
        Returns an error response if no retrieval handler is configured.
        """
        try:
            return await dispatcher.dispatch_download_document(
                request.source_identifier, request.document_identifier
            )
        except ValueError as exc:
            # Dispatcher raises ValueError for missing handlers/retrieval
            # Return a structured error rather than HTTP error
            return DocumentDownloadResponse(
                document_identifier=request.document_identifier,
                adapter_document_id="",
                content_b64="",
            )

    @router.get("/adapters")
    async def list_adapters() -> list[str]:
        """Return a list of all registered adapter identifiers.

        Used by Core to populate adapter selection dropdowns.
        """
        return sorted(dispatcher.get_handler_identifiers())

    @router.get("/version", response_model=VersionInfo)
    async def get_version() -> VersionInfo:
        """Return version information about the adapter and Core platform.

        Reads the adapter version from pyproject.toml and the Core platform
        version from core-version.txt (both in the adapter project root).
        """
        adapter_version = "unknown"
        core_version = "unknown"
        tenant_name = getattr(settings, "TENANT_NAME", "unknown") if settings else "unknown"

        try:
            pyproject_path = Path("pyproject.toml")
            if pyproject_path.exists():
                with open(pyproject_path, "rb") as f:
                    pyproject_data = tomllib.load(f)
                    adapter_version = pyproject_data.get("project", {}).get("version", "unknown")
        except Exception as exc:
            logger.warning("Could not read adapter version: %s", exc)

        try:
            core_version_path = Path("core-version.txt")
            if core_version_path.exists():
                core_version = core_version_path.read_text().strip()
        except Exception as exc:
            logger.warning("Could not read core version: %s", exc)

        return VersionInfo(
            core_version=core_version,
            adapter_version=adapter_version,
            tenant_name=tenant_name,
        )

    @router.get("/health", response_model=HealthResponse)
    async def health() -> HealthResponse:
        """Shallow liveness check returning registered handler identifiers.

        No database or external service calls — just confirms the app is
        running and lists which handlers are registered.
        """
        return HealthResponse(
            status="ok",
            handlers=sorted(dispatcher.get_handler_identifiers()),
        )

    # -- Debug endpoints (conditional on ENV) --

    env = getattr(settings, "ENV", None) or os.environ.get("ENV", "production")

    if env == "local":
        logger.info("Debug endpoints enabled (ENV=local)")

        @router.get("/debug/handlers")
        async def debug_handlers() -> dict:
            """Return detailed handler information (debug only)."""
            info = {}
            for key, handler in handlers.items():
                info[key] = {
                    "handler_class": type(handler).__name__,
                    "has_retrieval_handler": handler.retrieval_handler is not None,
                    "retrieval_class": (
                        type(handler.retrieval_handler).__name__
                        if handler.retrieval_handler
                        else None
                    ),
                    "settings_type": (
                        type(handler.settings).__name__
                        if handler.settings
                        else None
                    ),
                }
            return {"handlers": info, "env": env}
    else:
        logger.info("Debug endpoints disabled (ENV=%s)", env)

    return router
