"""MCP elicitation helpers for Login Flow v2.

Provides a unified way to present login URLs to users, using MCP elicitation
when the client supports it, or falling back to returning the URL in a message.
"""

import logging

from mcp.server.fastmcp import Context
from pydantic import BaseModel, Field

logger = logging.getLogger(__name__)


class LoginFlowConfirmation(BaseModel):
    """Schema for Login Flow v2 confirmation elicitation."""

    acknowledged: bool = Field(
        default=False,
        description="Check this box after completing login at the provided URL",
    )


async def present_login_url(
    ctx: Context,
    login_url: str,
    message: str | None = None,
) -> str:
    """Present a login URL to the user via MCP elicitation or message.

    Tries MCP elicitation first (ctx.elicit) for interactive clients.
    Falls back to returning the URL as a plain message.

    Args:
        ctx: MCP context
        login_url: URL the user should open in their browser
        message: Optional custom message (defaults to standard Login Flow prompt)

    Returns:
        "accepted" if user acknowledged via elicitation,
        "declined" if user declined,
        "message_only" if elicitation not supported (URL returned in message)
    """
    if message is None:
        message = (
            f"Please log in to Nextcloud to grant access:\n\n"
            f"{login_url}\n\n"
            f"Open this URL in your browser, log in, and grant the requested permissions. "
            f"Then check the box below and click OK."
        )

    if not hasattr(ctx, "elicit"):
        logger.debug(
            "Elicitation not available (no elicit method), returning URL in message"
        )
        return "message_only"

    try:
        result = await ctx.elicit(
            message=message,
            schema=LoginFlowConfirmation,
        )

        if result.action == "accept":
            if hasattr(result, "data") and not result.data.acknowledged:  # type: ignore[union-attr]
                logger.warning(
                    "User accepted login flow without checking the acknowledged box — "
                    "login completion will be verified via polling"
                )
            logger.info("User acknowledged login flow completion")
            return "accepted"
        elif result.action == "decline":
            logger.info("User declined login flow")
            return "declined"
        else:
            logger.info("User cancelled login flow")
            return "cancelled"

    except NotImplementedError:
        # Elicitation not supported by this client/SDK - fall back to message
        logger.debug("Elicitation not available, returning URL in message")
        return "message_only"
    except Exception as e:
        logger.warning(
            f"Elicitation failed unexpectedly ({type(e).__name__}: {e}), "
            "falling back to message"
        )
        return "message_only"
