"""Position management tools (trade scope required)."""

from __future__ import annotations

from typing import Any

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

from liquidtrading.errors import LiquidError
from liquid_mcp.audit import log_trade
from liquid_mcp.client_manager import get_client
from liquid_mcp.config import get_config
from liquid_mcp.error_handling import handle_sdk_error
from liquid_mcp.serializers import to_dict
from liquid_mcp.server import mcp


@mcp.tool(annotations=ToolAnnotations(destructiveHint=True))
def close_position(
    symbol: str, size: float | None = None, dry_run: bool = False, ctx: Context = None,
) -> dict[str, Any]:
    """Close an open position entirely or partially.

    Args:
        symbol: Trading pair, e.g. "BTC-PERP"
        size: Partial close size in coin units. Omit for full close.
        dry_run: Preview without executing (default False)
    """
    cfg = get_config()
    params = {"symbol": symbol, "size": size}

    if dry_run:
        result = {"dry_run": True, "would_execute": params, "status": "ok"}
        log_trade(cfg.audit_path, "close_position", params, result=result, dry_run=True)
        return {**result, "next_steps": ["get_positions", "get_account"]}

    try:
        client = get_client(cfg)
        close_result = client.close_position(symbol, size=size)
    except LiquidError as e:
        log_trade(cfg.audit_path, "close_position", params, error=str(e))
        return handle_sdk_error("close_position", e)

    result = to_dict(close_result)
    log_trade(cfg.audit_path, "close_position", params, result=result)
    return {**result, "next_steps": ["get_positions", "get_account"]}


@mcp.tool(annotations=ToolAnnotations(destructiveHint=True))
def set_tp_sl(
    symbol: str,
    tp: float | None = None,
    sl: float | None = None,
    dry_run: bool = False,
    ctx: Context = None,
) -> dict[str, Any]:
    """Set or update take-profit and/or stop-loss on a position.

    Args:
        symbol: Trading pair, e.g. "BTC-PERP"
        tp: Take-profit trigger price
        sl: Stop-loss trigger price
        dry_run: Preview without executing (default False)
    """
    cfg = get_config()
    params = {"symbol": symbol, "tp": tp, "sl": sl}

    if dry_run:
        result = {"dry_run": True, "would_execute": params, "status": "ok"}
        log_trade(cfg.audit_path, "set_tp_sl", params, result=result, dry_run=True)
        return {**result, "next_steps": ["get_positions"]}

    try:
        client = get_client(cfg)
        tp_sl = client.set_tp_sl(symbol, tp=tp, sl=sl)
    except LiquidError as e:
        log_trade(cfg.audit_path, "set_tp_sl", params, error=str(e))
        return handle_sdk_error("set_tp_sl", e)

    result = to_dict(tp_sl)
    log_trade(cfg.audit_path, "set_tp_sl", params, result=result)
    return {**result, "next_steps": ["get_positions", "close_position"]}


@mcp.tool(annotations=ToolAnnotations(destructiveHint=True))
def update_leverage(
    symbol: str,
    leverage: int,
    is_cross: bool = False,
    dry_run: bool = False,
    ctx: Context = None,
) -> dict[str, Any]:
    """Update the leverage for a symbol.

    WARNING: Increasing leverage on an existing position moves the liquidation
    price closer. Check get_positions for current liquidation price first.

    Args:
        symbol: Trading pair, e.g. "BTC-PERP"
        leverage: New leverage multiplier (1-200)
        is_cross: Use cross margin mode (default False = isolated)
        dry_run: Preview without executing (default False)
    """
    if not 1 <= leverage <= 200:
        return {
            "error": True,
            "message": "leverage must be between 1 and 200",
            "next_steps": ["get_positions"],
        }

    cfg = get_config()
    params = {"symbol": symbol, "leverage": leverage, "is_cross": is_cross}

    warnings: list[str] = []
    if leverage > 20:
        warnings.append(
            f"High leverage ({leverage}x). Liquidation risk is significantly elevated."
        )

    if dry_run:
        result: dict[str, Any] = {"dry_run": True, "would_execute": params, "status": "ok"}
        if warnings:
            result["warnings"] = warnings
        log_trade(cfg.audit_path, "update_leverage", params, result=result, dry_run=True)
        return {**result, "next_steps": ["get_positions"]}

    try:
        client = get_client(cfg)
        lev = client.update_leverage(symbol, leverage, is_cross=is_cross)
    except LiquidError as e:
        log_trade(cfg.audit_path, "update_leverage", params, error=str(e))
        return handle_sdk_error("update_leverage", e)

    result = to_dict(lev)
    if warnings:
        result["warnings"] = warnings
    log_trade(cfg.audit_path, "update_leverage", params, result=result)
    return {**result, "next_steps": ["get_positions", "update_margin"]}


@mcp.tool(annotations=ToolAnnotations(destructiveHint=True))
def update_margin(
    symbol: str, amount: float, dry_run: bool = False, ctx: Context = None,
) -> dict[str, Any]:
    """Adjust the isolated margin on a position.

    Args:
        symbol: Trading pair, e.g. "BTC-PERP"
        amount: Margin to add (positive) or remove (negative)
        dry_run: Preview without executing (default False)
    """
    cfg = get_config()
    params = {"symbol": symbol, "amount": amount}

    if dry_run:
        result = {"dry_run": True, "would_execute": params, "status": "ok"}
        log_trade(cfg.audit_path, "update_margin", params, result=result, dry_run=True)
        return {**result, "next_steps": ["get_positions"]}

    try:
        client = get_client(cfg)
        margin = client.update_margin(symbol, amount)
    except LiquidError as e:
        log_trade(cfg.audit_path, "update_margin", params, error=str(e))
        return handle_sdk_error("update_margin", e)

    result = to_dict(margin)
    log_trade(cfg.audit_path, "update_margin", params, result=result)
    return {**result, "next_steps": ["get_positions", "update_leverage"]}
