using Dalamud.Plugin;
using HellionChat.Integrations;
using HellionChat.Ipc;
using HellionChat.Themes;
using Microsoft.Extensions.Hosting;

namespace HellionChat.Infrastructure.Hosting;

// Adapter shells around IHostedService so the host triggers each service's
// existing init method without touching the service class itself. Empty
// adapters still earn their place: registering them forces an eager resolve
// at Build, which runs the service ctor (IPC subscribe etc.) right then
// instead of lazily on first GetRequiredService.

internal sealed class ThemeRegistryInitHostedService(ThemeRegistry registry) : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Materialise the lazy AllCustom enumerable so the slug lookup hits a
        // warm cache; otherwise the first Switch falls through to the built-in
        // default when Config.Theme points at a custom slug.
        foreach (var _ in registry.AllCustom()) { }
        registry.SwitchSilent(Plugin.Config.Theme);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

// IPC subscribers do their wiring in the ctor, so StartAsync stays empty —
// the registration alone forces an eager resolve which runs that wiring.

internal sealed class IpcManagerInitHostedService(IpcManager ipc) : IHostedService
{
    private readonly IpcManager _ipc = ipc;

    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

internal sealed class TypingIpcInitHostedService(TypingIpc typingIpc) : IHostedService
{
    private readonly TypingIpc _typingIpc = typingIpc;

    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

internal sealed class ExtraChatInitHostedService(ExtraChat extraChat) : IHostedService
{
    private readonly ExtraChat _extraChat = extraChat;

    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

internal sealed class MessageManagerInitHostedService(
    IDalamudPluginInterface pluginInterface,
    MessageManager manager
) : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        // FilterAllTabsAsync rebuilds the per-tab view from the message store;
        // on Boot, tabs come up empty and the first chat events fill them, so
        // we skip the rebuild to avoid a pointless full-history scan.
        if (pluginInterface.Reason is not PluginLoadReason.Boot)
            manager.FilterAllTabsAsync();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

internal sealed class AutoTellTabsServiceInitHostedService(AutoTellTabsService service)
    : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        service.Initialize();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

// Eager-resolve trigger: resolving FailedTellNotifier in this adapter's ctor
// enables its game hook during host startup. StartAsync itself is a no-op.
internal sealed class FailedTellNotifierInitHostedService(FailedTellNotifier notifier)
    : IHostedService
{
    // No-op adapter: the ctor dependency above is the actual eager-resolve
    // trigger. Field kept to match the IpcManager/TypingIpc/ExtraChat no-op
    // adapters and to avoid the CS9113 unread-parameter warning.
    private readonly FailedTellNotifier _notifier = notifier;

    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
