using Serilog.Events;
using System.Collections.Generic;

namespace Ayay.SerilogLogs
{
    /// <summary>
    /// 日志组件配置选项
    /// <para>包含身份标识、存储路径、分级策略以及自动清理策略。</para>
    /// </summary>
    public class LogOptions
    {
        // ==========================================
        // 1. 基础身份标识
        // ==========================================

        /// <summary>
        /// 应用名称/服务ID。
        /// <para>例如: "VideoServer-01", "Gatekeeper-Api"。</para>
        /// <para>在 Seq 中对应 {AppId} 属性，用于区分多服务环境下的日志来源。</para>
        /// </summary>
        public string AppId { get; set; } = "DefaultApp";

        // ==========================================
        // 2. 存储路径配置
        // ==========================================

        /// <summary>
        /// 本地日志文件的存储根目录。
        /// <para>默认: @"D:\Logs"</para>
        /// <para>程序会自动在此目录下按模块创建子文件夹（如 System, Network）。</para>
        /// <para>注意：如果该目录无写入权限，组件会自动降级到程序运行目录。</para>
        /// </summary>
        public string LogRootPath { get; set; } = @"D:\Logs";

        // ==========================================
        // 3. Seq 集中式日志配置
        // ==========================================

        /// <summary>
        /// Seq 服务器地址。
        /// <para>例如: "http://192.168.1.100:5341"</para>
        /// <para>如果留空 (null/empty)，则不启用 Seq 投递。</para>
        /// </summary>
        public string SeqServerUrl { get; set; }

        /// <summary>
        /// Seq API Key (令牌)。
        /// <para>建议在 Seq 后台申请仅具有 [Ingest] 权限的 Key。</para>
        /// <para>配置 Key 后支持动态调整日志级别 (Dynamic Level Control)。</para>
        /// </summary>
        public string SeqApiKey { get; set; }

        /// <summary>
        /// 机器码
        /// </summary>
        public string PcCode { get; set; }

        // ==========================================
        // 4. 输出端级别控制 (Sink Levels)
        // 用于控制不同媒介的“过滤网”疏密程度
        // ==========================================

        /// <summary>
        /// 控制台输出的最低级别。
        /// <para>默认: Information (开发调试时可改为 Debug)</para>
        /// </summary>
        public LogEventLevel ConsoleLevel { get; set; } = LogEventLevel.Information;

        /// <summary>
        /// 本地文件记录的最低级别。
        /// <para>默认: Debug (保留详细案底，便于事后追溯)</para>
        /// <para>注意：具体写入哪个文件(Main/Detail)由内部逻辑决定，此属性控制总开关。</para>
        /// </summary>
        public LogEventLevel FileLevel { get; set; } = LogEventLevel.Verbose;

        /// <summary>
        /// Seq 网络传输的最低级别。
        /// <para>默认: Information (减少网络带宽和服务器存储压力)</para>
        /// <para>生产环境建议设为 Information 或 Warning，除非需要在线排错。</para>
        /// </summary>
        public LogEventLevel SeqLevel { get; set; } = LogEventLevel.Verbose;

        // ==========================================
        // 5. 业务模块级别控制 (Context Levels)
        // 用于精细化控制特定业务模块的日志开关
        // ==========================================

        /// <summary>
        /// 全局默认最低级别。
        /// <para>如果某个日志没有指定模块，或者模块不在 ModuleLevels 列表中，则使用此级别。</para>
        /// </summary>
        public LogEventLevel GlobalMinimumLevel { get; set; } = LogEventLevel.Verbose;

        /// <summary>
        /// 针对特定业务模块的日志级别覆盖 (Override)。
        /// <para>Key: 模块名称 (建议使用 LogModules 常量字符串)</para>
        /// <para>Value: 该模块允许记录的最低级别</para>
        /// </summary>
        public Dictionary<string, LogEventLevel> ModuleLevels { get; set; } = new Dictionary<string, LogEventLevel>
        {
            // --- 系统层 ---
            { LogModules.Core,          LogEventLevel.Debug },      // 系统主逻辑
            { LogModules.Network,       LogEventLevel.Debug },      // 网络通讯：平时只看警告，防止心跳刷屏
            { LogModules.WebApi,        LogEventLevel.Debug },      // WebAPI：记录请求响应
            { LogModules.gRpc,          LogEventLevel.Debug },      // gRpc：记录请求响应
            
            // --- 业务层 ---
            { LogModules.UserSystem,    LogEventLevel.Debug },      // 用户系统
            { LogModules.UserAction,    LogEventLevel.Debug },      // 用户操作：必须记录，用于审计
            { LogModules.DeviceOps,     LogEventLevel.Debug },      // 设备操作：记录关键指令

            // --- 核心/高频数据 ---
            { LogModules.Algorithm,     LogEventLevel.Debug },      // 算法：核心业务，开启 Debug 以记录全过程
            { LogModules.Observation,   LogEventLevel.Debug },      // 观察点：最详细的埋点
            
            // --- 降噪区 (垃圾数据屏蔽) ---
            { LogModules.WebSocket,     LogEventLevel.Debug },      // WS：数据量极大，除非报错否则不记
            { LogModules.Ping,          LogEventLevel.Debug },      // Ping：几乎不记，除非完全断连
            { LogModules.HikVisionSdk,  LogEventLevel.Debug },      // SDK：屏蔽第三方的废话日志
            { LogModules.DaHuaSdk,      LogEventLevel.Debug },      // SDK：屏蔽第三方的废话日志
        };

        // ==========================================
        // 6. 文件滚动策略 (Rolling Policy)
        // 控制单个日志文件的大小和生成频率
        // ==========================================

        /// <summary>
        /// 单个日志文件大小限制 (单位：字节)。
        /// <para>默认: 10MB (10 * 1024 * 1024)</para>
        /// <para>当文件超过此大小时，会自动创建新文件 (例如 Main_001.txt)。</para>
        /// <para>建议不要设置过大，否则记事本打开会很卡。</para>
        /// </summary>
        public long FileSizeLimitBytes { get; set; } = 10 * 1024 * 1024;

        /// <summary>
        /// 超过大小限制后是否创建新文件。
        /// <para>默认: true (推荐)</para>
        /// </summary>
        public bool RollOnFileSizeLimit { get; set; } = true;

        // ==========================================
        // 7. 自动清理策略 (Auto Cleanup)
        // 由后台 LogCleaner 任务执行，满足任意条件即清理
        // ==========================================

        /// <summary>
        /// 历史日志最大保留天数 (时间策略)。
        /// <para>默认: 30天</para>
        /// <para>系统会强制删除最后修改时间超过此天数的文件。</para>
        /// </summary>
        public int MaxRetentionDays { get; set; } = 30;

        /// <summary>
        /// 日志目录总大小上限 (空间策略)。
        /// <para>默认: 1GB (1024 * 1024 * 1024)</para>
        /// <para>如果所有日志文件总和超过此大小，系统会按时间倒序(从旧到新)删除文件，直到空间低于此值。</para>
        /// </summary>
        public long MaxTotalLogSize { get; set; } = 1024L * 1024 * 1024;
    }
}