from unittest import TestCase

from lib.hub.hub_options_funds_lib import (
    merge_board_row_balances,
    merge_perp_options_balances,
    options_balances_usdt_equiv,
    repair_double_counted_fund_entry,
)


class HubOptionsFundsLibTests(TestCase):
    def test_options_balances_usdt_equiv(self):
        snap = {
            "ok": True,
            "enabled": True,
            "balances": {"funding_usdc": 10, "trading_usdt": 5, "trading_usdc": 2},
        }
        out = options_balances_usdt_equiv(snap)
        self.assertTrue(out["ok"])
        self.assertEqual(out["funding_usdt"], 10.0)
        self.assertEqual(out["trading_usdt"], 7.0)
        self.assertEqual(out["funding_usdc_equiv"], 10.0)
        self.assertEqual(out["trading_usdc_equiv"], 2.0)

    def test_merge_perp_options_balances_adds_usdc_only(self):
        """永续已含同账户 USDT 时,只叠加期权 USDC,避免双计."""
        out = merge_perp_options_balances(
            100,
            50,
            {
                "ok": True,
                "enabled": True,
                "balances": {
                    "funding_usdt": 100,
                    "funding_usdc": 8,
                    "trading_usdt": 50,
                    "trading_usdc": 4,
                },
            },
        )
        self.assertEqual(out["funding_usdt"], 108.0)
        self.assertEqual(out["trading_usdt"], 54.0)
        self.assertEqual(out["total_usdt"], 162.0)
        self.assertEqual(out["options_funding_usdt"], 8.0)
        self.assertEqual(out["options_trading_usdt"], 4.0)

    def test_merge_board_row_balances(self):
        row = {
            "account_ok": True,
            "funding_usdt": 20,
            "trading_usdt": 30,
            "capabilities": ["options"],
            "options": {
                "ok": True,
                "enabled": True,
                "balances": {"funding_usdt": 20, "funding_usdc": 1, "trading_usdc": 2},
                "positions": [{"inst_id": "X"}],
                "upl_total_usdc": 0.5,
            },
        }
        out = merge_board_row_balances(row)
        self.assertEqual(out["total_usdt"], 53.0)
        self.assertEqual(out["options_open_position_count"], 1)
        self.assertEqual(out["options_float_pnl_u"], 0.5)

    def test_options_float_pnl_usdt_coin_converts_by_index(self):
        from lib.hub.hub_options_funds_lib import options_float_pnl_usdt

        snap = {
            "ok": True,
            "enabled": True,
            "options_margin_mode": "coin",
            "options_index_px": 2280.0,
            "upl_total_usdc": 0.0016,
            "positions": [
                {
                    "inst_id": "ETH-USD-260822-2250-C",
                    "margin_mode": "coin",
                    "premium_ccy": "ETH",
                    "upl": 0.0016,
                    "idx_px": 2280.0,
                }
            ],
        }
        out = options_float_pnl_usdt(snap)
        self.assertAlmostEqual(out, round(0.0016 * 2280.0, 4), places=4)

    def test_repair_double_counted_fund_entry(self):
        raw = {
            "funding_usdt": 586.82,
            "trading_usdt": 69.46,
            "total_usdt": 656.28,
            "options_funding_usdt": 293.26,
            "options_trading_usdt": 69.44,
        }
        fixed = repair_double_counted_fund_entry(raw)
        self.assertTrue(fixed.get("repaired_double_count"))
        self.assertEqual(fixed["funding_usdt"], 293.26)
        self.assertEqual(fixed["trading_usdt"], 69.44)
        self.assertEqual(fixed["total_usdt"], round(293.26 + 69.44, 4))

    def test_repair_skips_new_usdc_only_options_line(self):
        raw = {
            "funding_usdt": 293.26,
            "trading_usdt": 69.44,
            "total_usdt": 362.7,
            "options_funding_usdt": 0.5,
            "options_trading_usdt": 69.42,
        }
        fixed = repair_double_counted_fund_entry(raw)
        self.assertFalse(fixed.get("repaired_double_count"))
        self.assertEqual(fixed["total_usdt"], 362.7)
