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

namespace AyCode.Core.Loggers;

/// <summary>
/// ILoggerProvider implementation that creates logger instances using AcLoggerBase.
/// Since AcLoggerBase now implements ILogger directly, this provider just wraps
/// the base logger with category-specific instances.
/// </summary>
public sealed class AcLoggerProvider<TLogger> : ILoggerProvider where TLogger : AcLoggerBase
{
    private readonly Func<string, TLogger> _loggerFactory;
    private readonly ConcurrentDictionary<string, TLogger> _loggers = new(StringComparer.OrdinalIgnoreCase);

    /// <summary>
    /// Creates a provider that uses a factory function to create category-specific loggers.
    /// </summary>
    /// <param name="loggerFactory">Factory function that creates a logger for a given category name.</param>
    public AcLoggerProvider(Func<string, TLogger> loggerFactory)
    {
        ArgumentNullException.ThrowIfNull(loggerFactory);
        _loggerFactory = loggerFactory;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return _loggers.GetOrAdd(categoryName, _loggerFactory);
    }

    public void Dispose()
    {
        _loggers.Clear();
    }
}

/// <summary>
/// Extension methods for registering AcLogger with Microsoft's DI and logging infrastructure.
/// </summary>
public static class AcLoggerExtensions
{
    /// <summary>
    /// Adds AcLogger as a logging provider using a factory function.
    /// The factory receives the category name and should return a configured logger instance.
    /// </summary>
    /// <example>
    /// <code>
    /// builder.Logging.AddAcLogger(categoryName => new MyLogger(categoryName));
    /// </code>
    /// </example>
    public static ILoggingBuilder AddAcLogger<TLogger>(this ILoggingBuilder builder, Func<string, TLogger> loggerFactory)
        where TLogger : AcLoggerBase
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentNullException.ThrowIfNull(loggerFactory);

        builder.AddProvider(new AcLoggerProvider<TLogger>(loggerFactory));
        return builder;
    }

    /// <summary>
    /// Clears default providers and adds only AcLogger.
    /// Use this if you want ONLY your logger, not Microsoft's console/debug loggers.
    /// </summary>
    public static ILoggingBuilder UseOnlyAcLogger<TLogger>(this ILoggingBuilder builder, Func<string, TLogger> loggerFactory)
        where TLogger : AcLoggerBase
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentNullException.ThrowIfNull(loggerFactory);

        builder.ClearProviders();
        builder.AddProvider(new AcLoggerProvider<TLogger>(loggerFactory));
        return builder;
    }
}
