from datetime import datetime, timezone
from decimal import Decimal
import unittest

from kartsell_policy_contract import SellAction, SellInput, default_chain


def base_input(**changes):
    values = dict(
        position_lot_id="lot-1",
        cycle_id="cycle-1",
        evidence_id="evidence-1",
        dataset_id="dataset-1",
        model_version="model-1",
        config_version="config-1",
        code_sha="sha-1",
        as_of=datetime(2026, 8, 1, 7, tzinfo=timezone.utc),
        published_at_cutoff=datetime(2026, 8, 1, 6, tzinfo=timezone.utc),
        current_portfolio_weight=Decimal("0.60"),
        strategic_core_floor_weight=Decimal("0.30"),
    )
    values.update(changes)
    return SellInput(**values)


class PolicyContractTests(unittest.TestCase):
    def test_hard_impairment_wins(self):
        result = default_chain().evaluate(base_input(
            hard_impairment_approved=True,
            capital_floor_breached=True,
            survival_sell_ratio_of_lot=Decimal("0.5"),
            gap_below_floor_atr=Decimal("2"),
        ))
        self.assertEqual("ALG-SELL-001", result.policy_id)
        self.assertEqual(SellAction.FULL_SELL, result.action)
        self.assertFalse(result.reentry_eligible)

    def test_gap_preserves_absolute_core_weight(self):
        result = default_chain().evaluate(base_input(
            strategic_core_floor_weight=Decimal("0.50"),
            gap_below_floor_atr=Decimal("2"),
        ))
        self.assertEqual("ALG-SELL-002", result.policy_id)
        self.assertEqual(Decimal("0.50000000"), result.target_portfolio_weight_after)

    def test_survival_can_cross_core(self):
        result = default_chain().evaluate(base_input(
            capital_floor_breached=True,
            survival_sell_ratio_of_lot=Decimal("0.50"),
        ))
        self.assertEqual("ALG-SELL-PORT-001", result.policy_id)
        self.assertEqual(Decimal("0.30000000"), result.target_portfolio_weight_after)

    def test_future_published_at_is_rejected(self):
        with self.assertRaises(ValueError):
            default_chain().evaluate(base_input(
                published_at_cutoff=datetime(2026, 8, 1, 8, tzinfo=timezone.utc)
            ))


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