using EonaCat.Logger.Managers;
using System.IO.Compression;
using EonaCat.Logger.Extensions;

namespace EonaCat.Logger.Test.Web
{
    public static class Logger
    {
        public static ELogType MaxLogType { get; set; }
        public static bool UseLocalTime { get; set; }
        private static LogManager LogManager;
        public static string LogFolder => "Logs";
        public static string CurrentLogFile => LogManager.CurrentLogFile;
        public static bool IsDisabled { get; set; }

        public static void DeleteCurrentLogFile()
        {
            if (IsDisabled)
                return;

            LogManager.DeleteCurrentLogFile();
        }

        private static string ConvertToAbsolutePath(string path)
        {
            return Path.IsPathRooted(path) ? path : Path.Combine(LogFolder, path);
        }

        public static async Task DownloadLogAsync(HttpContext context, string logName, long limit)
        {
            var logFileName = logName + ".log";

            await using var fS = new FileStream(Path.Combine(ConvertToAbsolutePath(LogFolder), logFileName), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 64 * 1024, true);
            var response = context.Response;

            response.ContentType = "text/plain";
            response.Headers.ContentDisposition = "attachment;filename=" + logFileName;

            if ((limit > fS.Length) || (limit < 1))
                limit = fS.Length;

            var oFS = new OffsetStream(fS, 0, limit);
            var request = context.Request;
            Stream s;

            string acceptEncoding = request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(acceptEncoding))
            {
                s = response.Body;
            }
            else
            {
                string[] acceptEncodingParts = acceptEncoding.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);

                if (acceptEncodingParts.Contains("br"))
                {
                    response.Headers.ContentEncoding = "br";
                    s = new BrotliStream(response.Body, CompressionMode.Compress);
                }
                else if (acceptEncodingParts.Contains("gzip"))
                {
                    response.Headers.ContentEncoding = "gzip";
                    s = new GZipStream(response.Body, CompressionMode.Compress);
                }
                else if (acceptEncodingParts.Contains("deflate"))
                {
                    response.Headers.ContentEncoding = "deflate";
                    s = new DeflateStream(response.Body, CompressionMode.Compress);
                }
                else
                {
                    s = response.Body;
                }
            }

            await using (s)
            {
                await oFS.CopyToAsync(s).ConfigureAwait(false);

                if (fS.Length > limit)
                    await s.WriteAsync("\r\n####__EONACATLOGGER_TRUNCATED___####"u8.ToArray()).ConfigureAwait(false);
            }
        }




        public static void Log(string message, ELogType logType = ELogType.INFO, bool writeToConsole = true)
        {
            if (IsDisabled)
                return;

            LogManager.Write(message, logType, writeToConsole);
        }

        public static void Log(Exception exception, string message = "", bool writeToConsole = true)
        {
            if (IsDisabled)
                return;

            LogManager.Write(exception, module: message, writeToConsole: writeToConsole);
        }

        public static void Configure()
        {
            var loggerSettings = new LoggerSettings
            {
                Id = "EonaCatDnsLogger",
                MaxLogType = ELogType.TRACE,
                UseLocalTime = UseLocalTime,
                FileLoggerOptions =
                {
                    LogDirectory = "Logs",
                    FileSizeLimit = 20_000_000, // 20 MB,
                    UseLocalTime = UseLocalTime,
                }
            };
            LogManager = new LogManager(loggerSettings);
        }
    }
}
