namespace KArtSell.Modules.SignalEngine.Domain.Policies;

public sealed class GapFloorBreachPolicy : ISellPolicy
{
    public int Priority => SellPolicyContract.GapFloorBreachPriority;
    public string PolicyId => SellPolicyContract.GapFloorBreachPolicyId;

    public SellPolicyResult Evaluate(SellDecisionInput input)
    {
        const decimal requested = SellPolicyContract.GapFloorSellRatioOfLot;
        if (input.GapBelowFloorAtr < SellPolicyContract.GapFloorAtrThreshold)
        {
            return SellPolicyResult.NotApplicable(PolicyId, Priority, "GAP_BELOW_1_5_ATR");
        }

        if (!input.CooldownSatisfied)
        {
            return SellPolicyResult.Blocked(PolicyId, Priority, "COOLDOWN_NOT_SATISFIED", requested);
        }

        var max = input.MaxSellRatioPreservingStrategicCore();
        var applied = Math.Min(requested, max);
        if (applied <= 0m)
        {
            return SellPolicyResult.Blocked(PolicyId, Priority, "STRATEGIC_CORE_BLOCKED", requested);
        }

        var decision = Create(input, applied, "GAP_FLOOR_BREACH");
        return SellPolicyResult.Applied(decision, requested, applied < requested);
    }

    private SellDecision Create(SellDecisionInput input, decimal ratio, string reason)
        => new(
            SellAction.PartialSell,
            ratio,
            input.TargetSecurityPortfolioWeightAfter(ratio),
            PolicyId,
            Priority,
            reason,
            input.EvidenceId,
            input.DatasetId,
            input.ModelVersion,
            input.ConfigVersion,
            input.CodeSha,
            true,
            Array.Empty<PolicyTraceEntry>());
}
