using System;
using Application;
using Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Infrastructure
{
  public static class ServiceCollectionExtensions
  {
    /// <summary>
    /// Ajout des services pour la gestion de notre domaine fonctionnel avec les implémentations
    /// à base d'Entity Framework Core.
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection AddHNServicesEF(this IServiceCollection services)
    {
      services.AddDbContext<HNDbContext>((provider, options) =>
      {
        var configuration = provider.GetRequiredService<IConfiguration>();

        // configuration["ConnectionStrings:Default"]

        options.UseSqlite(configuration.GetConnectionString("Default"));
      });

      services.AddScoped<ILinkRepository, Infrastructure.Repositories.EntityFramework.LinkRepository>();
      services.AddScoped<ICommentRepository, Infrastructure.Repositories.EntityFramework.CommentRepository>();
      services.AddScoped<IData, HNDbContext>();

      return services.AddCommon();
    }

    /// <summary>
    /// Ajout des services pour la gestion de notre domaine fonctionnel avec les implémentations
    /// en mémoire, parfait pour des tests.
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection AddHNServicesInMemory(this IServiceCollection services)
    {
      var uid = Guid.NewGuid();
      var link1 = new Domain.Link(uid, "http://default.website");
      var link2 = new Domain.Link(uid, "http://another.website");
      var link3 = new Domain.Link(uid, "http://a.final.website");

      services.AddSingleton<ILinkRepository>(new Infrastructure.Repositories.Memory.LinkRepository(
        link1,
        link2,
        link3
      ));
      services.AddSingleton<ICommentRepository>(new Infrastructure.Repositories.Memory.CommentRepository(
        link1.AddComment(uid, "my first comment"),
        link3.AddComment(uid, "another comment")
      ));
      services.AddSingleton<IData>(serviceProvider =>
      {
        var memoryLinkRepository = serviceProvider.GetRequiredService<ILinkRepository>() as Infrastructure.Repositories.Memory.LinkRepository;
        var memoryCommentRepository = serviceProvider.GetRequiredService<ICommentRepository>() as Infrastructure.Repositories.Memory.CommentRepository;
        return new Infrastructure.Repositories.Memory.Data(memoryLinkRepository, memoryCommentRepository);
      });


      return services.AddCommon();
    }

    /// <summary>
    /// Ajout des services communs peu importe la persistance choisie.
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    private static IServiceCollection AddCommon(this IServiceCollection services)
    {
      services.AddScoped<ICurrentUserProvider, HttpCurrentUserProvider>();
      services.AddTransient<LinkService>();
      services.AddTransient<CommentService>();

      return services;
    }
  }
}