using System.ComponentModel.DataAnnotations;
using Managing.Common;
using Orleans;

namespace Managing.Domain.Risk;

/// <summary>
/// Risk management configuration for trading bots
/// Contains all configurable risk parameters for probabilistic analysis and position sizing
/// </summary>
[GenerateSerializer]
public class RiskManagement
{
    /// <summary>
    /// Threshold for adverse probability in signal validation (default: 20%)
    /// Signals with SL probability above this threshold may be filtered out
    /// Range: 0.05 (5%) to 0.50 (50%)
    /// </summary>
    [Id(0)]
    [Range(0.05, 0.50)]
    [Required]
    public decimal AdverseProbabilityThreshold { get; set; } = 0.20m;

    /// <summary>
    /// Threshold for favorable probability in signal validation (default: 30%)
    /// Used for additional signal filtering and confidence assessment
    /// Range: 0.10 (10%) to 0.70 (70%)
    /// </summary>
    [Id(1)]
    [Range(0.10, 0.70)]
    [Required]
    public decimal FavorableProbabilityThreshold { get; set; } = 0.30m;

    /// <summary>
    /// Risk aversion parameter for Expected Utility calculations (default: 1.0)
    /// Higher values = more risk-averse behavior in utility calculations
    /// Range: 0.1 (risk-seeking) to 5.0 (highly risk-averse)
    /// </summary>
    [Id(2)]
    [Range(0.1, 5.0)]
    [Required]
    public decimal RiskAversion { get; set; } = 1.0m;

    /// <summary>
    /// Minimum Kelly Criterion fraction to consider a trade favorable (default: 1%)
    /// Trades with Kelly fraction below this threshold are considered unfavorable
    /// Range: 0.5% to 10%
    /// </summary>
    [Id(3)]
    [Range(0.005, 0.10)]
    [Required]
    public decimal KellyMinimumThreshold { get; set; } = 0.01m;

    /// <summary>
    /// Maximum Kelly Criterion fraction cap for practical risk management (default: 25%)
    /// Prevents over-allocation even when Kelly suggests higher percentages
    /// Range: 5% to 50%
    /// </summary>
    [Id(4)]
    [Range(0.05, 0.50)]
    [Required]
    public decimal KellyMaximumCap { get; set; } = 0.25m;

    /// <summary>
    /// Maximum acceptable liquidation probability for position risk assessment (default: 10%)
    /// Positions with higher liquidation risk may be blocked or reduced
    /// Range: 5% to 30%
    /// </summary>
    [Id(5)]
    [Range(0.05, 0.30)]
    [Required]
    public decimal MaxLiquidationProbability { get; set; } = 0.10m;

    /// <summary>
    /// Time horizon in hours for signal validation analysis (default: 24 hours)
    /// Longer horizons provide more stable predictions but less responsive signals
    /// Range: 1 hour to 168 hours (1 week)
    /// </summary>
    [Id(6)]
    [Range(1, 168)]
    [Required]
    public int SignalValidationTimeHorizonHours { get; set; } = 24;

    /// <summary>
    /// Time horizon in hours for position risk monitoring (default: 6 hours)
    /// Shorter horizons for more frequent risk updates on open positions
    /// Range: 1 hour to 48 hours
    /// </summary>
    [Id(7)]
    [Range(1, 48)]
    [Required]
    public int PositionMonitoringTimeHorizonHours { get; set; } = 6;

    /// <summary>
    /// Probability threshold for issuing position risk warnings (default: 20%)
    /// Positions exceeding this liquidation risk will trigger warnings
    /// Range: 10% to 40%
    /// </summary>
    [Id(8)]
    [Range(0.10, 0.40)]
    [Required]
    public decimal PositionWarningThreshold { get; set; } = 0.20m;

    /// <summary>
    /// Probability threshold for automatic position closure (default: 50%)
    /// Positions exceeding this liquidation risk will be automatically closed
    /// Range: 30% to 80%
    /// </summary>
    [Id(9)]
    [Range(0.30, 0.80)]
    [Required]
    public decimal PositionAutoCloseThreshold { get; set; } = 0.50m;

    /// <summary>
    /// Fractional Kelly multiplier for conservative position sizing (default: 1.0)
    /// Values less than 1.0 implement fractional Kelly (e.g., 0.5 = half-Kelly)
    /// Range: 0.1 to 1.0
    /// </summary>
    [Id(10)]
    [Range(0.1, 1.0)]
    [Required]
    public decimal KellyFractionalMultiplier { get; set; } = 1.0m;

    /// <summary>
    /// Risk tolerance level affecting overall risk calculations
    /// </summary>
    [Id(11)]
    [Required]
    public Enums.RiskToleranceLevel RiskTolerance { get; set; } = Enums.RiskToleranceLevel.Moderate;

    /// <summary>
    /// Whether to use Expected Utility Theory for decision making
    /// </summary>
    [Id(12)]
    [Required]
    public bool UseExpectedUtility { get; set; } = true;

    /// <summary>
    /// Whether to use Kelly Criterion for position sizing recommendations
    /// </summary>
    [Id(13)]
    [Required]
    public bool UseKellyCriterion { get; set; } = true;

    /// <summary>
    /// Validates that the risk management configuration is coherent
    /// </summary>
    /// <returns>True if configuration is valid, false otherwise</returns>
    public bool IsConfigurationValid()
    {
        // Ensure favorable threshold is higher than adverse threshold
        if (FavorableProbabilityThreshold <= AdverseProbabilityThreshold)
            return false;

        // Ensure Kelly minimum is less than maximum
        if (KellyMinimumThreshold >= KellyMaximumCap)
            return false;

        // Ensure warning threshold is less than auto-close threshold
        if (PositionWarningThreshold >= PositionAutoCloseThreshold)
            return false;

        // Ensure signal validation horizon is longer than position monitoring
        if (SignalValidationTimeHorizonHours < PositionMonitoringTimeHorizonHours)
            return false;

        return true;
    }

    /// <summary>
    /// Gets a preset configuration based on risk tolerance level
    /// </summary>
    /// <param name="tolerance">Risk tolerance level</param>
    /// <returns>Configured RiskManagement instance</returns>
    public static RiskManagement GetPresetConfiguration(Enums.RiskToleranceLevel tolerance)
    {
        return tolerance switch
        {
            Enums.RiskToleranceLevel.Conservative => new RiskManagement
            {
                AdverseProbabilityThreshold = 0.15m,
                FavorableProbabilityThreshold = 0.40m,
                RiskAversion = 2.0m,
                KellyMinimumThreshold = 0.02m,
                KellyMaximumCap = 0.15m,
                MaxLiquidationProbability = 0.08m,
                PositionWarningThreshold = 0.15m,
                PositionAutoCloseThreshold = 0.35m,
                KellyFractionalMultiplier = 0.5m,
                RiskTolerance = tolerance
            },
            Enums.RiskToleranceLevel.Aggressive => new RiskManagement
            {
                AdverseProbabilityThreshold = 0.30m,
                FavorableProbabilityThreshold = 0.25m,
                RiskAversion = 0.5m,
                KellyMinimumThreshold = 0.005m,
                KellyMaximumCap = 0.40m,
                MaxLiquidationProbability = 0.15m,
                PositionWarningThreshold = 0.30m,
                PositionAutoCloseThreshold = 0.70m,
                KellyFractionalMultiplier = 1.0m,
                RiskTolerance = tolerance
            },
            _ => new RiskManagement { RiskTolerance = tolerance } // Moderate (default values)
        };
    }
}