using Hangfire;
using Hangfire.Dashboard;
using Hangfire.MemoryStorage;
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
using QYZH.InteractiveMagazine.Infrastructure.Redis;
using QYZH.InteractiveMagazine.Infrastructure.SDK;
using QYZH.InteractiveMagazine.Models.Settings;
using QYZH.InteractiveMagazine.WorkService.Consumers;
using QYZH.InteractiveMagazine.WorkService.Jobs;
using Serilog;
using SqlSugar;
using SqlSugar.IOC;
using System.Linq.Expressions;
using System.Reflection;
using Yitter.IdGenerator;

var builder = WebApplication.CreateBuilder(args);

// 加载配置
builder.Configuration
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);

// 配置Serilog
Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .CreateLogger();
builder.Services.AddSerilog();

// 初始化雪花ID生成器
YitIdHelper.SetIdGenerator(new IdGeneratorOptions { WorkerId = 2 });

// 初始化MySQL（SqlSugar）
builder.Services.AddSqlSugar(new IocConfig
{
    ConfigId = 0,
    DbType = IocDbType.MySql,
    ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection"),
    IsAutoCloseConnection = true
});
SugarIocServices.ConfigurationSugar(db =>
{
    db.Aop.OnLogExecuting = (sql, pars) =>
    {
        Log.Information("[SQL] {Sql}", UtilMethods.GetSqlString((DbType)IocDbType.MySql, sql, pars));
    };
    db.Aop.OnError = ex =>
    {
        Log.Error(ex, "[SQL Error] {Message}", ex.Message);
    };
});

// 显式注册 ISqlSugarClient，供后台服务中通过 DI 解析
builder.Services.AddScoped<ISqlSugarClient>(_ => DbScoped.SugarScope);

// 配置Hangfire（内存存储，后续可切换Redis）
builder.Services.AddHangfire(config => config
    .UseMemoryStorage()
    .UseSerializerSettings(new Newtonsoft.Json.JsonSerializerSettings
    {
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
    }));
builder.Services.AddHangfireServer();

// 配置Redis
builder.Services.AddCSRedisCacheExtension(builder.Configuration.GetSection("RedisSettings"));

// 配置HttpClient
builder.Services.AddHttpClient();

// 配置OSS/SDK服务
builder.Services.AddSDKService(builder.Configuration);

// 配置RabbitMQ
builder.Services.AddRabbitMQ(builder.Configuration);

// 注册队列消费者（新增消费者只需实现 IQueueConsumer 并在此注册）
builder.Services.AddScoped<IQueueConsumer, JournalTaskReceiveConsumer>();
builder.Services.AddScoped<IQueueConsumer, UserJournalQrCodeGenerateConsumer>();

// 注册消费者后台服务
builder.Services.AddHostedService<RabbitMQHostedService>();

// 从配置文件读取定时任务列表
var jobSettings = builder.Configuration.GetSection("HangfireJobs").Get<HangfireJobSettings>();

var app = builder.Build();

// 配置Hangfire Dashboard（仅本机访问）
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new LocalRequestsOnlyAuthorizationFilter() }
});

// 根据配置动态注册定时任务
if (jobSettings?.Jobs != null)
{
    foreach (var job in jobSettings.Jobs)
    {
        var jobType = Type.GetType(job.JobType);
        if (jobType == null)
        {
            Log.Warning("定时任务 [{Name}] 类型未找到: {JobType}，跳过注册", job.Name, job.JobType);
            continue;
        }

        if (!job.Enabled)
        {
            // 配置为关闭的任务，从 Hangfire 中移除
            RecurringJob.RemoveIfExists(job.Name);
            Log.Information("定时任务 [{Name}] 已禁用，已移除", job.Name);
            continue;
        }

        // 构造表达式：job => job.MethodName()
        var method = jobType.GetMethod(job.MethodName);
        if (method == null)
        {
            Log.Warning("定时任务 [{Name}] 方法未找到: {MethodName}，跳过注册", job.Name, job.MethodName);
            continue;
        }

        var param = Expression.Parameter(jobType, "job");
        var call = Expression.Call(param, method);
        var lambda = Expression.Lambda<Action>(call, param);

        RecurringJob.AddOrUpdate(job.Name, lambda, job.Cron);
        Log.Information("定时任务 [{Name}] 已注册，Cron: {Cron}", job.Name, job.Cron);
    }
}

Log.Information("WorkService 已启动，Hangfire Dashboard: /hangfire");

app.Run();
