using e_suite.Database.Core;
using eSuite.Core.Clock;
using Microsoft.AspNetCore.Builder;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace e_suite.Database.SqlServer;

public static class ESuiteDatabaseExtension
{
    public static void AddDatabaseContext(this WebApplicationBuilder builder)
    {
        var connectionString = BuildConnectionString(builder.Configuration);

        builder.Services.AddDbContext<SqlEsuiteDatabaseDbContext>(options => options
            .UseSqlServer(connectionString, b => b
                .MigrationsAssembly("e-suite.Database.SqlServer")
                .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery))
        );
        builder.Services.AddScoped<IEsuiteDatabaseDbContext>(provider => provider.GetRequiredService<SqlEsuiteDatabaseDbContext>());
    }

    public static Task<EsuiteDatabaseDbContext> CreateDatabase(IClock clock)
    {
        var configuration = BuildConfiguration();

        var connectionString = BuildConnectionString(configuration);

        var options = new DbContextOptionsBuilder<SqlEsuiteDatabaseDbContext>()
            .UseSqlServer(connectionString)
            .Options;

        var esuiteDatabase = new SqlEsuiteDatabaseDbContext(options, clock);
        
        return Task.FromResult<EsuiteDatabaseDbContext>(esuiteDatabase);
    }

    public static IConfiguration BuildConfiguration()
    {
        var environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");

        var configurationBuilder = new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), $"appsettings.json"), true, true);

        if (!string.IsNullOrEmpty(environmentName))
            configurationBuilder = configurationBuilder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(),
                $"appsettings.{environmentName}.json"));

        var configuration = configurationBuilder.Build();
        return configuration;
    }

#pragma warning disable IDE0060 // Remove unused parameter
    public static bool IsAzure(IConfiguration configuration)
#pragma warning restore IDE0060 // Remove unused parameter
    {
        var azureEnv = Environment.GetEnvironmentVariable("AZURE");
        return !string.IsNullOrWhiteSpace(azureEnv);
    }

    public static string BuildConnectionString(IConfiguration configuration)
    {
        var builder = new SqlConnectionStringBuilder
        {
            ApplicationName = "e-suite",
            MultipleActiveResultSets = true
        };

        var envSqlServername = Environment.GetEnvironmentVariable("SQL_SERVER");
        var envSqlDatabase = Environment.GetEnvironmentVariable("SQL_DATABASE");
        var envSqlUser = Environment.GetEnvironmentVariable("SQL_USER");
        var envSqlPassword = Environment.GetEnvironmentVariable("SQL_PASSWORD");
        var envSqlEncrypt = Environment.GetEnvironmentVariable("SQL_ENCRYPT");
        var envSqlTrustServerCertifiate = Environment.GetEnvironmentVariable("SQL_TRUSTSERVERCERTIFIATE");

        builder.InitialCatalog = !string.IsNullOrWhiteSpace(envSqlDatabase) ? envSqlDatabase : configuration.GetValue("database:databaseName", "esuite");
        builder.DataSource = !string.IsNullOrWhiteSpace(envSqlServername) ? envSqlServername : configuration.GetValue("database:server", "(local)");
        builder.Encrypt = (!string.IsNullOrWhiteSpace(envSqlEncrypt) ? envSqlEncrypt : configuration.GetValue("database:encrypt", "true")) == "true";
        builder.TrustServerCertificate = (!string.IsNullOrWhiteSpace(envSqlTrustServerCertifiate) ? envSqlTrustServerCertifiate == "true" : configuration.GetValue("database:trustServerCertificate", true));
        var username = !string.IsNullOrWhiteSpace(envSqlUser) ? envSqlUser : configuration.GetValue("database:username", string.Empty);
        var password = !string.IsNullOrWhiteSpace(envSqlPassword) ? envSqlPassword : configuration.GetValue("database:password", string.Empty);

        if (string.IsNullOrWhiteSpace(username))
        {
            builder.IntegratedSecurity = true;
        }
        else
        {
            builder.UserID = username;
            builder.Password = password;
        }
        
        return builder.ToString();
    }
}
