"""对冲计划虚实值选约与校验."""
import unittest

from lib.hedge_plan.hedge_plan_moneyness_lib import (
    is_atm_or_otm,
    is_itm_or_atm,
    parse_strike_from_inst,
    pick_itm_or_atm_contract,
    recommend_oo_legs,
    validate_oo_legs_moneyness,
    validate_po_option_moneyness,
)
from lib.hedge_plan.hedge_plan_orders_lib import validate_start_body


class TestHedgeMoneyness(unittest.TestCase):
    def test_parse_strike(self):
        self.assertEqual(parse_strike_from_inst("ETH-USD-260731-1800-P"), 1800.0)
        self.assertIsNone(parse_strike_from_inst("bad"))

    def test_po_geometry(self):
        # Call: K<=S 实/平
        self.assertTrue(is_itm_or_atm(opt_type="C", strike=3500, index_px=3510))
        self.assertFalse(is_itm_or_atm(opt_type="C", strike=3600, index_px=3510))
        # Put: K>=S
        self.assertTrue(is_itm_or_atm(opt_type="P", strike=3600, index_px=3510))
        self.assertFalse(is_itm_or_atm(opt_type="P", strike=3400, index_px=3510))

    def test_oo_geometry(self):
        self.assertTrue(is_atm_or_otm(opt_type="C", strike=3600, index_px=3510))
        self.assertFalse(is_atm_or_otm(opt_type="C", strike=3400, index_px=3510))
        self.assertTrue(is_atm_or_otm(opt_type="P", strike=3400, index_px=3510))
        self.assertFalse(is_atm_or_otm(opt_type="P", strike=3600, index_px=3510))

    def test_validate_po_rejects_otm(self):
        err = validate_po_option_moneyness(opt_type="P", strike=1700, index_px=1800)
        self.assertIsNotNone(err)
        self.assertIn("虚值", err)
        self.assertIsNone(
            validate_po_option_moneyness(opt_type="P", strike=1800, index_px=1800)
        )

    def test_validate_oo_rejects_itm(self):
        err = validate_oo_legs_moneyness(
            {"opt_type": "C", "strike": 1700},
            {"opt_type": "P", "strike": 1900},
            index_px=1800,
        )
        self.assertIsNotNone(err)
        self.assertIn("实值", err)
        self.assertIsNone(
            validate_oo_legs_moneyness(
                {"opt_type": "C", "strike": 1850},
                {"opt_type": "P", "strike": 1750},
                index_px=1800,
            )
        )

    def test_pick_itm_or_atm(self):
        contracts = [
            {"inst_id": "E-C-3600", "opt_type": "C", "strike": 3600},
            {"inst_id": "E-C-3500", "opt_type": "C", "strike": 3500},
            {"inst_id": "E-C-3400", "opt_type": "C", "strike": 3400},
        ]
        picked = pick_itm_or_atm_contract(
            contracts, opt_type="C", index_px=3510, itm_max_dist=200
        )
        self.assertIsNotNone(picked)
        self.assertEqual(picked["strike"], 3500)

    def test_recommend_oo(self):
        contracts = [
            {"inst_id": "E-C-1800", "opt_type": "C", "strike": 1800},
            {"inst_id": "E-P-1800", "opt_type": "P", "strike": 1800},
            {"inst_id": "E-C-1900", "opt_type": "C", "strike": 1900},
            {"inst_id": "E-P-1700", "opt_type": "P", "strike": 1700},
        ]
        pair = recommend_oo_legs(contracts, index_px=1800, template="atm_straddle")
        self.assertIsNotNone(pair)
        self.assertEqual(pair[0]["opt_type"], "C")
        self.assertEqual(pair[1]["opt_type"], "P")

    def test_validate_start_body_po_otm(self):
        err = validate_start_body(
            "perp_options",
            {
                "direction": "long",
                "entry": 1800,
                "tp": 1900,
                "sl": 1700,
                "contracts": 1,
                "opt_inst_id": "ETH-USD-260731-1700-P",
                "opt_type": "P",
                "strike": 1700,
                "index_px": 1800,
                "sheets": 1,
                "exchange_symbol": "ETH/USDT:USDT",
            },
        )
        self.assertIsNotNone(err)
        self.assertIn("虚值", err)

    def test_validate_start_body_oo_itm(self):
        err = validate_start_body(
            "options_options",
            {
                "profit_rr": 2,
                "index_px": 1800,
                "leg_a": {"inst_id": "ETH-USD-260731-1700-C", "opt_type": "C", "strike": 1700},
                "leg_b": {"inst_id": "ETH-USD-260731-1900-P", "opt_type": "P", "strike": 1900},
            },
        )
        self.assertIsNotNone(err)
        self.assertIn("实值", err)


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