using System;

namespace NT8.Core.Common.Models
{
    /// <summary>
    /// Represents a financial instrument (e.g., a futures contract, stock).
    /// </summary>
    public class Instrument
    {
        /// <summary>
        /// Unique symbol for the instrument (e.g., "ES", "AAPL").
        /// </summary>
        public string Symbol { get; private set; }

        /// <summary>
        /// Exchange where the instrument is traded (e.g., "CME", "NASDAQ").
        /// </summary>
        public string Exchange { get; private set; }

        /// <summary>
        /// Minimum price increment for the instrument (e.g., 0.25 for ES futures).
        /// </summary>
        public double TickSize { get; private set; }

        /// <summary>
        /// Value of one tick in currency (e.g., $12.50 for ES futures).
        /// </summary>
        public double TickValue { get; private set; }

        /// <summary>
        /// Contract size multiplier (e.g., 50.0 for ES futures, 1.0 for stocks).
        /// This is the value of one point movement in the instrument.
        /// </summary>
        public double ContractMultiplier { get; private set; }

        /// <summary>
        /// The currency in which the instrument is denominated (e.g., "USD").
        /// </summary>
        public string Currency { get; private set; }

        /// <summary>
        /// Initializes a new instance of the Instrument class.
        /// </summary>
        /// <param name="symbol">Unique symbol.</param>
        /// <param name="exchange">Exchange.</param>
        /// <param name="tickSize">Minimum price increment.</param>
        /// <param name="tickValue">Value of one tick.</param>
        /// <param name="contractMultiplier">Contract size multiplier.</param>
        /// <param name="currency">Denomination currency.</param>
        public Instrument(
            string symbol,
            string exchange,
            double tickSize,
            double tickValue,
            double contractMultiplier,
            string currency)
        {
            if (string.IsNullOrEmpty(symbol))
                throw new ArgumentNullException("symbol");
            if (string.IsNullOrEmpty(exchange))
                throw new ArgumentNullException("exchange");
            if (tickSize <= 0)
                throw new ArgumentOutOfRangeException("tickSize", "Tick size must be positive.");
            if (tickValue <= 0)
                throw new ArgumentOutOfRangeException("tickValue", "Tick value must be positive.");
            if (contractMultiplier <= 0)
                throw new ArgumentOutOfRangeException("contractMultiplier", "Contract multiplier must be positive.");
            if (string.IsNullOrEmpty(currency))
                throw new ArgumentNullException("currency");

            Symbol = symbol;
            Exchange = exchange;
            TickSize = tickSize;
            TickValue = tickValue;
            ContractMultiplier = contractMultiplier;
            Currency = currency;
        }

        /// <summary>
        /// Creates a default, invalid instrument.
        /// </summary>
        /// <returns>An invalid Instrument instance.</returns>
        public static Instrument CreateInvalid()
        {
            return new Instrument(
                symbol: "INVALID",
                exchange: "N/A",
                tickSize: 0.01,
                tickValue: 0.01,
                contractMultiplier: 1.0,
                currency: "USD");
        }

        /// <summary>
        /// Provides a string representation of the instrument.
        /// </summary>
        /// <returns>A string with symbol and exchange.</returns>
        public override string ToString()
        {
            return String.Format("{0} ({1})", Symbol, Exchange);
        }
    }
}
