using Microsoft.AspNetCore.Identity;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using RpgRoller.Data;
using RpgRoller.Domain;
using RpgRoller.Services;

namespace RpgRoller.Hosting;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddRpgRollerCore(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment environment)
    {
        var sqliteConnectionString = configuration.GetConnectionString("RpgRoller") ?? "Data Source=App_Data/rpgroller.db";
        var sqliteDatabasePath = ResolveSqliteDatabasePath(sqliteConnectionString, environment.ContentRootPath);
        EnsureSqliteDataDirectory(sqliteDatabasePath);

        services.AddSingleton<IPasswordHasher<UserAccount>, PasswordHasher<UserAccount>>();
        services.AddSingleton(new SqliteDatabaseFile(sqliteDatabasePath));
        services.AddDbContextFactory<RpgRollerDbContext>(options => options.UseSqlite(sqliteConnectionString));
        services.AddSingleton<IDiceRoller, RandomDiceRoller>();
        services.AddSingleton<IGameService, GameService>();

        return services;
    }

    private static string? ResolveSqliteDatabasePath(string connectionString, string contentRootPath)
    {
        var builder = new SqliteConnectionStringBuilder(connectionString);
        if (string.IsNullOrWhiteSpace(builder.DataSource) || builder.DataSource == ":memory:")
            return null;

        var databasePath = Path.IsPathRooted(builder.DataSource) ? builder.DataSource : Path.Combine(contentRootPath, builder.DataSource);
        return Path.GetFullPath(databasePath);
    }

    private static void EnsureSqliteDataDirectory(string? sqliteDatabasePath)
    {
        var directory = Path.GetDirectoryName(sqliteDatabasePath);
        if (!string.IsNullOrWhiteSpace(directory))
            Directory.CreateDirectory(directory);
    }
}