using System;

using AIRuntime.Runtime.Providers.Fallback;


namespace AIRuntime.Runtime.Providers.Health
{
    /// <summary>
    /// Stores runtime health information for one provider.
    /// </summary>
    public sealed class ProviderHealthRecord
    {
        internal ProviderHealthRecord(
            IProvider provider)
        {
            Provider =
                provider ??
                throw new ArgumentNullException(
                    nameof(provider));


            ProviderName =
                provider.Name ??
                string.Empty;


            State =
                ProviderHealthState.Healthy;
        }


        public IProvider Provider
        {
            get;
        }


        public string ProviderName
        {
            get;
        }


        public ProviderHealthState State
        {
            get;
            internal set;
        }


        public int TotalAttempts
        {
            get;
            internal set;
        }


        public int TotalSuccesses
        {
            get;
            internal set;
        }


        public int TotalFailures
        {
            get;
            internal set;
        }


        public int ConsecutiveFailures
        {
            get;
            internal set;
        }


        public ProviderFailureKind LastFailureKind
        {
            get;
            internal set;
        }


        public string LastFailureMessage
        {
            get;
            internal set;
        }


        public DateTimeOffset? LastAttemptAt
        {
            get;
            internal set;
        }


        public DateTimeOffset? LastSuccessAt
        {
            get;
            internal set;
        }


        public DateTimeOffset? LastFailureAt
        {
            get;
            internal set;
        }


        public DateTimeOffset? CooldownUntil
        {
            get;
            internal set;
        }


        public TimeSpan LastLatency
        {
            get;
            internal set;
        }


        public bool IsCoolingDown(
            DateTimeOffset now)
        {
            return
                CooldownUntil.HasValue &&
                CooldownUntil.Value > now;
        }


        internal ProviderHealthRecord CreateSnapshot()
        {
            return new ProviderHealthRecord(
                Provider)
            {
                State =
                    State,

                TotalAttempts =
                    TotalAttempts,

                TotalSuccesses =
                    TotalSuccesses,

                TotalFailures =
                    TotalFailures,

                ConsecutiveFailures =
                    ConsecutiveFailures,

                LastFailureKind =
                    LastFailureKind,

                LastFailureMessage =
                    LastFailureMessage,

                LastAttemptAt =
                    LastAttemptAt,

                LastSuccessAt =
                    LastSuccessAt,

                LastFailureAt =
                    LastFailureAt,

                CooldownUntil =
                    CooldownUntil,

                LastLatency =
                    LastLatency
            };
        }
    }
}