using System.Collections.Concurrent;
using MEL = Microsoft.Extensions.Logging;

namespace ClawdDotNet.Core.Logging;

/// <summary>
/// ILoggerProvider-Implementierung für das dateibasierte Logging.
/// Erzeugt pro Kategorie (= Modul) einen eigenen ModuleLogger.
///
/// Kategorien werden auf Modulnamen gemappt:
///   "ClawdDotNet.Core.Engine.AgentEngine" → "Core"
///   "ClawdDotNet.Tools.Database.DatabaseTool" → "Tool_Database"
///   "ClawdDotNet.Tools.FileRW.FileRWTool" → "Tool_FileRW"
///   Alles andere → letzter Namespace-Teil oder "General"
/// </summary>
public sealed class FileLoggerProvider : MEL.ILoggerProvider
{
    private readonly FileLogWriter _writer;
    private readonly FileLoggerOptions _options;
    private readonly ConcurrentDictionary<string, ModuleLogger> _loggers = new();

    public FileLoggerProvider(FileLoggerOptions options)
    {
        _options = options;
        _writer = new FileLogWriter(options);
    }

    public MEL.ILogger CreateLogger(string categoryName)
    {
        var module = MapCategoryToModule(categoryName);
        return _loggers.GetOrAdd(module, m => new ModuleLogger(m, _writer, _options));
    }

    internal static string MapCategoryToModule(string categoryName)
    {
        if (string.IsNullOrWhiteSpace(categoryName))
            return "General";

        // ClawdDotNet.Core.* → "Core"
        if (categoryName.StartsWith("ClawdDotNet.Core.", StringComparison.Ordinal))
            return "Core";

        // ClawdDotNet.Host.* → "Host"
        if (categoryName.StartsWith("ClawdDotNet.Host.", StringComparison.Ordinal)
            || categoryName == "ClawdDotNet.Host")
            return "Host";

        // ClawdDotNet.Tools.{ToolName}.* → "Tool_{ToolName}"
        if (categoryName.StartsWith("ClawdDotNet.Tools.", StringComparison.Ordinal))
        {
            var afterTools = categoryName["ClawdDotNet.Tools.".Length..];
            var dotIndex = afterTools.IndexOf('.');
            var toolName = dotIndex > 0 ? afterTools[..dotIndex] : afterTools;
            return $"Tool_{toolName}";
        }

        // Fallback: letzter Segment-Teil
        var lastDot = categoryName.LastIndexOf('.');
        return lastDot >= 0 ? categoryName[(lastDot + 1)..] : categoryName;
    }

    public void Dispose()
    {
        _writer.DisposeAsync().AsTask().GetAwaiter().GetResult();
    }
}
