using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using NeonSprawl.Server.Game.Items;
using NeonSprawl.Server.Game.Skills;

namespace NeonSprawl.Server.Game.Gathering;

/// <summary>DI registration for the fail-fast resource-node catalog and registry (NEO-58, NEO-59).</summary>
public static class ResourceNodeCatalogServiceCollectionExtensions
{
    /// <summary>
    /// Binds <see cref="ContentPathsOptions"/> and registers <see cref="ResourceNodeCatalog"/> and
    /// <see cref="IResourceNodeDefinitionRegistry"/> as singletons.
    /// </summary>
    public static IServiceCollection AddResourceNodeCatalog(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddOptions<ContentPathsOptions>()
            .Bind(configuration.GetSection(ContentPathsOptions.SectionName));

        services.AddSingleton<ResourceNodeCatalog>(sp =>
        {
            var hostEnv = sp.GetRequiredService<IHostEnvironment>();
            var opts = sp.GetRequiredService<IOptions<ContentPathsOptions>>().Value;
            var itemCatalog = sp.GetRequiredService<ItemDefinitionCatalog>();
            var logger = sp.GetRequiredService<ILoggerFactory>()
                .CreateLogger("NeonSprawl.Server.Game.Gathering.ResourceNodeCatalog");

            var resourceNodesDir = ResourceNodeCatalogPathResolution.ResolveResourceNodesDirectory(
                opts.ResourceNodesDirectory,
                hostEnv.ContentRootPath);
            var nodeSchemaPath = ResourceNodeCatalogPathResolution.ResolveResourceNodeDefSchemaPath(
                resourceNodesDir,
                opts.ResourceNodeDefSchemaPath,
                hostEnv.ContentRootPath);
            var yieldSchemaPath = ResourceNodeCatalogPathResolution.ResolveResourceYieldRowSchemaPath(
                resourceNodesDir,
                opts.ResourceYieldRowSchemaPath,
                hostEnv.ContentRootPath);

            var knownItemIds = itemCatalog.ById.Keys.ToHashSet(StringComparer.Ordinal);

            return ResourceNodeCatalogLoader.Load(
                resourceNodesDir,
                nodeSchemaPath,
                yieldSchemaPath,
                knownItemIds,
                logger);
        });

        services.AddSingleton<IResourceNodeDefinitionRegistry>(sp =>
            new ResourceNodeDefinitionRegistry(sp.GetRequiredService<ResourceNodeCatalog>()));

        services.AddResourceNodeInstanceStore(configuration);

        return services;
    }
}
