using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.ScadaBridge.CentralUI.Auth;
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
using ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis;
using ZB.MOM.WW.ScadaBridge.CentralUI.Services;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;

namespace ZB.MOM.WW.ScadaBridge.CentralUI;

public static class ServiceCollectionExtensions
{
    /// <summary>
    /// Registers all Central UI services including Blazor, auth state, dialogs, audit query, and script analysis.
    /// </summary>
    /// <param name="services">The service collection to configure.</param>
    /// <returns>The <paramref name="services"/> instance for chaining.</returns>
    public static IServiceCollection AddCentralUI(this IServiceCollection services)
    {
        services.AddRazorComponents()
            .AddInteractiveServerComponents();

        services.AddHttpContextAccessor();

        services.AddScoped<AuthenticationStateProvider, CookieAuthenticationStateProvider>();
        services.AddCascadingAuthenticationState();

        // Resolves the current user's permitted site set from their SiteId claims
        // so Deployment/Monitoring pages can enforce site scoping (CentralUI-002).
        services.AddScoped<SiteScopeService>();

        // Centralised dialog service: pages inject IDialogService and a single
        // <DialogHost /> in MainLayout renders the active dialog. See
        // Components/Shared/IDialogService.cs.
        services.AddScoped<IDialogService, DialogService>();

        // Audit Log (#23 M7-T3): CentralUI facade over IAuditLogRepository so the
        // results grid can be tested with a stubbed query source.
        //
        // Registered with an explicit factory so the IServiceScopeFactory ctor is
        // always chosen — AuditLogQueryService has a second (test-seam) ctor that
        // takes IAuditLogRepository directly, and both are constructor-resolvable,
        // so default activation would be ambiguous. The scope-factory ctor opens a
        // fresh DbContext per query, which is what keeps the page's auto-load from
        // racing AuditFilterBar's site enumeration on the shared scoped context.
        services.AddScoped<IAuditLogQueryService>(sp => new AuditLogQueryService(
            sp.GetRequiredService<IServiceScopeFactory>(),
            sp.GetRequiredService<ICentralHealthAggregator>()));

        // Audit Log (#23 M7-T14 / Bundle F): server-side streaming CSV export.
        // Backs the Audit Log page's Export button via GET /api/centralui/audit/export.
        services.AddScoped<IAuditLogExportService, AuditLogExportService>();

        // OPC UA Tag Browser (Task 14): facade over CommunicationService.BrowseNodeAsync
        // that enforces the CentralUI-side Design-role trust boundary and translates
        // transport failures into typed BrowseFailure results for the dialog.
        services.AddScoped<IBrowseService, BrowseService>();

        // Test Bindings: facade over CommunicationService.ReadTagValuesAsync —
        // same Design-role guard + typed-failure translation as the browse
        // service. Backs the Test Bindings dialog on the Configure Instance
        // page (one-shot live read of every bound attribute, grouped by
        // connection).
        services.AddScoped<IBindingTester, BindingTester>();

        // Roslyn-backed C# analysis for the Monaco script editor.
        // Scoped because SharedScriptCatalog wraps a scoped service.
        services.AddMemoryCache(o => o.SizeLimit = 200);
        services.AddScoped<ISharedScriptCatalog, SharedScriptCatalog>();
        services.AddScoped<ScriptAnalysisService>();

        return services;
    }
}
