#nullable enable
using System;
using System.Threading;
using UnityEngine;

namespace IGP.UnitySDK
{
    /// <summary>
    /// Shared SDK logging entry point. Use scope and path to identify the calling module.
    /// </summary>
    public static class IGPLog
    {
        private static int configuredLevel = (int)IGPLogLevel.Off;

        public static string RunId { get; } = Guid.NewGuid().ToString("N");

        internal static void Configure(IGPLogLevel level)
        {
            Volatile.Write(ref configuredLevel, (int)level);
        }

        public static void Debug(string scope, string path, string message)
        {
            if (!ShouldLog(IGPLogLevel.Debug))
            {
                return;
            }

            Write(IGPLogLevel.Debug, scope, path, message);
        }

        public static void Info(string scope, string path, string message)
        {
            if (!ShouldLog(IGPLogLevel.Info))
            {
                return;
            }

            Write(IGPLogLevel.Info, scope, path, message);
        }

        public static void Warning(string scope, string path, string message)
        {
            if (!ShouldLog(IGPLogLevel.Warning))
            {
                return;
            }

            Write(IGPLogLevel.Warning, scope, path, message);
        }

        public static void Error(string scope, string path, string message)
        {
            if (!ShouldLog(IGPLogLevel.Error))
            {
                return;
            }

            Write(IGPLogLevel.Error, scope, path, message);
        }

        /// <summary>
        /// Returns whether a message should be logged. Call this before building expensive log details.
        /// </summary>
        public static bool ShouldLog(IGPLogLevel messageLevel)
        {
            var level = (IGPLogLevel)Volatile.Read(ref configuredLevel);
            return level != IGPLogLevel.Off &&
                   messageLevel != IGPLogLevel.Off &&
                   (int)messageLevel <= (int)level;
        }

        public static string FormatValue(string? value)
        {
            return string.IsNullOrWhiteSpace(value) ? "-" : value!;
        }

        private static void Write(IGPLogLevel level, string scope, string path, string message)
        {
            string formatted =
                $"[IGP SDK] timestamp={DateTimeOffset.Now:O} runId={RunId} level={level} scope={FormatValue(scope)} path={FormatValue(path)} {message}";

            switch (level)
            {
                case IGPLogLevel.Error:
                    UnityEngine.Debug.LogError(formatted);
                    break;
                case IGPLogLevel.Warning:
                    UnityEngine.Debug.LogWarning(formatted);
                    break;
                default:
                    UnityEngine.Debug.Log(formatted);
                    break;
            }
        }
    }
}
