using System;
using System.Collections.Generic;

namespace NT8.Core.Intelligence
{
    /// <summary>
    /// Risk operating mode used to control trade acceptance and sizing aggressiveness.
    /// </summary>
    public enum RiskMode
    {
        /// <summary>
        /// High Risk state - no new trades allowed.
        /// </summary>
        HR = 0,

        /// <summary>
        /// Diminished Confidence Play - very selective and reduced size.
        /// </summary>
        DCP = 1,

        /// <summary>
        /// Primary Confidence Play - baseline operating mode.
        /// </summary>
        PCP = 2,

        /// <summary>
        /// Elevated Confidence Play - increased aggressiveness when conditions are strong.
        /// </summary>
        ECP = 3
    }

    /// <summary>
    /// Configuration for one risk mode.
    /// </summary>
    public class RiskModeConfig
    {
        /// <summary>
        /// Risk mode identity.
        /// </summary>
        public RiskMode Mode { get; set; }

        /// <summary>
        /// Position size multiplier for this mode.
        /// </summary>
        public double SizeMultiplier { get; set; }

        /// <summary>
        /// Minimum trade grade required to allow a trade.
        /// </summary>
        public TradeGrade MinimumGrade { get; set; }

        /// <summary>
        /// Maximum daily risk allowed under this mode.
        /// </summary>
        public double MaxDailyRisk { get; set; }

        /// <summary>
        /// Maximum concurrent open trades in this mode.
        /// </summary>
        public int MaxConcurrentTrades { get; set; }

        /// <summary>
        /// Indicates whether aggressive entries are allowed.
        /// </summary>
        public bool AggressiveEntries { get; set; }

        /// <summary>
        /// Additional mode-specific settings.
        /// </summary>
        public Dictionary<string, object> CustomSettings { get; set; }

        /// <summary>
        /// Creates a risk mode configuration.
        /// </summary>
        /// <param name="mode">Risk mode identity.</param>
        /// <param name="sizeMultiplier">Size multiplier.</param>
        /// <param name="minimumGrade">Minimum accepted trade grade.</param>
        /// <param name="maxDailyRisk">Maximum daily risk.</param>
        /// <param name="maxConcurrentTrades">Maximum concurrent trades.</param>
        /// <param name="aggressiveEntries">Aggressive entry enable flag.</param>
        /// <param name="customSettings">Additional settings map.</param>
        public RiskModeConfig(
            RiskMode mode,
            double sizeMultiplier,
            TradeGrade minimumGrade,
            double maxDailyRisk,
            int maxConcurrentTrades,
            bool aggressiveEntries,
            Dictionary<string, object> customSettings)
        {
            if (sizeMultiplier < 0.0)
                throw new ArgumentException("sizeMultiplier must be non-negative", "sizeMultiplier");
            if (maxDailyRisk < 0.0)
                throw new ArgumentException("maxDailyRisk must be non-negative", "maxDailyRisk");
            if (maxConcurrentTrades < 0)
                throw new ArgumentException("maxConcurrentTrades must be non-negative", "maxConcurrentTrades");

            Mode = mode;
            SizeMultiplier = sizeMultiplier;
            MinimumGrade = minimumGrade;
            MaxDailyRisk = maxDailyRisk;
            MaxConcurrentTrades = maxConcurrentTrades;
            AggressiveEntries = aggressiveEntries;
            CustomSettings = customSettings ?? new Dictionary<string, object>();
        }
    }

    /// <summary>
    /// Rule that governs transitions between risk modes.
    /// </summary>
    public class ModeTransitionRule
    {
        /// <summary>
        /// Origin mode for this rule.
        /// </summary>
        public RiskMode FromMode { get; set; }

        /// <summary>
        /// Destination mode for this rule.
        /// </summary>
        public RiskMode ToMode { get; set; }

        /// <summary>
        /// Human-readable rule name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Optional description for diagnostics.
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Enables or disables rule evaluation.
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// Creates a transition rule.
        /// </summary>
        /// <param name="fromMode">Origin mode.</param>
        /// <param name="toMode">Destination mode.</param>
        /// <param name="name">Rule name.</param>
        /// <param name="description">Rule description.</param>
        /// <param name="enabled">Rule enabled flag.</param>
        public ModeTransitionRule(
            RiskMode fromMode,
            RiskMode toMode,
            string name,
            string description,
            bool enabled)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            FromMode = fromMode;
            ToMode = toMode;
            Name = name;
            Description = description ?? string.Empty;
            Enabled = enabled;
        }
    }

    /// <summary>
    /// Current risk mode state and transition metadata.
    /// </summary>
    public class RiskModeState
    {
        /// <summary>
        /// Current active risk mode.
        /// </summary>
        public RiskMode CurrentMode { get; set; }

        /// <summary>
        /// Previous mode before current transition.
        /// </summary>
        public RiskMode PreviousMode { get; set; }

        /// <summary>
        /// Last transition timestamp in UTC.
        /// </summary>
        public DateTime LastTransitionAtUtc { get; set; }

        /// <summary>
        /// Optional reason for last transition.
        /// </summary>
        public string LastTransitionReason { get; set; }

        /// <summary>
        /// Indicates whether current mode is manually overridden.
        /// </summary>
        public bool IsManualOverride { get; set; }

        /// <summary>
        /// Current mode duration.
        /// </summary>
        public TimeSpan ModeDuration { get; set; }

        /// <summary>
        /// Optional mode metadata for diagnostics.
        /// </summary>
        public Dictionary<string, object> Metadata { get; set; }

        /// <summary>
        /// Creates a risk mode state model.
        /// </summary>
        /// <param name="currentMode">Current mode.</param>
        /// <param name="previousMode">Previous mode.</param>
        /// <param name="lastTransitionAtUtc">Last transition time.</param>
        /// <param name="lastTransitionReason">Transition reason.</param>
        /// <param name="isManualOverride">Manual override flag.</param>
        /// <param name="modeDuration">Current mode duration.</param>
        /// <param name="metadata">Mode metadata map.</param>
        public RiskModeState(
            RiskMode currentMode,
            RiskMode previousMode,
            DateTime lastTransitionAtUtc,
            string lastTransitionReason,
            bool isManualOverride,
            TimeSpan modeDuration,
            Dictionary<string, object> metadata)
        {
            CurrentMode = currentMode;
            PreviousMode = previousMode;
            LastTransitionAtUtc = lastTransitionAtUtc;
            LastTransitionReason = lastTransitionReason ?? string.Empty;
            IsManualOverride = isManualOverride;
            ModeDuration = modeDuration;
            Metadata = metadata ?? new Dictionary<string, object>();
        }
    }

    /// <summary>
    /// Performance snapshot used for mode transition decisions.
    /// </summary>
    public class PerformanceMetrics
    {
        /// <summary>
        /// Current daily PnL.
        /// </summary>
        public double DailyPnL { get; set; }

        /// <summary>
        /// Consecutive winning trades.
        /// </summary>
        public int WinStreak { get; set; }

        /// <summary>
        /// Consecutive losing trades.
        /// </summary>
        public int LossStreak { get; set; }

        /// <summary>
        /// Recent win rate in range [0.0, 1.0].
        /// </summary>
        public double RecentWinRate { get; set; }

        /// <summary>
        /// Recent execution quality in range [0.0, 1.0].
        /// </summary>
        public double RecentExecutionQuality { get; set; }

        /// <summary>
        /// Current volatility regime.
        /// </summary>
        public VolatilityRegime VolatilityRegime { get; set; }

        /// <summary>
        /// Creates a performance metrics snapshot.
        /// </summary>
        /// <param name="dailyPnL">Current daily PnL.</param>
        /// <param name="winStreak">Win streak.</param>
        /// <param name="lossStreak">Loss streak.</param>
        /// <param name="recentWinRate">Recent win rate in [0.0, 1.0].</param>
        /// <param name="recentExecutionQuality">Recent execution quality in [0.0, 1.0].</param>
        /// <param name="volatilityRegime">Current volatility regime.</param>
        public PerformanceMetrics(
            double dailyPnL,
            int winStreak,
            int lossStreak,
            double recentWinRate,
            double recentExecutionQuality,
            VolatilityRegime volatilityRegime)
        {
            if (recentWinRate < 0.0 || recentWinRate > 1.0)
                throw new ArgumentException("recentWinRate must be between 0.0 and 1.0", "recentWinRate");
            if (recentExecutionQuality < 0.0 || recentExecutionQuality > 1.0)
                throw new ArgumentException("recentExecutionQuality must be between 0.0 and 1.0", "recentExecutionQuality");
            if (winStreak < 0)
                throw new ArgumentException("winStreak must be non-negative", "winStreak");
            if (lossStreak < 0)
                throw new ArgumentException("lossStreak must be non-negative", "lossStreak");

            DailyPnL = dailyPnL;
            WinStreak = winStreak;
            LossStreak = lossStreak;
            RecentWinRate = recentWinRate;
            RecentExecutionQuality = recentExecutionQuality;
            VolatilityRegime = volatilityRegime;
        }
    }
}
