using NT8.Core.Common.Models;
using System;
using System.Collections.Generic;

namespace NT8.Core.Orders
{
    #region Core Order Models

    /// <summary>
    /// Order request parameters
    /// </summary>
    public class OrderRequest
    {
        /// <summary>
        /// Trading symbol
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Order type
        /// </summary>
        public OrderType Type { get; set; }

        /// <summary>
        /// Order quantity
        /// </summary>
        public int Quantity { get; set; }

        /// <summary>
        /// Limit price (if applicable)
        /// </summary>
        public decimal? LimitPrice { get; set; }

        /// <summary>
        /// Stop price (if applicable)
        /// </summary>
        public decimal? StopPrice { get; set; }

        /// <summary>
        /// Time in force
        /// </summary>
        public TimeInForce TimeInForce { get; set; }

        /// <summary>
        /// Algorithm to use (TWAP, VWAP, Iceberg, or null for regular order)
        /// </summary>
        public string Algorithm { get; set; }

        /// <summary>
        /// Algorithm-specific parameters
        /// </summary>
        public Dictionary<string, object> AlgorithmParameters { get; set; }

        /// <summary>
        /// Constructor for OrderRequest
        /// </summary>
        public OrderRequest(
            string symbol,
            OrderSide side,
            OrderType type,
            int quantity,
            decimal? limitPrice,
            decimal? stopPrice,
            TimeInForce timeInForce,
            string algorithm,
            Dictionary<string, object> algorithmParameters)
        {
            Symbol = symbol;
            Side = side;
            Type = type;
            Quantity = quantity;
            LimitPrice = limitPrice;
            StopPrice = stopPrice;
            TimeInForce = timeInForce;
            Algorithm = algorithm;
            AlgorithmParameters = algorithmParameters ?? new Dictionary<string, object>();
        }
    }

    /// <summary>
    /// Order submission result
    /// </summary>
    public class OrderResult
    {
        /// <summary>
        /// Whether the order submission was successful
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// Order ID if successful
        /// </summary>
        public string OrderId { get; set; }

        /// <summary>
        /// Message describing the result
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// Order status if successful
        /// </summary>
        public OrderStatus Status { get; set; }

        /// <summary>
        /// Constructor for OrderResult
        /// </summary>
        public OrderResult(
            bool success,
            string orderId,
            string message,
            OrderStatus status)
        {
            Success = success;
            OrderId = orderId;
            Message = message;
            Status = status;
        }
    }

    /// <summary>
    /// Current order status
    /// </summary>
    public class OrderStatus
    {
        /// <summary>
        /// Order ID
        /// </summary>
        public string OrderId { get; set; }

        /// <summary>
        /// Trading symbol
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Order type
        /// </summary>
        public OrderType Type { get; set; }

        /// <summary>
        /// Order quantity
        /// </summary>
        public int Quantity { get; set; }

        /// <summary>
        /// Filled quantity
        /// </summary>
        public int FilledQuantity { get; set; }

        /// <summary>
        /// Limit price (if applicable)
        /// </summary>
        public decimal? LimitPrice { get; set; }

        /// <summary>
        /// Stop price (if applicable)
        /// </summary>
        public decimal? StopPrice { get; set; }

        /// <summary>
        /// Current order state
        /// </summary>
        public OrderState State { get; set; }

        /// <summary>
        /// Order creation time
        /// </summary>
        public DateTime CreatedTime { get; set; }

        /// <summary>
        /// Order fill time (if filled)
        /// </summary>
        public DateTime? FilledTime { get; set; }

        /// <summary>
        /// Order fills
        /// </summary>
        public List<OrderFill> Fills { get; set; }

        /// <summary>
        /// Constructor for OrderStatus
        /// </summary>
        public OrderStatus(
            string orderId,
            string symbol,
            OrderSide side,
            OrderType type,
            int quantity,
            int filledQuantity,
            decimal? limitPrice,
            decimal? stopPrice,
            OrderState state,
            DateTime createdTime,
            DateTime? filledTime,
            List<OrderFill> fills)
        {
            OrderId = orderId;
            Symbol = symbol;
            Side = side;
            Type = type;
            Quantity = quantity;
            FilledQuantity = filledQuantity;
            LimitPrice = limitPrice;
            StopPrice = stopPrice;
            State = state;
            CreatedTime = createdTime;
            FilledTime = filledTime;
            Fills = fills ?? new List<OrderFill>();
        }
    }

    /// <summary>
    /// Order modification parameters
    /// </summary>
    public class OrderModification
    {
        /// <summary>
        /// New quantity (if changing)
        /// </summary>
        public int? NewQuantity { get; set; }

        /// <summary>
        /// New limit price (if changing)
        /// </summary>
        public decimal? NewLimitPrice { get; set; }

        /// <summary>
        /// New stop price (if changing)
        /// </summary>
        public decimal? NewStopPrice { get; set; }

        /// <summary>
        /// New time in force (if changing)
        /// </summary>
        public TimeInForce? NewTimeInForce { get; set; }

        /// <summary>
        /// Constructor for OrderModification
        /// </summary>
        public OrderModification(
            int? newQuantity,
            decimal? newLimitPrice,
            decimal? newStopPrice,
            TimeInForce? newTimeInForce)
        {
            NewQuantity = newQuantity;
            NewLimitPrice = newLimitPrice;
            NewStopPrice = newStopPrice;
            NewTimeInForce = newTimeInForce;
        }
    }

    #endregion

    #region Algorithm Parameters

    /// <summary>
    /// TWAP algorithm parameters
    /// </summary>
    public class TwapParameters
    {
        /// <summary>
        /// Trading symbol
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Total quantity to trade
        /// </summary>
        public int TotalQuantity { get; set; }

        /// <summary>
        /// Total duration for execution
        /// </summary>
        public TimeSpan Duration { get; set; }

        /// <summary>
        /// Interval between order slices in seconds
        /// </summary>
        public int IntervalSeconds { get; set; }

        /// <summary>
        /// Limit price (if applicable)
        /// </summary>
        public decimal? LimitPrice { get; set; }

        /// <summary>
        /// Constructor for TwapParameters
        /// </summary>
        public TwapParameters(
            string symbol,
            OrderSide side,
            int totalQuantity,
            TimeSpan duration,
            int intervalSeconds,
            decimal? limitPrice)
        {
            Symbol = symbol;
            Side = side;
            TotalQuantity = totalQuantity;
            Duration = duration;
            IntervalSeconds = intervalSeconds;
            LimitPrice = limitPrice;
        }
    }

    /// <summary>
    /// VWAP algorithm parameters
    /// </summary>
    public class VwapParameters
    {
        /// <summary>
        /// Trading symbol
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Total quantity to trade
        /// </summary>
        public int TotalQuantity { get; set; }

        /// <summary>
        /// Start time for execution
        /// </summary>
        public DateTime StartTime { get; set; }

        /// <summary>
        /// End time for execution
        /// </summary>
        public DateTime EndTime { get; set; }

        /// <summary>
        /// Limit price (if applicable)
        /// </summary>
        public decimal? LimitPrice { get; set; }

        /// <summary>
        /// Participation rate (0.0 to 1.0)
        /// </summary>
        public double ParticipationRate { get; set; }

        /// <summary>
        /// Constructor for VwapParameters
        /// </summary>
        public VwapParameters(
            string symbol,
            OrderSide side,
            int totalQuantity,
            DateTime startTime,
            DateTime endTime,
            decimal? limitPrice,
            double participationRate)
        {
            Symbol = symbol;
            Side = side;
            TotalQuantity = totalQuantity;
            StartTime = startTime;
            EndTime = endTime;
            LimitPrice = limitPrice;
            ParticipationRate = participationRate;
        }
    }

    /// <summary>
    /// Iceberg algorithm parameters
    /// </summary>
    public class IcebergParameters
    {
        /// <summary>
        /// Trading symbol
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Total quantity to trade
        /// </summary>
        public int TotalQuantity { get; set; }

        /// <summary>
        /// Visible quantity for each slice
        /// </summary>
        public int VisibleQuantity { get; set; }

        /// <summary>
        /// Limit price (if applicable)
        /// </summary>
        public decimal? LimitPrice { get; set; }

        /// <summary>
        /// Constructor for IcebergParameters
        /// </summary>
        public IcebergParameters(
            string symbol,
            OrderSide side,
            int totalQuantity,
            int visibleQuantity,
            decimal? limitPrice)
        {
            Symbol = symbol;
            Side = side;
            TotalQuantity = totalQuantity;
            VisibleQuantity = visibleQuantity;
            LimitPrice = limitPrice;
        }
    }

    #endregion

    #region Routing Models

    /// <summary>
    /// Order routing result
    /// </summary>
    public class RoutingResult
    {
        /// <summary>
        /// Whether routing was successful
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// Order ID
        /// </summary>
        public string OrderId { get; set; }

        /// <summary>
        /// Selected execution venue
        /// </summary>
        public ExecutionVenue SelectedVenue { get; set; }

        /// <summary>
        /// Message describing the result
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// Routing details
        /// </summary>
        public Dictionary<string, object> RoutingDetails { get; set; }

        /// <summary>
        /// Constructor for RoutingResult
        /// </summary>
        public RoutingResult(
            bool success,
            string orderId,
            ExecutionVenue selectedVenue,
            string message,
            Dictionary<string, object> routingDetails)
        {
            Success = success;
            OrderId = orderId;
            SelectedVenue = selectedVenue;
            Message = message;
            RoutingDetails = routingDetails ?? new Dictionary<string, object>();
        }
    }

    /// <summary>
    /// Execution venue information
    /// </summary>
    public class ExecutionVenue
    {
        /// <summary>
        /// Venue name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Venue description
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Whether venue is active
        /// </summary>
        public bool IsActive { get; set; }

        /// <summary>
        /// Relative cost factor (1.0 = baseline)
        /// </summary>
        public double CostFactor { get; set; }

        /// <summary>
        /// Relative speed factor (1.0 = baseline)
        /// </summary>
        public double SpeedFactor { get; set; }

        /// <summary>
        /// Reliability score (0.0 to 1.0)
        /// </summary>
        public double ReliabilityFactor { get; set; }

        /// <summary>
        /// Constructor for ExecutionVenue
        /// </summary>
        public ExecutionVenue(
            string name,
            string description,
            bool isActive,
            double costFactor,
            double speedFactor,
            double reliabilityFactor)
        {
            Name = name;
            Description = description;
            IsActive = isActive;
            CostFactor = costFactor;
            SpeedFactor = speedFactor;
            ReliabilityFactor = reliabilityFactor;
        }
    }

    /// <summary>
    /// Routing performance metrics
    /// </summary>
    public class RoutingMetrics
    {
        /// <summary>
        /// Performance metrics by venue
        /// </summary>
        public Dictionary<string, VenueMetrics> VenuePerformance { get; set; }

        /// <summary>
        /// Total number of routed orders
        /// </summary>
        public int TotalRoutedOrders { get; set; }

        /// <summary>
        /// Average routing time in milliseconds
        /// </summary>
        public double AverageRoutingTimeMs { get; set; }

        /// <summary>
        /// Last update timestamp
        /// </summary>
        public DateTime LastUpdated { get; set; }

        /// <summary>
        /// Constructor for RoutingMetrics
        /// </summary>
        public RoutingMetrics(
            Dictionary<string, VenueMetrics> venuePerformance,
            int totalRoutedOrders,
            double averageRoutingTimeMs,
            DateTime lastUpdated)
        {
            VenuePerformance = venuePerformance ?? new Dictionary<string, VenueMetrics>();
            TotalRoutedOrders = totalRoutedOrders;
            AverageRoutingTimeMs = averageRoutingTimeMs;
            LastUpdated = lastUpdated;
        }
    }

    /// <summary>
    /// Metrics for a specific execution venue
    /// </summary>
    public class VenueMetrics
    {
        /// <summary>
        /// Venue name
        /// </summary>
        public string VenueName { get; set; }

        /// <summary>
        /// Number of orders routed to this venue
        /// </summary>
        public int OrdersRouted { get; set; }

        /// <summary>
        /// Fill rate for this venue
        /// </summary>
        public double FillRate { get; set; }

        /// <summary>
        /// Average slippage for this venue
        /// </summary>
        public double AverageSlippage { get; set; }

        /// <summary>
        /// Average execution time in milliseconds
        /// </summary>
        public double AverageExecutionTimeMs { get; set; }

        /// <summary>
        /// Total value routed through this venue
        /// </summary>
        public decimal TotalValueRouted { get; set; }

        /// <summary>
        /// Constructor for VenueMetrics
        /// </summary>
        public VenueMetrics(
            string venueName,
            int ordersRouted,
            double fillRate,
            double averageSlippage,
            double averageExecutionTimeMs,
            decimal totalValueRouted)
        {
            VenueName = venueName;
            OrdersRouted = ordersRouted;
            FillRate = fillRate;
            AverageSlippage = averageSlippage;
            AverageExecutionTimeMs = averageExecutionTimeMs;
            TotalValueRouted = totalValueRouted;
        }
    }

    /// <summary>
    /// Routing configuration parameters
    /// </summary>
    public class RoutingConfig
    {
        /// <summary>
        /// Whether smart routing is enabled
        /// </summary>
        public bool SmartRoutingEnabled { get; set; }

        /// <summary>
        /// Default venue to use when smart routing is disabled
        /// </summary>
        public string DefaultVenue { get; set; }

        /// <summary>
        /// Venue preferences (venue name -> preference weight)
        /// </summary>
        public Dictionary<string, double> VenuePreferences { get; set; }

        /// <summary>
        /// Maximum allowed slippage percentage
        /// </summary>
        public double MaxSlippagePercent { get; set; }

        /// <summary>
        /// Maximum time allowed for routing
        /// </summary>
        public TimeSpan MaxRoutingTime { get; set; }

        /// <summary>
        /// Whether to route based on cost
        /// </summary>
        public bool RouteByCost { get; set; }

        /// <summary>
        /// Whether to route based on speed
        /// </summary>
        public bool RouteBySpeed { get; set; }

        /// <summary>
        /// Whether to route based on reliability
        /// </summary>
        public bool RouteByReliability { get; set; }

        /// <summary>
        /// Constructor for RoutingConfig
        /// </summary>
        public RoutingConfig(
            bool smartRoutingEnabled,
            string defaultVenue,
            Dictionary<string, double> venuePreferences,
            double maxSlippagePercent,
            TimeSpan maxRoutingTime,
            bool routeByCost,
            bool routeBySpeed,
            bool routeByReliability)
        {
            SmartRoutingEnabled = smartRoutingEnabled;
            DefaultVenue = defaultVenue;
            VenuePreferences = venuePreferences ?? new Dictionary<string, double>();
            MaxSlippagePercent = maxSlippagePercent;
            MaxRoutingTime = maxRoutingTime;
            RouteByCost = routeByCost;
            RouteBySpeed = routeBySpeed;
            RouteByReliability = routeByReliability;
        }
    }

    /// <summary>
    /// Algorithm configuration parameters
    /// </summary>
    public class AlgorithmParameters
    {
        /// <summary>
        /// TWAP settings
        /// </summary>
        public TwapConfig TwapSettings { get; set; }

        /// <summary>
        /// VWAP settings
        /// </summary>
        public VwapConfig VwapSettings { get; set; }

        /// <summary>
        /// Iceberg settings
        /// </summary>
        public IcebergConfig IcebergSettings { get; set; }

        /// <summary>
        /// Constructor for AlgorithmParameters
        /// </summary>
        public AlgorithmParameters(
            TwapConfig twapSettings,
            VwapConfig vwapSettings,
            IcebergConfig icebergSettings)
        {
            TwapSettings = twapSettings;
            VwapSettings = vwapSettings;
            IcebergSettings = icebergSettings;
        }
    }

    /// <summary>
    /// TWAP configuration
    /// </summary>
    public class TwapConfig
    {
        /// <summary>
        /// Default duration for TWAP orders
        /// </summary>
        public TimeSpan DefaultDuration { get; set; }

        /// <summary>
        /// Default interval between slices in seconds
        /// </summary>
        public int DefaultIntervalSeconds { get; set; }

        /// <summary>
        /// Whether TWAP is enabled
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// Constructor for TwapConfig
        /// </summary>
        public TwapConfig(
            TimeSpan defaultDuration,
            int defaultIntervalSeconds,
            bool enabled)
        {
            DefaultDuration = defaultDuration;
            DefaultIntervalSeconds = defaultIntervalSeconds;
            Enabled = enabled;
        }
    }

    /// <summary>
    /// VWAP configuration
    /// </summary>
    public class VwapConfig
    {
        /// <summary>
        /// Default participation rate for VWAP orders
        /// </summary>
        public double DefaultParticipationRate { get; set; }

        /// <summary>
        /// Whether VWAP is enabled
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// Constructor for VwapConfig
        /// </summary>
        public VwapConfig(
            double defaultParticipationRate,
            bool enabled)
        {
            DefaultParticipationRate = defaultParticipationRate;
            Enabled = enabled;
        }
    }

    /// <summary>
    /// Iceberg configuration
    /// </summary>
    public class IcebergConfig
    {
        /// <summary>
        /// Default visible ratio for Iceberg orders
        /// </summary>
        public double DefaultVisibleRatio { get; set; }

        /// <summary>
        /// Whether Iceberg is enabled
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// Constructor for IcebergConfig
        /// </summary>
        public IcebergConfig(
            double defaultVisibleRatio,
            bool enabled)
        {
            DefaultVisibleRatio = defaultVisibleRatio;
            Enabled = enabled;
        }
    }

    #endregion

    #region Metrics Models

    /// <summary>
    /// OMS performance metrics
    /// </summary>
    public class OmsMetrics
    {
        /// <summary>
        /// Total number of orders
        /// </summary>
        public int TotalOrders { get; set; }

        /// <summary>
        /// Number of active orders
        /// </summary>
        public int ActiveOrders { get; set; }

        /// <summary>
        /// Number of failed orders
        /// </summary>
        public int FailedOrders { get; set; }

        /// <summary>
        /// Fill rate (0.0 to 1.0)
        /// </summary>
        public double FillRate { get; set; }

        /// <summary>
        /// Average slippage
        /// </summary>
        public double AverageSlippage { get; set; }

        /// <summary>
        /// Average execution time in milliseconds
        /// </summary>
        public double AverageExecutionTimeMs { get; set; }

        /// <summary>
        /// Total value traded
        /// </summary>
        public decimal TotalValueTraded { get; set; }

        /// <summary>
        /// Last update timestamp
        /// </summary>
        public DateTime LastUpdated { get; set; }

        /// <summary>
        /// Constructor for OmsMetrics
        /// </summary>
        public OmsMetrics(
            int totalOrders,
            int activeOrders,
            int failedOrders,
            double fillRate,
            double averageSlippage,
            double averageExecutionTimeMs,
            decimal totalValueTraded,
            DateTime lastUpdated)
        {
            TotalOrders = totalOrders;
            ActiveOrders = activeOrders;
            FailedOrders = failedOrders;
            FillRate = fillRate;
            AverageSlippage = averageSlippage;
            AverageExecutionTimeMs = averageExecutionTimeMs;
            TotalValueTraded = totalValueTraded;
            LastUpdated = lastUpdated;
        }
    }

    #endregion

    #region Enumerations

    /// <summary>
    /// Order side enumeration
    /// </summary>
    public enum OrderSide
    {
        Buy = 1,
        Sell = -1
    }

    /// <summary>
    /// Order type enumeration
    /// </summary>
    public enum OrderType
    {
        Market,
        Limit,
        StopMarket,
        StopLimit
    }

    /// <summary>
    /// Order state enumeration
    /// </summary>
    public enum OrderState
    {
        New,
        Submitted,
        Accepted,
        PartiallyFilled,
        Filled,
        Cancelled,
        Rejected,
        Expired
    }

    /// <summary>
    /// Time in force enumeration
    /// </summary>
    public enum TimeInForce
    {
        Day,
        Gtc, // Good Till Cancelled
        Ioc, // Immediate Or Cancel
        Fok  // Fill Or Kill
    }

    #endregion
}
