using System;
using System.Collections.Generic;

namespace NT8.Core.MarketData
{
    /// <summary>
    /// Represents bid-ask spread information for a symbol
    /// </summary>
    public class SpreadInfo
    {
        /// <summary>
        /// Symbol for the spread information
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Current bid price
        /// </summary>
        public double Bid { get; set; }

        /// <summary>
        /// Current ask price
        /// </summary>
        public double Ask { get; set; }

        /// <summary>
        /// Calculated spread value (ask - bid)
        /// </summary>
        public double Spread { get; set; }

        /// <summary>
        /// Spread as percentage of midpoint
        /// </summary>
        public double SpreadPercentage { get; set; }

        /// <summary>
        /// Timestamp of the spread measurement
        /// </summary>
        public DateTime Timestamp { get; set; }

        /// <summary>
        /// Constructor for SpreadInfo
        /// </summary>
        /// <param name="symbol">Symbol for the spread</param>
        /// <param name="bid">Bid price</param>
        /// <param name="ask">Ask price</param>
        /// <param name="timestamp">Timestamp of measurement</param>
        public SpreadInfo(string symbol, double bid, double ask, DateTime timestamp)
        {
            if (string.IsNullOrEmpty(symbol))
                throw new ArgumentNullException("symbol");

            Symbol = symbol;
            Bid = bid;
            Ask = ask;
            Spread = ask - bid;
            SpreadPercentage = Spread > 0 && bid > 0 ? (Spread / ((bid + ask) / 2.0)) * 100 : 0;
            Timestamp = timestamp;
        }
    }

    /// <summary>
    /// Metrics representing liquidity conditions for a symbol
    /// </summary>
    public class LiquidityMetrics
    {
        /// <summary>
        /// Symbol for the liquidity metrics
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Current bid-ask spread
        /// </summary>
        public double Spread { get; set; }

        /// <summary>
        /// Average spread over recent period
        /// </summary>
        public double AverageSpread { get; set; }

        /// <summary>
        /// Bid volume at best bid level
        /// </summary>
        public long BidVolume { get; set; }

        /// <summary>
        /// Ask volume at best ask level
        /// </summary>
        public long AskVolume { get; set; }

        /// <summary>
        /// Total depth in the order book
        /// </summary>
        public long TotalDepth { get; set; }

        /// <summary>
        /// Number of orders at each level
        /// </summary>
        public int OrderLevels { get; set; }

        /// <summary>
        /// Timestamp of the metrics
        /// </summary>
        public DateTime Timestamp { get; set; }

        /// <summary>
        /// Constructor for LiquidityMetrics
        /// </summary>
        /// <param name="symbol">Symbol for the metrics</param>
        /// <param name="spread">Current spread</param>
        /// <param name="averageSpread">Average spread</param>
        /// <param name="bidVolume">Bid volume</param>
        /// <param name="askVolume">Ask volume</param>
        /// <param name="totalDepth">Total order book depth</param>
        /// <param name="orderLevels">Number of order levels</param>
        /// <param name="timestamp">Timestamp of metrics</param>
        public LiquidityMetrics(
            string symbol,
            double spread,
            double averageSpread,
            long bidVolume,
            long askVolume,
            long totalDepth,
            int orderLevels,
            DateTime timestamp)
        {
            if (string.IsNullOrEmpty(symbol))
                throw new ArgumentNullException("symbol");

            Symbol = symbol;
            Spread = spread;
            AverageSpread = averageSpread;
            BidVolume = bidVolume;
            AskVolume = askVolume;
            TotalDepth = totalDepth;
            OrderLevels = orderLevels;
            Timestamp = timestamp;
        }
    }

    /// <summary>
    /// Information about the current trading session
    /// </summary>
    public class SessionInfo
    {
        /// <summary>
        /// Symbol for the session information
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Current trading session type
        /// </summary>
        public TradingSession Session { get; set; }

        /// <summary>
        /// Start time of current session
        /// </summary>
        public DateTime SessionStart { get; set; }

        /// <summary>
        /// End time of current session
        /// </summary>
        public DateTime SessionEnd { get; set; }

        /// <summary>
        /// Time remaining in current session
        /// </summary>
        public TimeSpan TimeRemaining { get; set; }

        /// <summary>
        /// Whether this is regular trading hours
        /// </summary>
        public bool IsRegularHours { get; set; }

        /// <summary>
        /// Constructor for SessionInfo
        /// </summary>
        /// <param name="symbol">Symbol for the session</param>
        /// <param name="session">Current session type</param>
        /// <param name="sessionStart">Session start time</param>
        /// <param name="sessionEnd">Session end time</param>
        /// <param name="timeRemaining">Time remaining in session</param>
        /// <param name="isRegularHours">Whether it's regular trading hours</param>
        public SessionInfo(
            string symbol,
            TradingSession session,
            DateTime sessionStart,
            DateTime sessionEnd,
            TimeSpan timeRemaining,
            bool isRegularHours)
        {
            if (string.IsNullOrEmpty(symbol))
                throw new ArgumentNullException("symbol");

            Symbol = symbol;
            Session = session;
            SessionStart = sessionStart;
            SessionEnd = sessionEnd;
            TimeRemaining = timeRemaining;
            IsRegularHours = isRegularHours;
        }
    }

    /// <summary>
    /// Information about contract roll status
    /// </summary>
    public class ContractRollInfo
    {
        /// <summary>
        /// Base symbol (e.g., ES for ESZ24, ESH25)
        /// </summary>
        public string BaseSymbol { get; set; }

        /// <summary>
        /// Current active contract
        /// </summary>
        public string ActiveContract { get; set; }

        /// <summary>
        /// Next contract to roll to
        /// </summary>
        public string NextContract { get; set; }

        /// <summary>
        /// Date of the roll
        /// </summary>
        public DateTime RollDate { get; set; }

        /// <summary>
        /// Days remaining until roll
        /// </summary>
        public int DaysToRoll { get; set; }

        /// <summary>
        /// Whether currently in roll period
        /// </summary>
        public bool IsRollPeriod { get; set; }

        /// <summary>
        /// Constructor for ContractRollInfo
        /// </summary>
        /// <param name="baseSymbol">Base symbol</param>
        /// <param name="activeContract">Current active contract</param>
        /// <param name="nextContract">Next contract to roll to</param>
        /// <param name="rollDate">Roll date</param>
        /// <param name="daysToRoll">Days until roll</param>
        /// <param name="isRollPeriod">Whether in roll period</param>
        public ContractRollInfo(
            string baseSymbol,
            string activeContract,
            string nextContract,
            DateTime rollDate,
            int daysToRoll,
            bool isRollPeriod)
        {
            if (string.IsNullOrEmpty(baseSymbol))
                throw new ArgumentNullException("baseSymbol");

            BaseSymbol = baseSymbol;
            ActiveContract = activeContract;
            NextContract = nextContract;
            RollDate = rollDate;
            DaysToRoll = daysToRoll;
            IsRollPeriod = isRollPeriod;
        }
    }

    /// <summary>
    /// Enum representing liquidity quality score
    /// </summary>
    public enum LiquidityScore
    {
        /// <summary>
        /// Very poor liquidity conditions
        /// </summary>
        Poor = 0,

        /// <summary>
        /// Fair liquidity conditions
        /// </summary>
        Fair = 1,

        /// <summary>
        /// Good liquidity conditions
        /// </summary>
        Good = 2,

        /// <summary>
        /// Excellent liquidity conditions
        /// </summary>
        Excellent = 3
    }

    /// <summary>
    /// Enum representing different trading sessions
    /// </summary>
    public enum TradingSession
    {
        /// <summary>
        /// Pre-market session
        /// </summary>
        PreMarket = 0,

        /// <summary>
        /// Regular trading hours
        /// </summary>
        RTH = 1,

        /// <summary>
        /// Extended trading hours
        /// </summary>
        ETH = 2,

        /// <summary>
        /// Market closed
        /// </summary>
        Closed = 3
    }
}
