"""hub_calculator_market_lib 合约解析."""

import unittest
from unittest.mock import patch

from lib.hub.hub_calculator_market_lib import (
    amount_decimals_from_exchange,
    find_exchange,
    get_calculator_market,
    list_calculator_exchanges,
    make_amount_precise_fn_from_market,
    normalize_base_symbol,
    resolve_usdt_perp_symbol,
)


class FakeExchange:
    def __init__(self, markets: dict):
        self.markets = markets

    def market(self, symbol: str):
        return self.markets[symbol]

    def amount_to_precision(self, symbol: str, amount: float) -> str:
        return f"{float(amount):.3f}"


class HubCalculatorMarketLibTests(unittest.TestCase):
    def test_normalize_base_symbol(self):
        self.assertEqual(normalize_base_symbol("eth"), "ETH")
        self.assertEqual(normalize_base_symbol("ETH/USDT:USDT"), "ETH")
        self.assertEqual(normalize_base_symbol("ETHUSDT"), "ETH")

    def test_resolve_usdt_perp_symbol(self):
        ex = FakeExchange(
            {
                "ETH/USDT:USDT": {
                    "base": "ETH",
                    "quote": "USDT",
                    "swap": True,
                    "active": True,
                    "contractSize": 1.0,
                    "limits": {"amount": {"min": 0.001}},
                    "precision": {"price": 2, "amount": 3},
                }
            }
        )
        sym, err = resolve_usdt_perp_symbol(ex, "ETH")
        self.assertIsNone(err)
        self.assertEqual(sym, "ETH/USDT:USDT")

    def test_amount_decimals_from_exchange(self):
        ex = FakeExchange({})
        self.assertEqual(amount_decimals_from_exchange(ex, "ETH/USDT:USDT"), 3)

    def test_make_amount_precise_fn_from_market(self):
        fn = make_amount_precise_fn_from_market({"amount_decimals": 3, "min_amount": 0.001})
        self.assertEqual(fn(1.23456), 1.234)
        self.assertIsNone(fn(0.0001))

    @patch.dict("os.environ", {"HUB_BRIDGE_TOKEN": "test-token"}, clear=False)
    def test_hub_headers_use_x_hub_token(self):
        from lib.hub.hub_calculator_market_lib import _hub_headers

        self.assertEqual(_hub_headers(), {"X-Hub-Token": "test-token"})

    @patch("lib.hub.hub_calculator_market_lib.fetch_instance_market_sync")
    def test_get_calculator_market_from_instance(self, fetch_mock):
        fetch_mock.return_value = {
            "ok": True,
            "base": "ETH",
            "exchange_symbol": "ETH/USDT:USDT",
            "display_symbol": "ETH/USDT",
            "contract_size": 0.01,
            "price_tick": 0.01,
            "price_decimals": 2,
            "amount_decimals": 2,
            "min_amount": 0.01,
        }
        ex = {
            "id": "0",
            "key": "binance",
            "name": "币安 · crypto_monitor_binance",
            "enabled": True,
            "flask_url": "http://127.0.0.1:5001",
        }
        data, err = get_calculator_market("0", "ETH", ex=ex)
        self.assertIsNone(err)
        self.assertIsNotNone(data)
        assert data is not None
        self.assertEqual(data["exchange_id"], "0")
        self.assertEqual(data["exchange_name"], "币安 · crypto_monitor_binance")
        self.assertEqual(data["contract_size"], 0.01)

    @patch("lib.hub.hub_calculator_market_lib.enabled_exchanges")
    def test_list_calculator_exchanges(self, enabled_mock):
        enabled_mock.return_value = [
            {"id": "0", "key": "binance", "name": "币安", "enabled": True},
        ]
        rows = list_calculator_exchanges()
        self.assertEqual(len(rows), 1)
        self.assertEqual(rows[0]["id"], "0")

    def test_find_exchange_by_id(self):
        with patch(
            "lib.hub.hub_calculator_market_lib.load_settings",
            return_value={"exchanges": [{"id": "2", "key": "gate", "name": "Gate"}]},
        ):
            self.assertEqual(find_exchange("2")["key"], "gate")


if __name__ == "__main__":
    unittest.main()
