using System;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PolyTrader.Core.Modularity;

namespace PolyTrader.App.Avalonia.Shell
{
    /// <summary>
    /// Registriert die Fenster der Module. Liegt bewusst in der App und nicht in den Modulen –
    /// Begründung in <c>Views/Modules/README.md</c>: die Modulprojekte bleiben dadurch frei von
    /// Avalonia, was für den kopflosen Linux-Betrieb (<c>--headless</c>) den Ausschlag gibt.
    ///
    /// <para>Eine Seite bekommt nur, was auch geladen ist: ist ein Modul über
    /// <c>DisabledModules</c> abgeschaltet oder fehlt die Lizenz, fehlen seine Dienste im Container.
    /// Ein solches Modul wird dann als <see cref="AvaloniaUiHost.UnavailableView"/> gemeldet und
    /// erscheint in der Seitenleiste ausgegraut mit dem Grund – lautlos verschwinden darf es nicht.</para>
    /// </summary>
    public static class ModuleViews
    {
        public static void Register(AvaloniaUiHost host, IServiceProvider services)
        {
            RegisterIfLoaded(host, services, "CopyTrading", "Copytrading", "copytrading", 100,
                () => host.RegisterView(new ModuleView
            {
                Id = "copytrading.main",
                Title = "Copytrading",
                Group = "CopyTrading",
                Order = 100,
                CreateView = () => new Views.Modules.CopyTradingWindow(
                    host,
                    services.GetRequiredService<PolyTraderSharp.TradingState>(),
                    services.GetRequiredService<PolyTraderSharp.CopyTradingState>(),
                    services.GetRequiredService<Modules.CopyTrading.Persistence.ITrackedTraderRepository>(),
                    services.GetRequiredService<Modules.CopyTrading.Persistence.ICopyTradingAccountSettingsRepository>(),
                    services.GetRequiredService<Modules.CopyTrading.Persistence.ICopyTradeLogRepository>())
            }));

            RegisterIfLoaded(host, services, "ResolutionFarming", "ResolutionFarming", "resolutionfarming", 200,
                () => host.RegisterView(new ModuleView
            {
                Id = "resolutionfarming.main",
                Title = "ResolutionFarming",
                Group = "ResolutionFarming",
                Order = 200,
                CreateView = () => new Views.Modules.ResolutionFarmingWindow(
                    host,
                    services.GetRequiredService<PolyTraderSharp.TradingState>(),
                    services.GetRequiredService<Modules.ResolutionFarming.Persistence.IRfCandidateRepository>(),
                    services.GetRequiredService<Modules.ResolutionFarming.Persistence.IRfPositionRepository>(),
                    services.GetRequiredService<Modules.ResolutionFarming.Persistence.IRfClosedTradeRepository>(),
                    services.GetRequiredService<Modules.ResolutionFarming.Persistence.IRfSettingsRepository>())
            }));

            RegisterIfLoaded(host, services, "Supervisor", "Supervisor", "supervisor", 300,
                () => host.RegisterView(new ModuleView
            {
                Id = "supervisor.main",
                Title = "Supervisor",
                Group = "Supervisor",
                Order = 300,
                CreateView = () => new Views.Modules.SupervisorWindow(
                    host,
                    services.GetRequiredService<Modules.Supervisor.Agent.SupervisorAgent>(),
                    services.GetRequiredService<Modules.Supervisor.Services.DossierService>(),
                    services.GetRequiredService<Modules.Supervisor.Persistence.ISupervisorReportRepository>(),
                    services.GetRequiredService<Modules.Supervisor.Persistence.ISupervisorCounterfactualRepository>(),
                    services.GetRequiredService<PolyTraderSharp.Services.TerminalLogger>())
            }));

            RegisterIfLoaded(host, services, "Accounting", "Accounting", "accounting", 400,
                () => host.RegisterView(new ModuleView
            {
                Id = "accounting.main",
                Title = "Accounting",
                Group = "Accounting",
                Order = 400,
                CreateView = () => new Views.Modules.AccountingWindow(
                    host,
                    services.GetRequiredService<PolyTraderSharp.TradingState>(),
                    services.GetRequiredService<Modules.Accounting.Services.AccountingReportService>(),
                    services.GetRequiredService<Modules.Accounting.Persistence.ILedgerRepository>(),
                    services.GetRequiredService<Modules.Accounting.Persistence.IIngestRunRepository>(),
                    services.GetRequiredService<Modules.Accounting.Services.AccountingIngestService>(),
                    services.GetRequiredService<PolyTraderSharp.Services.TerminalLogger>())
            }));
        }

        /// <summary>
        /// Registriert die Seite, wenn das Modul in dieser Sitzung geladen ist – sonst einen
        /// ausgegrauten Platzhalter samt Grund.
        /// </summary>
        private static void RegisterIfLoaded(AvaloniaUiHost host, IServiceProvider services,
            string moduleName, string title, string iconKey, int order, Action register)
        {
            bool loaded = services.GetServices<IPolyTraderModule>()
                                  .Any(m => string.Equals(m.Name, moduleName, StringComparison.OrdinalIgnoreCase));
            if (loaded)
            {
                register();
                return;
            }

            host.RegisterUnavailable(new AvaloniaUiHost.UnavailableView(
                title, iconKey, order, BlockerOf(moduleName, services)));
        }

        /// <summary>
        /// Warum fehlt das Modul? Ein modul-eigener Grund (z.B. fehlender API-Key) ist die genaueste
        /// Auskunft; sonst bleibt der allgemeine Fall: Lizenz oder <c>DisabledModules</c>.
        /// </summary>
        private static string BlockerOf(string moduleName, IServiceProvider services)
        {
            var config = services.GetService<IConfiguration>();
            if (config != null)
            {
                IPolyTraderModule? known = moduleName.ToLowerInvariant() switch
                {
                    "copytrading" => new Modules.CopyTrading.CopyTradingModule(),
                    "resolutionfarming" => new Modules.ResolutionFarming.ResolutionFarmingModule(),
                    "supervisor" => new Modules.Supervisor.SupervisorModule(),
                    "accounting" => new Modules.Accounting.AccountingModule(),
                    _ => null
                };

                try
                {
                    string? blocker = known?.GetActivationBlocker(config);
                    if (!string.IsNullOrWhiteSpace(blocker))
                        return $"Modul nicht geladen: {blocker}";
                }
                catch
                {
                    // Die Auskunft ist ein Komfort, kein Muss – ein Fehler darin darf den Start
                    // nicht aufhalten. Dann greift der allgemeine Text.
                }
            }

            return "Modul in dieser Sitzung nicht geladen – Lizenz pruefen oder unter " +
                   "Einstellungen aktivieren (wirkt nach einem Neustart).";
        }
    }
}
