using System;
using Microsoft.Extensions.Logging;

namespace NT8.Core.OMS
{
    /// <summary>
    /// Validates order type parameters and ensures price relationships are correct
    /// </summary>
    public class OrderTypeValidator
    {
        private readonly ILogger _logger;

        /// <summary>
        /// Constructor for OrderTypeValidator
        /// </summary>
        /// <param name="logger">Logger instance</param>
        public OrderTypeValidator(ILogger<OrderTypeValidator> logger)
        {
            if (logger == null)
                throw new ArgumentNullException("logger");

            _logger = logger;
        }

        /// <summary>
        /// Validates a limit order request
        /// </summary>
        /// <param name="request">Limit order request to validate</param>
        /// <param name="marketPrice">Current market price</param>
        /// <returns>Validation result indicating success or failure</returns>
        public ValidationResult ValidateLimitOrder(LimitOrderRequest request, decimal marketPrice)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            try
            {
                // Check basic parameters
                if (request.Quantity <= 0)
                {
                    return new ValidationResult(false, "Quantity must be positive", request.ClientOrderId);
                }

                if (request.LimitPrice <= 0)
                {
                    return new ValidationResult(false, "Limit price must be positive", request.ClientOrderId);
                }

                // Validate price relationship based on order side
                if (request.Side == OrderSide.Buy && request.LimitPrice > marketPrice)
                {
                    // Buy limit orders should be below market price
                    _logger.LogDebug("Buy limit order price {LimitPrice} is above market price {MarketPrice}",
                        request.LimitPrice, marketPrice);
                }
                else if (request.Side == OrderSide.Sell && request.LimitPrice < marketPrice)
                {
                    // Sell limit orders should be above market price
                    _logger.LogDebug("Sell limit order price {LimitPrice} is below market price {MarketPrice}",
                        request.LimitPrice, marketPrice);
                }

                // All validations passed
                _logger.LogDebug("Limit order validation passed for {ClientOrderId}", request.ClientOrderId);
                return new ValidationResult(true, "Limit order is valid", request.ClientOrderId);
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to validate limit order {ClientOrderId}: {Message}",
                    request.ClientOrderId, ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Validates a stop order request
        /// </summary>
        /// <param name="request">Stop order request to validate</param>
        /// <param name="marketPrice">Current market price</param>
        /// <returns>Validation result indicating success or failure</returns>
        public ValidationResult ValidateStopOrder(StopOrderRequest request, decimal marketPrice)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            try
            {
                // Check basic parameters
                if (request.Quantity <= 0)
                {
                    return new ValidationResult(false, "Quantity must be positive", request.ClientOrderId);
                }

                if (request.StopPrice <= 0)
                {
                    return new ValidationResult(false, "Stop price must be positive", request.ClientOrderId);
                }

                // Validate price relationship based on order side
                if (request.Side == OrderSide.Buy && request.StopPrice <= marketPrice)
                {
                    // Buy stop orders should be above market price
                    return new ValidationResult(false,
                        String.Format("Buy stop order price {0} must be above market price {1}",
                            request.StopPrice, marketPrice), request.ClientOrderId);
                }
                else if (request.Side == OrderSide.Sell && request.StopPrice >= marketPrice)
                {
                    // Sell stop orders should be below market price
                    return new ValidationResult(false,
                        String.Format("Sell stop order price {0} must be below market price {1}",
                            request.StopPrice, marketPrice), request.ClientOrderId);
                }

                // All validations passed
                _logger.LogDebug("Stop order validation passed for {ClientOrderId}", request.ClientOrderId);
                return new ValidationResult(true, "Stop order is valid", request.ClientOrderId);
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to validate stop order {ClientOrderId}: {Message}",
                    request.ClientOrderId, ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Validates a stop-limit order request
        /// </summary>
        /// <param name="request">Stop-limit order request to validate</param>
        /// <param name="marketPrice">Current market price</param>
        /// <returns>Validation result indicating success or failure</returns>
        public ValidationResult ValidateStopLimitOrder(StopLimitOrderRequest request, decimal marketPrice)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            try
            {
                // Check basic parameters
                if (request.Quantity <= 0)
                {
                    return new ValidationResult(false, "Quantity must be positive", request.ClientOrderId);
                }

                if (request.StopPrice <= 0)
                {
                    return new ValidationResult(false, "Stop price must be positive", request.ClientOrderId);
                }

                if (request.LimitPrice <= 0)
                {
                    return new ValidationResult(false, "Limit price must be positive", request.ClientOrderId);
                }

                // Validate price relationship based on order side
                if (request.Side == OrderSide.Buy)
                {
                    // For buy stop-limit, stop price should be above market and limit price should be >= stop price
                    if (request.StopPrice <= marketPrice)
                    {
                        return new ValidationResult(false,
                            String.Format("Buy stop-limit stop price {0} must be above market price {1}",
                                request.StopPrice, marketPrice), request.ClientOrderId);
                    }

                    if (request.LimitPrice < request.StopPrice)
                    {
                        return new ValidationResult(false,
                            String.Format("Buy stop-limit limit price {0} must be >= stop price {1}",
                                request.LimitPrice, request.StopPrice), request.ClientOrderId);
                    }
                }
                else if (request.Side == OrderSide.Sell)
                {
                    // For sell stop-limit, stop price should be below market and limit price should be <= stop price
                    if (request.StopPrice >= marketPrice)
                    {
                        return new ValidationResult(false,
                            String.Format("Sell stop-limit stop price {0} must be below market price {1}",
                                request.StopPrice, marketPrice), request.ClientOrderId);
                    }

                    if (request.LimitPrice > request.StopPrice)
                    {
                        return new ValidationResult(false,
                            String.Format("Sell stop-limit limit price {0} must be <= stop price {1}",
                                request.LimitPrice, request.StopPrice), request.ClientOrderId);
                    }
                }

                // All validations passed
                _logger.LogDebug("Stop-limit order validation passed for {ClientOrderId}", request.ClientOrderId);
                return new ValidationResult(true, "Stop-limit order is valid", request.ClientOrderId);
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to validate stop-limit order {ClientOrderId}: {Message}",
                    request.ClientOrderId, ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Validates a market-if-touched order request
        /// </summary>
        /// <param name="request">MIT order request to validate</param>
        /// <param name="marketPrice">Current market price</param>
        /// <returns>Validation result indicating success or failure</returns>
        public ValidationResult ValidateMITOrder(MITOrderRequest request, decimal marketPrice)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            try
            {
                // Check basic parameters
                if (request.Quantity <= 0)
                {
                    return new ValidationResult(false, "Quantity must be positive", request.ClientOrderId);
                }

                if (request.TriggerPrice <= 0)
                {
                    return new ValidationResult(false, "Trigger price must be positive", request.ClientOrderId);
                }

                // Validate price relationship based on order side
                if (request.Side == OrderSide.Buy && request.TriggerPrice >= marketPrice)
                {
                    // Buy MIT orders should be below market price (to be triggered when price falls)
                    return new ValidationResult(false,
                        String.Format("Buy MIT trigger price {0} must be below market price {1}",
                            request.TriggerPrice, marketPrice), request.ClientOrderId);
                }
                else if (request.Side == OrderSide.Sell && request.TriggerPrice <= marketPrice)
                {
                    // Sell MIT orders should be above market price (to be triggered when price rises)
                    return new ValidationResult(false,
                        String.Format("Sell MIT trigger price {0} must be above market price {1}",
                            request.TriggerPrice, marketPrice), request.ClientOrderId);
                }

                // All validations passed
                _logger.LogDebug("MIT order validation passed for {ClientOrderId}", request.ClientOrderId);
                return new ValidationResult(true, "MIT order is valid", request.ClientOrderId);
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to validate MIT order {ClientOrderId}: {Message}",
                    request.ClientOrderId, ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Validates an order request regardless of type
        /// </summary>
        /// <param name="request">Order request to validate</param>
        /// <param name="marketPrice">Current market price</param>
        /// <returns>Validation result indicating success or failure</returns>
        public ValidationResult ValidateOrder(OrderRequest request, decimal marketPrice)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            try
            {
                // Validate common parameters first
                if (string.IsNullOrEmpty(request.Symbol))
                {
                    return new ValidationResult(false, "Symbol is required", request.ClientOrderId);
                }

                if (request.Quantity <= 0)
                {
                    return new ValidationResult(false, "Quantity must be positive", request.ClientOrderId);
                }

                // Validate based on order type
                switch (request.Type)
                {
                    case OrderType.Limit:
                        var limitRequest = request as LimitOrderRequest;
                        if (limitRequest != null)
                        {
                            return ValidateLimitOrder(limitRequest, marketPrice);
                        }
                        else
                        {
                            return new ValidationResult(false, "Invalid order type for limit order validation", request.ClientOrderId);
                        }

                    case OrderType.StopMarket:
                        var stopRequest = request as StopOrderRequest;
                        if (stopRequest != null)
                        {
                            return ValidateStopOrder(stopRequest, marketPrice);
                        }
                        else
                        {
                            return new ValidationResult(false, "Invalid order type for stop order validation", request.ClientOrderId);
                        }

                    case OrderType.StopLimit:
                        var stopLimitRequest = request as StopLimitOrderRequest;
                        if (stopLimitRequest != null)
                        {
                            return ValidateStopLimitOrder(stopLimitRequest, marketPrice);
                        }
                        else
                        {
                            return new ValidationResult(false, "Invalid order type for stop-limit order validation", request.ClientOrderId);
                        }

                    case OrderType.Market:
                        // For MIT orders
                        var mitRequest = request as MITOrderRequest;
                        if (mitRequest != null)
                        {
                            return ValidateMITOrder(mitRequest, marketPrice);
                        }
                        else
                        {
                            // Regular market orders don't need complex validation
                            return new ValidationResult(true, "Market order is valid", request.ClientOrderId);
                        }

                    default:
                        return new ValidationResult(false,
                            String.Format("Unsupported order type: {0}", request.Type), request.ClientOrderId);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to validate order {ClientOrderId}: {Message}",
                    request.ClientOrderId, ex.Message);
                throw;
            }
        }
    }

    /// <summary>
    /// Result of order validation
    /// </summary>
    public class ValidationResult
    {
        /// <summary>
        /// Whether the validation passed
        /// </summary>
        public bool IsValid { get; set; }

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

        /// <summary>
        /// Client order ID associated with this validation
        /// </summary>
        public string ClientOrderId { get; set; }

        /// <summary>
        /// Constructor for ValidationResult
        /// </summary>
        /// <param name="isValid">Whether validation passed</param>
        /// <param name="message">Validation message</param>
        /// <param name="clientOrderId">Associated client order ID</param>
        public ValidationResult(bool isValid, string message, string clientOrderId)
        {
            IsValid = isValid;
            Message = message;
            ClientOrderId = clientOrderId;
        }
    }
}
