using System.Diagnostics.CodeAnalysis;
using AyCode.Core.Enums;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace AyCode.Core.Loggers;

/// <summary>
/// DI extension methods for the <see cref="AcLoggerBase"/> factory pattern.
/// <para>
/// Consumers call one of the <c>AddAcLoggerFactory</c> overloads after
/// <c>services.Configure&lt;AcLoggerOptions&gt;(...)</c> to register a
/// <see cref="Func{String, AcLoggerBase}"/> singleton that produces category-scoped
/// logger instances with DI-resolved writers.
/// </para>
/// </summary>
public static class AcLoggerServiceExtensions
{
    /// <summary>
    /// Registers a logger factory creating <typeparamref name="TLogger"/> instances per caller category.
    /// Writers are resolved from DI via <see cref="IAcLogWriterBase"/> (all registered writers are included).
    /// </summary>
    /// <typeparam name="TLogger">
    /// Concrete logger type. Must expose a public constructor with signature
    /// <c>(AppType, LogLevel, string?, params IAcLogWriterBase[])</c>.
    /// </typeparam>
    /// <param name="services">The service collection.</param>
    /// <param name="defaultAppType">A host kód-defaultja (pl. WASM/MAUI kliensen <see cref="AppType.Web"/>) — CSAK akkor
    /// érvényesül, ha az appsettings (<see cref="AcLoggerOptions.AppType"/>) nem adja meg; ha a config kimondja, az nyer.</param>
    public static IServiceCollection AddAcLoggerFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TLogger>(
        this IServiceCollection services, AppType defaultAppType = AppType.Server)
        where TLogger : AcLoggerBase
    {
        return services.AddAcLoggerFactory<TLogger, IAcLogWriterBase>(defaultAppType);
    }

    /// <summary>
    /// Registers a logger factory with a custom writer marker interface — e.g. a client-only marker
    /// to keep server-only and client-only writers separated at the DI level.
    /// </summary>
    /// <typeparam name="TLogger">Concrete logger type. See <see cref="AddAcLoggerFactory{TLogger}(IServiceCollection, AppType)"/> for ctor requirements.</typeparam>
    /// <typeparam name="TWriterBase">Writer marker interface; must extend <see cref="IAcLogWriterBase"/>.</typeparam>
    /// <param name="services">The service collection.</param>
    /// <param name="defaultAppType">A host kód-defaultja — csak config-érték hiányában érvényesül (a config nyer).</param>
    public static IServiceCollection AddAcLoggerFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TLogger, TWriterBase>(
        this IServiceCollection services, AppType defaultAppType = AppType.Server)
        where TLogger : AcLoggerBase
        where TWriterBase : class, IAcLogWriterBase
    {
        services.AddSingleton<Func<string, TLogger>>(sp =>
        {
            var opts = sp.GetRequiredService<IOptions<AcLoggerOptions>>().Value;
            // Prioritás: appsettings (ha megadva) → a hívó defaultAppType-ja. Így a host kódja hordozza a helyes
            // alapértéket (kliensen Web/Mobile), a config pedig runtime felülírást ad újrafordítás nélkül.
            var appType = opts.AppType ?? defaultAppType;
            return categoryName =>
            {
                var writers = sp.GetServices<TWriterBase>().Cast<IAcLogWriterBase>().ToArray();
                return (TLogger)Activator.CreateInstance(typeof(TLogger), appType, opts.LogLevel, categoryName, writers)!;
            };
        });

        return services;
    }
}
