Tikfinity/Configuration/TikfinityGiftRule.cs
using System;
using Sandbox;

namespace TikfinitySbox;

public sealed class TikfinityGiftRule
{
    [Property] public bool RuleEnabled { get; set; } = true;
    [Property] public int Priority { get; set; }
    [Property] public string GiftId { get; set; } = "";
    [Property] public string GiftName { get; set; } = "";
    [Property] public int MinimumCoins { get; set; }
    [Property] public int MaximumCoins { get; set; }
    [Property] public string Route { get; set; } = "gift.default";
    [Property] public TikfinityAmountMode AmountMode { get; set; } = TikfinityAmountMode.RepeatCount;
    [Property, Range( 1, 1000 )] public int AmountDivisor { get; set; } = 1;
    [Property, Range( 1, 1000 )] public int MaxAmount { get; set; } = 100;
    [Property, Range( 0f, 300f )] public float CooldownSeconds { get; set; }
    [Property] public bool CooldownPerUser { get; set; }

    public bool Matches( TikfinityEvent evt )
    {
        if ( !RuleEnabled || evt is null || evt.Kind != TikfinityEventKind.Gift ) return false;
        if ( string.IsNullOrWhiteSpace( Route ) ) return false;

        if ( !string.IsNullOrWhiteSpace( GiftId ) &&
             !string.Equals( GiftId.Trim(), evt.GiftId, StringComparison.OrdinalIgnoreCase ) )
            return false;

        if ( !string.IsNullOrWhiteSpace( GiftName ) &&
             !string.Equals( GiftName.Trim(), evt.GiftName, StringComparison.OrdinalIgnoreCase ) )
            return false;

        var coins = evt.TotalCoins > 0 ? evt.TotalCoins : evt.GiftCoins;
        if ( MinimumCoins > 0 && coins < MinimumCoins ) return false;
        if ( MaximumCoins > 0 && coins > MaximumCoins ) return false;
        return true;
    }

    public int CalculateAmount( TikfinityEvent evt, int globalMaximum )
    {
        if ( evt is null ) return 1;

        long source = AmountMode switch
        {
            TikfinityAmountMode.RepeatCount => evt.RepeatCount,
            TikfinityAmountMode.GiftCoins => evt.GiftCoins,
            TikfinityAmountMode.TotalCoins => evt.TotalCoins,
            _ => 1
        };

        var divisor = AmountDivisor < 1 ? 1 : AmountDivisor;
        source /= divisor;
        if ( source < 1 ) source = 1;

        var ruleMaximum = MaxAmount < 1 ? 1 : MaxAmount;
        var safeGlobalMaximum = globalMaximum < 1 ? 1 : globalMaximum;
        var maximum = Math.Min( ruleMaximum, safeGlobalMaximum );
        return source > maximum ? maximum : (int)source;
    }
}