using System.ComponentModel.DataAnnotations;
using Managing.Domain.Risk;
using Managing.Domain.Scenarios;
using Orleans;
using static Managing.Common.Enums;

namespace Managing.Domain.Bots;

[GenerateSerializer]
public class TradingBotConfig
{
    [Id(0)]
    [Required] public string AccountName { get; set; }
    
    [Id(1)]
    [Required] public LightMoneyManagement MoneyManagement { get; set; }
    
    [Id(2)]
    [Required] public Ticker Ticker { get; set; }
    
    [Id(3)]
    [Required] public Timeframe Timeframe { get; set; }
    
    [Id(4)]
    [Required] public bool IsForWatchingOnly { get; set; }
    
    [Id(5)]
    [Required] public decimal BotTradingBalance { get; set; }
    
    [Id(6)]
    [Required] public bool IsForBacktest { get; set; }
    
    [Id(7)]
    [Required] public int CooldownPeriod { get; set; }
    
    [Id(8)]
    [Required] public int MaxLossStreak { get; set; }
    
    [Id(9)]
    [Required] public bool FlipPosition { get; set; }
    
    [Id(10)]
    [Required] public string Name { get; set; }

    /// <summary>
    /// Risk management configuration for advanced probabilistic analysis and position sizing.
    /// Contains all configurable parameters for Expected Utility Theory, Kelly Criterion, and probability thresholds.
    /// If null, default risk management settings will be used.
    /// </summary>
    [Id(11)]
    public RiskManagement RiskManagement { get; set; } = new();

    /// <summary>
    /// The lightweight scenario object containing all strategies. When provided, this takes precedence over ScenarioName.
    /// This allows running backtests without requiring scenarios to be saved in the database.
    /// Orleans-friendly version without FixedSizeQueue and User properties.
    /// </summary>
    [Id(12)]
    public LightScenario Scenario { get; set; }

    /// <summary>
    /// The scenario name to load from database. Only used when Scenario object is not provided.
    /// </summary>
    [Id(13)]
    public string ScenarioName { get; set; }

    /// <summary>
    /// Maximum time in hours that a position can remain open before being automatically closed.
    /// If null, time-based position closure is disabled.
    /// </summary>
    [Id(14)]
    public decimal? MaxPositionTimeHours { get; set; }

    /// <summary>
    /// When MaxPositionTimeHours is set and this is true, the position will be closed as soon as 
    /// it reaches breakeven or profit, rather than waiting for the full time duration.
    /// If false, the position will only be closed when MaxPositionTimeHours is reached.
    /// Default is false to maintain existing behavior.
    /// </summary>
    [Id(15)]
    public bool CloseEarlyWhenProfitable { get; set; } = false;

    /// <summary>
    /// If true, positions will only be flipped when the current position is in profit.
    /// If false, positions will be flipped regardless of profit status.
    /// Default is true for safer trading.
    /// </summary>
    [Id(16)]
    [Required]
    public bool FlipOnlyWhenInProfit { get; set; } = true;

    /// <summary>
    /// Whether to use Synth API for probabilistic price forecasts and risk assessment.
    /// When true, the bot will use Synth predictions for signal filtering, position risk assessment, and position monitoring.
    /// When false, the bot operates in traditional mode without Synth predictions.
    /// The actual Synth configuration is managed centrally in SynthPredictionService.
    /// </summary>
    [Id(17)]
    public bool UseSynthApi { get; set; } = false;

    /// <summary>
    /// Whether to use Synth predictions for position sizing adjustments and risk assessment
    /// </summary>
    [Id(18)]
    public bool UseForPositionSizing { get; set; } = true;

    /// <summary>
    /// Whether to use Synth predictions for signal filtering
    /// </summary>
    [Id(19)]
    public bool UseForSignalFiltering { get; set; } = true;

    /// <summary>
    /// Whether to use Synth predictions for dynamic stop-loss/take-profit adjustments
    /// </summary>
    [Id(20)]
    public bool UseForDynamicStopLoss { get; set; } = true;
}