namespace KArtSell.Modules.SignalEngine.Domain;

/// <summary>
/// Approved implementation contract for the v12.3 research-candidate sell policy chain.
/// Values are mirrored in contracts/policies/sell-policy-contract.v1.json and checked by validate_v123.py.
/// Changing any value requires a Model Change record, Golden vectors and OOS impact evidence.
/// </summary>
public static class SellPolicyContract
{
    public const string ContractVersion = "sell-policy.v1";
    public const string DecisionContractVersion = "sell-decision.v2";
    public const int PolicyTraceSchemaVersion = 2;

    public const string HardImpairmentPolicyId = "ALG-SELL-001";
    public const string PortfolioSurvivalPolicyId = "ALG-SELL-PORT-001";
    public const string GapFloorBreachPolicyId = "ALG-SELL-002";
    public const string TwoCloseFloorBreachPolicyId = "ALG-SELL-003";
    public const string ConcentrationLiquidityPolicyId = "ALG-SELL-004";
    public const string OpportunityCostPolicyId = "ALG-SELL-005";

    public const int HardImpairmentPriority = 1000;
    public const int PortfolioSurvivalPriority = 900;
    public const int GapFloorBreachPriority = 800;
    public const int TwoCloseFloorBreachPriority = 700;
    public const int ConcentrationLiquidityPriority = 600;
    public const int OpportunityCostPriority = 500;

    public const decimal HardImpairmentSellRatioOfLot = 1.00m;
    public const decimal GapFloorAtrThreshold = 1.50m;
    public const decimal GapFloorSellRatioOfLot = 0.40m;
    public const int TwoCloseBreachCount = 2;
    public const decimal TwoCloseSellRatioOfLot = 0.20m;
    public const decimal OpportunityMinimumSellRatioOfLot = 0.10m;
    public const decimal OpportunityMaximumSellRatioOfLot = 0.25m;

    public static IReadOnlyList<SellPolicyDefinition> Definitions { get; } =
    [
        new(HardImpairmentPolicyId, HardImpairmentPriority, true),
        new(PortfolioSurvivalPolicyId, PortfolioSurvivalPriority, true),
        new(GapFloorBreachPolicyId, GapFloorBreachPriority, false),
        new(TwoCloseFloorBreachPolicyId, TwoCloseFloorBreachPriority, false),
        new(ConcentrationLiquidityPolicyId, ConcentrationLiquidityPriority, false),
        new(OpportunityCostPolicyId, OpportunityCostPriority, false)
    ];
}

public sealed record SellPolicyDefinition(string PolicyId, int Priority, bool MayCrossStrategicCore);
