using AyCode.Core.Loggers;
using AyCode.Services.SignalRs;
using FruitBank.Common.Loggers;
using FruitBank.Common.Models;
using FruitBank.Common.Services;
using FruitBankHybrid.Services;
using FruitBankHybrid.Services.Loggers;
using FruitBankHybrid.Shared.Databases;
using FruitBankHybrid.Shared.Services;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
//using DevExpress.Maui;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Reflection;

namespace FruitBankHybrid
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder.UseMauiApp<App>()
                //.UseDevExpress(useLocalization: false)
                //.UseDevExpressCollectionView()
                //.UseDevExpressControls()
                //.UseDevExpressEditors()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                });

            // Load embedded appsettings.json — MAUI has no automatic config file discovery,
            // so the JSON is shipped as an EmbeddedResource (see FruitBankHybrid.csproj).
            using (var appsettingsStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FruitBankHybrid.appsettings.json"))
            {
                if (appsettingsStream is not null)
                {
                    var jsonConfig = new ConfigurationBuilder().AddJsonStream(appsettingsStream).Build();
                    builder.Configuration.AddConfiguration(jsonConfig);
                }
            }

#if DEBUG
            builder.Services.AddSingleton<IAcLogWriterClientBase, BrowserConsoleLogWriter>();
#endif
            builder.Services.AddSingleton<IAcLogWriterClientBase, SignaRClientLogItemWriter>();

            // Logger options + framework factory. LoggerClient instances are created per caller category,
            // with AppType+LogLevel from appsettings and writers resolved from DI via IAcLogWriterClientBase.
            builder.Services.Configure<AcLoggerOptions>(builder.Configuration.GetSection("AyCode:Logger"));
            builder.Services.AddAcLoggerFactory<LoggerClient, IAcLogWriterClientBase>();

            // Bind SignalR options from configuration.
            // Precedence: code default → appsettings.json (this line) → any later Configure<T> action.
            builder.Services.Configure<AcHubConnectionOptions>(builder.Configuration.GetSection("AcHubConnection"));
            builder.Services.Configure<AcBinaryHubProtocolOptions>(builder.Configuration.GetSection("AcBinaryHubProtocol"));

            // Add device-specific services used by the FruitBankHybrid.Shared project
            builder.Services.AddSingleton<IFormFactor, FormFactor>();
            builder.Services.AddSingleton<ISecureCredentialService, MauiSecureCredentialService>();

            builder.Services.AddSingleton<LoggedInModel>(sp => new LoggedInModel(sp.GetRequiredService<ISecureCredentialService>()));

            // SignalR HubConnectionBuilder — transient so each consumer gets a fresh builder to Build().
            // All connection and protocol configuration flows from appsettings.json via IOptions<T>;
            // AddAcDefaults (framework) applies AcHubConnectionOptions and bridges the provided logger into SignalR's internal pipeline.
            // NOTE: AcBinaryHubProtocolOptions is resolved from the OUTER service provider and passed
            // explicitly — HubConnectionBuilder's inner DI cannot see outer services.Configure<T>() registrations.
            builder.Services.AddTransient<IHubConnectionBuilder>(sp =>
            {
                var loggerFactory = sp.GetRequiredService<Func<string, LoggerClient>>();
                var connectionOpts = sp.GetRequiredService<IOptions<AcHubConnectionOptions>>().Value;
                var protocolOpts = sp.GetRequiredService<IOptions<AcBinaryHubProtocolOptions>>().Value;

                var logger = loggerFactory(nameof(FruitBankSignalRClient));
                var hubBuilder = new HubConnectionBuilder().AddAcDefaults(logger, connectionOpts);

                hubBuilder.AddAcBinaryProtocol(protocolOpts);
                return hubBuilder;
            });

            builder.Services.AddSingleton<FruitBankSignalRClient>();
            builder.Services.AddSingleton<DatabaseClient>();

            builder.Services.AddMauiBlazorWebView();
            builder.Services.AddDevExpressBlazor(configure => configure.SizeMode = DevExpress.Blazor.SizeMode.Medium);

#if DEBUG
            builder.Services.AddBlazorWebViewDeveloperTools();
            builder.Logging.AddDebug();
#endif

            return builder.Build();
        }
    }
}
