"""Tests for helper tools."""

from __future__ import annotations

import os
import tempfile
from unittest.mock import patch

from liquidtrading.errors import SymbolNotFoundError
from liquidtrading.models import Account, Ticker
from liquid_mcp.config import Config, set_config


class TestCalculateTokenAmount:
    def test_calculate(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_token_amount

            result = calculate_token_amount("BTC-PERP", 1000, ctx=None)
            assert result["symbol"] == "BTC-PERP"
            assert result["usd_amount"] == 1000
            assert result["mark_price"] == 50000.0
            assert result["token_amount"] == 0.02
            assert "next_steps" in result

    def test_zero_mark_price(self, mock_client):
        mock_client.get_ticker.return_value = Ticker(
            symbol="DEAD-PERP", mark_price=0.0,
            volume_24h=0.0, change_24h=0.0, funding_rate=0.0,
        )
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_token_amount

            result = calculate_token_amount("DEAD-PERP", 1000, ctx=None)
            assert result["error"] is True
            assert "mark price" in result["message"].lower()

    def test_symbol_not_found(self, mock_client):
        mock_client.get_ticker.side_effect = SymbolNotFoundError(
            code="SYMBOL_NOT_FOUND", message="Symbol not found",
        )
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_token_amount

            result = calculate_token_amount("FAKE-PERP", 1000, ctx=None)
            assert result["error"] is True
            assert "get_markets" in result["next_steps"]


class TestCalculatePositionSize:
    def test_calculate(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_position_size

            result = calculate_position_size("BTC-PERP", 5.0, ctx=None)
            assert result["symbol"] == "BTC-PERP"
            assert result["percent_of_equity"] == 5.0
            assert result["equity"] == 10000.0
            assert result["usd_size"] == 500.0
            assert result["token_amount"] == 0.01
            assert "next_steps" in result

    def test_zero_equity(self, mock_client):
        mock_client.get_account.return_value = Account(
            equity=0.0, margin_used=0.0,
            available_balance=0.0, account_value=0.0,
        )
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_position_size

            result = calculate_position_size("BTC-PERP", 5.0, ctx=None)
            assert result["error"] is True
            assert "equity" in result["message"].lower()

    def test_zero_mark_price(self, mock_client):
        mock_client.get_ticker.return_value = Ticker(
            symbol="DEAD-PERP", mark_price=0.0,
            volume_24h=0.0, change_24h=0.0, funding_rate=0.0,
        )
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_position_size

            result = calculate_position_size("DEAD-PERP", 5.0, ctx=None)
            assert result["error"] is True
            assert "mark price" in result["message"].lower()

    def test_negative_percent(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import calculate_position_size

            result = calculate_position_size("BTC-PERP", -5.0, ctx=None)
            assert result["error"] is True
            assert "percent_of_equity" in result["message"]


class TestValidateTrade:
    def test_valid_trade(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import validate_trade

            result = validate_trade(
                "BTC-PERP", "buy", 100, leverage=5, ctx=None,
            )
            assert result["ok"] is True
            assert result["issues"] == []
            assert "place_order" in result["next_steps"]

    def test_exceeds_max_order(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=50.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
                from liquid_mcp.tools.helpers import validate_trade

                result = validate_trade(
                    "BTC-PERP", "buy", 100, ctx=None,
                )
                assert result["ok"] is False
                assert any("exceeds" in i for i in result["issues"])

    def test_invalid_side(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import validate_trade

            result = validate_trade(
                "BTC-PERP", "long", 100, ctx=None,
            )
            assert result["ok"] is False
            assert any("side" in i for i in result["issues"])

    def test_insufficient_balance(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=100000.0, daily_loss_limit=5000.0,
                audit_path=os.path.join(tmpdir, "trades.jsonl"),
            ))
            with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
                from liquid_mcp.tools.helpers import validate_trade

                result = validate_trade(
                    "BTC-PERP", "buy", 50000, ctx=None,
                )
                assert result["ok"] is False
                assert any("balance" in i.lower() for i in result["issues"])

    def test_symbol_not_found(self, mock_client):
        mock_client.get_account.side_effect = SymbolNotFoundError(
            code="SYMBOL_NOT_FOUND", message="Symbol not found",
        )
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import validate_trade

            result = validate_trade(
                "FAKE-PERP", "buy", 100, ctx=None,
            )
            assert result["ok"] is False
            assert any("not found" in i.lower() for i in result["issues"])

    def test_high_leverage_warning(self, mock_client):
        with patch("liquid_mcp.tools.helpers.get_client", return_value=mock_client):
            from liquid_mcp.tools.helpers import validate_trade

            result = validate_trade(
                "BTC-PERP", "buy", 100, leverage=50, ctx=None,
            )
            assert any("leverage" in i.lower() for i in result["issues"])
