"""Bybit MCP Server implementation."""

import json

from mcp.server.fastmcp import FastMCP
from mcp.types import ToolAnnotations

from bybit_mcp_server.config import get_auth_enabled, get_host, get_issuer_url, get_port, get_transport
from bybit_mcp_server.decorators import execute_confirmed, get_impl, require_mode
from bybit_mcp_server.tools.account import register_account_tools
from bybit_mcp_server.tools.asset import register_asset_tools
from bybit_mcp_server.tools.market import register_market_tools
from bybit_mcp_server.tools.position import register_position_tools
from bybit_mcp_server.tools.trade import register_trade_tools


def create_mcp() -> FastMCP:
    """Create and configure the MCP server instance."""
    transport = get_transport()

    if transport == "streamable-http":
        kwargs: dict = {
            "stateless_http": True,
            "json_response": True,
            "host": get_host(),
            "port": get_port(),
        }

        if get_auth_enabled():
            from mcp.server.auth.settings import AuthSettings, ClientRegistrationOptions, RevocationOptions
            from pydantic import AnyHttpUrl

            from bybit_mcp_server.auth.db import init_db
            from bybit_mcp_server.auth.provider import BybitMCPAuthProvider

            db_path = init_db()
            auth_provider = BybitMCPAuthProvider(db_path)
            issuer_url = AnyHttpUrl(get_issuer_url())

            kwargs["auth_server_provider"] = auth_provider
            kwargs["auth"] = AuthSettings(
                issuer_url=issuer_url,
                resource_server_url=issuer_url,
                client_registration_options=ClientRegistrationOptions(
                    enabled=True,
                    valid_scopes=["mcp:tools"],
                    default_scopes=["mcp:tools"],
                ),
                revocation_options=RevocationOptions(enabled=True),
            )

        server = FastMCP("bybit-mcp-server", **kwargs)

        # Register settings web routes (only for remote mode with auth)
        if get_auth_enabled():
            from bybit_mcp_server.web.settings import register_settings_routes

            register_settings_routes(server, db_path)
    else:
        server = FastMCP("bybit-mcp-server")

    # Register all tool modules
    register_market_tools(server)
    register_account_tools(server)
    register_trade_tools(server)
    register_position_tools(server)
    register_asset_tools(server)

    # Cross-cutting confirmation tool
    write_destructive = ToolAnnotations(readOnlyHint=False, destructiveHint=True, openWorldHint=True)

    @server.tool(annotations=write_destructive)
    @require_mode("trade")
    async def confirm_order(confirmation_id: str) -> str:
        """Execute a previously prepared HIGH-risk operation after review.

        When a HIGH-risk tool (place_order, amend_order, cancel_all_orders, set_leverage,
        internal_transfer) is called, it returns a confirmation summary instead of executing.
        Call this tool with the confirmation_id to actually execute the operation.

        Args:
            confirmation_id: The confirmation_id returned by the HIGH-risk tool.
        """
        pending = execute_confirmed(confirmation_id)
        if pending is None:
            return json.dumps(
                {"error": "Confirmation not found or expired. Please retry the original operation."},
                indent=2,
            )

        impl = get_impl(pending["tool"])
        if impl is None:
            return json.dumps(
                {"error": f"No implementation found for tool: {pending['tool']}"},
                indent=2,
            )

        return await impl(**pending["kwargs"])

    return server


mcp = create_mcp()


def main():
    """Run the MCP server.

    Transport is controlled by BYBIT_MCP_TRANSPORT env var:
      - "stdio" (default): Local transport for Claude Desktop / Cursor
      - "streamable-http": Remote HTTP transport for Claude Custom Connectors

    For remote mode, also set:
      - BYBIT_MCP_HOST (default: 0.0.0.0)
      - BYBIT_MCP_PORT (default: 8000)

    For auth (remote mode), also set:
      - BYBIT_MCP_ADMIN_USERNAME, BYBIT_MCP_ADMIN_PASSWORD
      - BYBIT_MCP_SECRET_KEY, BYBIT_MCP_ISSUER_URL
    """
    transport = get_transport()

    if transport == "streamable-http":
        mcp.run(transport="streamable-http")
    else:
        mcp.run(transport="stdio")


if __name__ == "__main__":
    main()
