using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;
using System.Threading;
using SLC1_N;

namespace SLC1_N
{
    public class mxlLog  // 日志文件类
    {
        // 日志级别
        public enum LogLevel
        {
            LOG_DEBUG,
            LOG_INFO,
            LOG_WARNING,
            LOG_ERROR,
            LOG_XXX
        };

        // 单例实例
        private static readonly mxlLog instance = new mxlLog();
        public static mxlLog Instance { get { return instance; } }

        private readonly object mutex = new object();
        private string logDir;
        private string logPrefix = "log_";
        private long maxFileSize = 10 * 1024 * 1024; // 10MB
        private int maxBackupFiles = 5; // 允许文件最大备份数
        private LogLevel minLevel = LogLevel.LOG_DEBUG; // 记录级别，大于则生成文件

        // 标志位控制
        public bool IsDebugEnabled { get; set; } = false;
        public bool IsInfoEnabled { get; set; } = false;
        public bool IsWarningEnabled { get; set; } = false;
        public bool IsErrorEnabled { get; set; } = false;
        public bool IsXXXEnabled { get; set; } = false;

        // 构造函数 - 自动初始化到当前目录
        private mxlLog()
        {
            // 自动设置为软件当前目录下的Logs文件夹
            logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
            minLevel = LogLevel.LOG_DEBUG;

            // 确保日志目录存在
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
        }

        // 初始化
        public void Initialize(string dir = null,  // 修改日志目录
                             string prefix = null, // 修改日志文件名前缀
                             long? maxSize = null,  // 限制单个日志文件最大
                             int? maxBackups = null,// 最多保留备份数
                             LogLevel? minLevel = null, // 只写入xxx及以上级别
                             bool? isDebugEnabled = null, bool? isInfoEnabled = null, // 写入使能
                             bool? isWarningEnabled = null, bool? isErrorEnabled = null,
                             bool? isXXXEnabled = null)
        {
            lock (mutex)
            {
                this.logDir = dir ?? this.logDir;
                this.logPrefix = prefix ?? this.logPrefix;
                this.maxFileSize = maxSize ?? this.maxFileSize;
                this.maxBackupFiles = maxBackups ?? this.maxBackupFiles;
                this.minLevel = minLevel ?? this.minLevel;

                // 设置标志位
                IsDebugEnabled = isDebugEnabled ?? IsDebugEnabled;
                IsInfoEnabled = isInfoEnabled ?? IsInfoEnabled;
                IsWarningEnabled = isWarningEnabled ?? IsWarningEnabled;
                IsErrorEnabled = isErrorEnabled ?? IsErrorEnabled;
                IsXXXEnabled = isXXXEnabled ?? IsXXXEnabled;

                if (!Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }
            }
        }

        // 写入日志
        public void Write(LogLevel level, string message, Exception ex = null)
        {
            if (!IsLevelEnabled(level) || level < minLevel) // 检查使能
                return;

            lock (mutex)
            {
                try
                {
                    string logFile = GetCurrentLogFilePath();
                    CheckFileSize(logFile);

                    string logEntry = $"{GetCurrentTimeStamp()} [{GetLevelString(level)}] {message}";

                    if (ex != null)
                    {
                        logEntry += $"\nException: {ex.GetType().Name}\nMessage: {ex.Message}\nStack Trace: {ex.StackTrace}";
                    }

                    File.AppendAllText(logFile, logEntry + Environment.NewLine);
                }
                catch (Exception logEx)
                {
                    HandleLogFailure(logEx);
                }
            }
        }

        // 清理旧日志文件
        public void ClearOldLogs(int keepDays = 30)
        {
            try
            {
                lock (mutex)
                {
                    if (!Directory.Exists(logDir))
                        return;

                    var cutoffDate = DateTime.Now.AddDays(-keepDays); // 截止日期

                    var allLogFiles = Directory.GetFiles(logDir, $"{logPrefix}*.log*"); // 筛选

                    foreach (var file in allLogFiles)
                    {
                        try
                        {
                            // 尝试从文件名中解析日期
                            var fileName = Path.GetFileNameWithoutExtension(file);

                            if (fileName.StartsWith(logPrefix))
                            {
                                var datePart = fileName.Substring(logPrefix.Length); //去掉前缀，获取日期部分

                                // 尝试解析日期 yyyyMMdd
                                if (datePart.Length >= 8 &&  // 日期是否8个字符("20250101") 则存到fileDate
                                    DateTime.TryParseExact(datePart.Substring(0, 8), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out var fileDate))
                                {
                                    if (fileDate < cutoffDate) // 对比日期
                                    {
                                        File.Delete(file);
                                        Write(LogLevel.LOG_INFO, $"删除旧日志文件: {file}");
                                    }
                                }
                                else if (File.Exists(file))  // 对于log.1, .log.2，检查最后修改时间
                                {
                                    var lastWriteTime = File.GetLastWriteTime(file);
                                    if (lastWriteTime < cutoffDate)
                                    {
                                        File.Delete(file);
                                        Write(LogLevel.LOG_INFO, $"删除旧日志备份: {file}");
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Write(LogLevel.LOG_ERROR, $"删除旧日志文件失败: {file}", ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Write(LogLevel.LOG_ERROR, "清除旧日志失败", ex);
            }
        }

        // 快捷方法
        public void Debug(string message) => Write(LogLevel.LOG_DEBUG, message);
        public void Info(string message) => Write(LogLevel.LOG_INFO, message);
        public void Warning(string message, Exception ex = null) => Write(LogLevel.LOG_WARNING, message, ex);
        public void Error(string message, Exception ex = null) => Write(LogLevel.LOG_ERROR, message, ex);
        public void XXX(string message, Exception ex = null) => Write(LogLevel.LOG_XXX, message, ex);
        public void MESDebug(string message) => Write(LogLevel.LOG_DEBUG, $"[MES] {message}");

        #region 私有方法

        // 获取使能
        private bool IsLevelEnabled(LogLevel level) 
        {
            switch (level)
            {
                case LogLevel.LOG_DEBUG: return IsDebugEnabled;
                case LogLevel.LOG_INFO: return IsInfoEnabled;
                case LogLevel.LOG_WARNING: return IsWarningEnabled;
                case LogLevel.LOG_ERROR: return IsErrorEnabled;
                case LogLevel.LOG_XXX: return IsXXXEnabled;
                default: return true;
            }
        }

        // 生成当前日志文件的完整路径
        private string GetCurrentLogFilePath()
        {
            string dateStamp = DateTime.Now.ToString("yyyyMMdd");
            return Path.Combine(logDir, $"{logPrefix}{dateStamp}.log");
        }

        // 超过大小，触发轮转（当前备份，重新新建）
        private void CheckFileSize(string logFile)
        {
            if (!File.Exists(logFile)) return;

            FileInfo fileInfo = new FileInfo(logFile);
            if (fileInfo.Length >= maxFileSize)
            {
                RotateLogFiles(logFile);
            }
        }
        // 实现日志轮转
        private void RotateLogFiles(string currentLogFile)
        {
            for (int i = maxBackupFiles - 1; i >= 1; i--)
            {
                string source = $"{currentLogFile}.{i}";
                string dest = $"{currentLogFile}.{i + 1}";

                if (File.Exists(source))
                {
                    File.Move(source, dest);
                }
            }

            if (File.Exists(currentLogFile))
            {
                File.Move(currentLogFile, $"{currentLogFile}.1");
            }
        }

        private string GetCurrentTimeStamp()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
        }

        private string GetLevelString(LogLevel level)
        {
            switch (level)
            {
                case LogLevel.LOG_DEBUG:   return "DEBUG";
                case LogLevel.LOG_INFO:    return "INFO";
                case LogLevel.LOG_WARNING: return "WARNING";
                case LogLevel.LOG_ERROR:   return "ERROR";
                case LogLevel.LOG_XXX:     return "XXX";
                default: return "UNKNOWN";
            }
        }

        // 主日志系统失败（如磁盘满、权限问题）
        private void HandleLogFailure(Exception ex)
        {
            try
            {
                string fallbackPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                    "LL_log_fallback.txt");

                File.AppendAllText(fallbackPath,
                    $"{GetCurrentTimeStamp()} [LOG_ERROR] Failed to write log: {ex.Message}" +
                    Environment.NewLine);
            }
            catch { /* 最终保底措施 */ }
        }

        #endregion
    }
}

// 使用方法 ： mxlLog.Instance.Error($"异常 ,行号{ex.StackTrace} ", ex);
//             mxlLog.Instance.IsErrorEnabled = true; 使能错误log
//             mxlLog.Instance.ClearOldLogs(5); 清理日志，仅保留近5天