"""对冲计划 P0 测算口径单测."""
import unittest

from lib.hedge_plan.hedge_plan_calc_lib import (
    build_options_options_preview,
    build_perp_options_preview,
    floor_contracts_to_precision,
    gate_status,
    option_expiry_pnl,
    option_premium_total,
    perp_pnl,
)


class TestHedgePlanCalc(unittest.TestCase):
    def test_perp_tp_accounting_is_profit_minus_premium(self):
        p = build_perp_options_preview(
            direction="long",
            entry=3200,
            tp=3400,
            sl=3000,
            contracts=50,
            contract_size=0.01,
            opt_type="P",
            strike=3100,
            sheets=10,
            ct_mult=0.01,
            premium_paid=8,
            index_px=3200,
        )
        self.assertEqual(p["summary"]["tp_total"], 92.0)
        self.assertEqual(p["scenarios"][0]["options_pnl"], -8.0)

    def test_perp_sl_accounting_is_option_plus_perp_signed(self):
        p = build_perp_options_preview(
            direction="long",
            entry=3200,
            tp=3400,
            sl=3000,
            contracts=50,
            contract_size=0.01,
            opt_type="P",
            strike=3100,
            sheets=10,
            ct_mult=0.01,
            premium_paid=8,
            index_px=3200,
        )
        self.assertEqual(p["summary"]["sl_total"], -98.0)
        self.assertEqual(p["summary"]["hedge_ratio_at_sl"], 2.0)

    def test_option_premium_and_expiry(self):
        self.assertEqual(option_premium_total(ask=80, sheets=1, ct_mult=0.01), 0.8)
        self.assertEqual(
            option_expiry_pnl(
                opt_type="P", strike=3100, spot=3000, sheets=10, ct_mult=0.01, premium_paid=8
            ),
            2.0,
        )

    def test_gate_perp_requires_full_margin_for_start_message(self):
        g = gate_status(
            hedge_enabled=True,
            sizing_mode="risk",
            plan_type="perp_options",
            options_enabled=True,
        )
        self.assertTrue(g["can_preview"])
        self.assertFalse(g["can_start"])
        self.assertTrue(any("全仓" in r for r in g["reasons"]))

    def test_oo_expiry_loss_flag(self):
        a = {"opt_type": "C", "strike": 3300, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
        b = {"opt_type": "P", "strike": 3100, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
        p = build_options_options_preview(
            target_price_up=3500,
            target_price_down=3000,
            index_px=3200,
            leg_a=a,
            leg_b=b,
        )
        self.assertEqual(p["summary"]["premium_paid"], 10)
        self.assertTrue(p["summary"]["expiry_is_loss"])
        self.assertEqual(len(p["scenarios"]), 4)
        self.assertEqual(p["scenarios"][0]["id"], "target_up")
        self.assertEqual(p["scenarios"][1]["id"], "target_down")

    def test_oo_legacy_single_target_still_works(self):
        a = {"opt_type": "C", "strike": 3300, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
        b = {"opt_type": "P", "strike": 3100, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
        p = build_options_options_preview(target_price=3500, index_px=3200, leg_a=a, leg_b=b)
        self.assertEqual(p["target_price_up"], 3500)
        self.assertEqual(p["target_price_down"], 3500)

    def test_perp_short_pnl(self):
        self.assertEqual(
            perp_pnl(direction="short", entry=100, exit_px=90, contracts=1, contract_size=1),
            10,
        )

    def test_floor_contracts_to_precision(self):
        self.assertEqual(floor_contracts_to_precision(4.569713, 4), 4.5697)
        self.assertEqual(floor_contracts_to_precision(4.569713, 0), 4.0)
        self.assertEqual(floor_contracts_to_precision(0, 4), 0.0)


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