using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.Extensions;
using EonaCat.Logger.Managers;
using Microsoft.Extensions.Logging;
using System;

namespace EonaCat.Logger.EonaCatCoreLogger.Internal
{
    public sealed class BatchingLogger : ILogger
    {
        private readonly string _category;
        private readonly BatchingLoggerProvider _provider;
        private readonly LoggerSettings _settings;

        public BatchingLogger(
            BatchingLoggerProvider provider,
            string category,
            LoggerSettings settings)
        {
            _provider = provider ?? throw new ArgumentNullException(nameof(provider));
            _category = category ?? throw new ArgumentNullException(nameof(category));
            _settings = settings ?? throw new ArgumentNullException(nameof(settings));
        }

        private DateTimeOffset Now =>
            _settings.UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;

        public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;

        public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;

        public void Log<TState>(
            LogLevel logLevel,
            EventId eventId,
            TState state,
            Exception exception,
            Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            string rawMessage = exception != null
                ? exception.FormatExceptionToMessage()
                : formatter?.Invoke(state, null);

            if (string.IsNullOrEmpty(rawMessage))
            {
                return;
            }

            try
            {
                var timestamp = Now;

                string formatted = LogHelper.FormatMessageWithHeader(
                    _settings,
                    logLevel.FromLogLevel(),
                    rawMessage,
                    timestamp.DateTime,
                    _category);

                var writtenMessage = _provider.AddMessage(timestamp, formatted, _category);

                _settings.RaiseOnLog(new EonaCatLogMessage
                {
                    DateTime = timestamp.DateTime,
                    Message = writtenMessage,
                    LogType = logLevel.FromLogLevel(),
                    Category = _category,
                    Exception = exception,
                    Origin = string.IsNullOrWhiteSpace(_settings.LogOrigin)
                        ? "BatchingLogger"
                        : _settings.LogOrigin
                });

                
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Logging error: {ex.Message}");
            }
        }

        private sealed class NullScope : IDisposable
        {
            public static readonly NullScope Instance = new();
            public void Dispose() { }
        }
    }
}
