using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using NPin.Framework.SqlSugarCore.Abstractions;
using NPin.Framework.SqlSugarCore.Repositories;
using NPin.Framework.SqlSugarCore.Uow;
using SqlSugar;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Modularity;

namespace NPin.Framework.SqlSugarCore;

[DependsOn(typeof(AbpDddDomainModule))]
public class NPinFrameworkSqlSugarCoreModule : AbpModule
{
    public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
    {
        var service = context.Services;
        var configuration = service.GetConfiguration();
        Configure<DbConnOptions>(configuration.GetSection("DbConnOptions"));
        
        // 开放 sqlSugarClient
        service.TryAddScoped<ISqlSugarDbContext, SqlSugarDbContext>();
        // 不开放 sqlSugarClient
        //service.AddTransient<ISqlSugarClient>(x => x.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient);

        service.AddTransient(typeof(IRepository<>), typeof(SqlSugarRepository<>));
        service.AddTransient(typeof(IRepository<,>), typeof(SqlSugarRepository<,>));
        service.AddTransient(typeof(ISqlSugarRepository<>), typeof(SqlSugarRepository<>));
        service.AddTransient(typeof(ISqlSugarRepository<,>), typeof(SqlSugarRepository<,>));

        service.AddTransient(typeof(ISugarDbContextProvider<>), typeof(UnitOfWorkSqlSugarDbContextProvider<>));
        
        return Task.CompletedTask;
    }

    public override async Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
    {
        // CodeFirst & DataSeed
        var service = context.ServiceProvider;
        var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
        
        if (options.EnabledCodeFirst)
        {
            CodeFirst(service);
        }

        if (options.EnabledDbSeed)
        {
            await DataSeedAsync(service);
        }
    }

    /// <summary>
    /// CodeFirst 建库建表
    /// </summary>
    /// <param name="service"></param>
    private void CodeFirst(IServiceProvider service)
    {
        var moduleContainer = service.GetRequiredService<IModuleContainer>();
        var db = service.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient;

        // 尝试创建数据库
        db.DbMaintenance.CreateDatabase();

        var types = new List<Type>();
        foreach (var module in moduleContainer.Modules)
        {
            types.AddRange(module.Assembly.GetTypes()
                .Where(x => x.GetCustomAttribute<IgnoreCodeFirstAttribute>() == null)
                .Where(x => x.GetCustomAttribute<SugarTable>() != null)
                .Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
        }

        if (types.Count > 0)
        {
            db.CopyNew().CodeFirst.InitTables(types.ToArray());
        }
    }

    /// <summary>
    /// 同步种子数据
    /// </summary>
    /// <param name="service"></param>
    private async Task DataSeedAsync(IServiceProvider service)
    {
        var dataSeeder = service.GetRequiredService<IDataSeeder>();
        await dataSeeder.SeedAsync();
    }
}