using Serilog;
using Serilog.Events;
using ZB.MOM.WW.OtOpcUa.Core.Scripting;

namespace ZB.MOM.WW.OtOpcUa.Host.Logging;

/// <summary>
///     Composes the root script <see cref="Serilog.ILogger"/> — the single pipeline every
///     per-script logger derives from. Fans each script log event out to three destinations:
///     a dedicated rolling <c>scripts-*.log</c> file, the main server log (via
///     <see cref="ScriptLogCompanionSink"/>, mirroring Error-or-higher events at Warning), and
///     the cluster <c>script-logs</c> DPS topic (via <see cref="ScriptLogTopicSink"/>) so the
///     live Script-log Admin UI page can tail script output.
/// </summary>
public static class ScriptRootLoggerFactory
{
    /// <summary>
    ///     Builds the composed root script logger.
    /// </summary>
    /// <param name="publisher">
    ///     The publisher the topic sink forwards entries to (the DPS publisher in production).
    /// </param>
    /// <param name="filePath">
    ///     Path template for the rolling <c>scripts-*.log</c> file sink (e.g. <c>logs/scripts-.log</c>).
    /// </param>
    /// <param name="topicMinLevel">
    ///     Minimum level for events forwarded to the <c>script-logs</c> topic; lower-level events
    ///     still land in the file sink but are not pushed onto the cluster bus.
    /// </param>
    /// <param name="companionLogger">
    ///     The application's main logger that receives mirrored Error-or-higher script events at
    ///     Warning level. Passed explicitly so callers control the source rather than reading the
    ///     global <see cref="Serilog.Log.Logger"/> static inside the factory.
    /// </param>
    /// <returns>The composed root script logger.</returns>
    public static Serilog.Core.Logger Build(
        IScriptLogPublisher publisher, string filePath, LogEventLevel topicMinLevel,
        Serilog.ILogger companionLogger)
        => new LoggerConfiguration()
            .MinimumLevel.Verbose()
            .WriteTo.File(filePath, rollingInterval: RollingInterval.Day)
            .WriteTo.Sink(new ScriptLogCompanionSink(companionLogger))
            .WriteTo.Sink(new ScriptLogTopicSink(publisher, topicMinLevel))
            .CreateLogger();
}
