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

namespace EonaCat.Logger.EonaCatCoreLogger.Internal
{
    // This file is part of the EonaCat project(s) which is released under the Apache License.
    // See the LICENSE file or go to https://EonaCat.com/License for full license details.

    public class BatchingLogger : ILogger
    {
        private readonly string _category;
        private readonly BatchingLoggerProvider _provider;
        private readonly LoggerSettings _loggerSettings;

        public BatchingLogger(BatchingLoggerProvider loggerProvider, string categoryName, LoggerSettings loggerSettings)
        {
            _provider = loggerProvider ?? throw new ArgumentNullException(nameof(loggerProvider));
            _category = categoryName ?? throw new ArgumentNullException(nameof(categoryName));
            _loggerSettings = loggerSettings ?? throw new ArgumentNullException(nameof(loggerSettings));
        }

        private DateTimeOffset CurrentDateTimeOffset => CurrentDateTime;

        private DateTime CurrentDateTime => _loggerSettings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;

        public IDisposable BeginScope<TState>(TState state) => null;

        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;
            }

            var timestamp = CurrentDateTimeOffset;
            Log(timestamp, logLevel, eventId, state, exception, formatter, _category);
        }

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

            string message = exception != null
                ? exception.FormatExceptionToMessage() + Environment.NewLine
                : formatter(state, exception);

            message = LogHelper.FormatMessageWithHeader(_loggerSettings, logLevel.FromLogLevel(), message, timestamp.DateTime, category)
                      + Environment.NewLine;

            var currentMessage = new EonaCatLogMessage
            {
                DateTime = timestamp.DateTime,
                Message = _provider.AddMessage(timestamp, message),
                LogType = logLevel.FromLogLevel(),
                Origin = string.IsNullOrWhiteSpace(_loggerSettings.LogOrigin) ? "BatchingLogger" : _loggerSettings.LogOrigin
            };

            _loggerSettings.OnLogEvent(currentMessage);
        }
    }
}