"""Tests for position tools."""

from __future__ import annotations

import os
import tempfile
from unittest.mock import patch

from liquidtrading.errors import SymbolNotFoundError
from liquid_mcp.config import Config, set_config


class TestClosePosition:
    def test_close_position(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import close_position

                result = close_position("BTC-PERP", ctx=None)
                assert result["status"] == "closed"
                assert "next_steps" in result

    def test_close_position_dry_run(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import close_position

                result = close_position("BTC-PERP", dry_run=True, ctx=None)
                assert result["dry_run"] is True
                assert "would_execute" in result
                mock_client.close_position.assert_not_called()

    def test_close_position_error(self, mock_client):
        mock_client.close_position.side_effect = SymbolNotFoundError(
            code="SYMBOL_NOT_FOUND", message="No position found",
        )
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import close_position

                result = close_position("FAKE-PERP", ctx=None)
                assert result["error"] is True


class TestSetTpSl:
    def test_set_tp_sl(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import set_tp_sl

                result = set_tp_sl("BTC-PERP", tp=52000, sl=48000, ctx=None)
                assert "tp" in result
                assert "sl" in result
                assert "next_steps" in result

    def test_set_tp_sl_dry_run(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import set_tp_sl

                result = set_tp_sl("BTC-PERP", tp=52000, sl=48000, dry_run=True, ctx=None)
                assert result["dry_run"] is True
                assert "would_execute" in result


class TestUpdateLeverage:
    def test_update_leverage(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import update_leverage

                result = update_leverage("BTC-PERP", 10, ctx=None)
                assert result["leverage"] == 10
                assert "next_steps" in result

    def test_update_leverage_dry_run(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import update_leverage

                result = update_leverage("BTC-PERP", 10, dry_run=True, ctx=None)
                assert result["dry_run"] is True
                assert "would_execute" in result

    def test_update_leverage_invalid_range(self, mock_client):
        with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
            from liquid_mcp.tools.positions import update_leverage

            result = update_leverage("BTC-PERP", 0, ctx=None)
            assert result["error"] is True
            assert "leverage" in result["message"]

    def test_update_leverage_too_high(self, mock_client):
        with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
            from liquid_mcp.tools.positions import update_leverage

            result = update_leverage("BTC-PERP", 201, ctx=None)
            assert result["error"] is True

    def test_update_leverage_high_warning(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import update_leverage

                result = update_leverage("BTC-PERP", 50, ctx=None)
                assert any("leverage" in w.lower() for w in result.get("warnings", []))


class TestUpdateMargin:
    def test_update_margin(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import update_margin

                result = update_margin("BTC-PERP", 500, ctx=None)
                assert result["margin_adjusted"] == 500.0
                assert "next_steps" in result

    def test_update_margin_dry_run(self, mock_client):
        with tempfile.TemporaryDirectory() as tmpdir:
            set_config(Config(
                api_key="lq_test", api_secret="sk_test", base_url=None,
                max_order_usd=1000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.positions.get_client", return_value=mock_client):
                from liquid_mcp.tools.positions import update_margin

                result = update_margin("BTC-PERP", 500, dry_run=True, ctx=None)
                assert result["dry_run"] is True
                assert "would_execute" in result
