using Microsoft.Extensions.DependencyInjection;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Quartz;
using Microsoft.IdentityModel.Tokens;
namespace HuanMeng.DotNetCore.QuartzExtend;

/// <summary>
/// 提供扩展方法，用于基于 QuartzTriggerAttribute 注册 Quartz 作业和触发器。
/// </summary>
public static class QuartzExtensions
{
    /// <summary>
    /// 扫描指定程序集中的所有带有 QuartzTriggerAttribute 的作业类，并将它们注册到 Quartz 调度器中。
    /// </summary>
    /// <param name="services">依赖注入服务集合。</param>
    /// <param name="assembly">要扫描的程序集。</param>
    /// <returns>更新后的服务集合。</returns>
    public static IServiceCollection AddQuartzWithAttributes(this IServiceCollection services, Assembly assembly)
    {
        services.AddQuartz(q =>
        {
            // 查找实现了 IJob 接口并带有 QuartzTriggerAttribute 特性的所有类
            var jobTypes = assembly.GetTypes()
                .Where(t => t.IsClass && !t.IsAbstract && typeof(IJob).IsAssignableFrom(t));

            foreach (var jobType in jobTypes)
            {
                // 获取 QuartzTriggerAttribute 特性实例
                var attr = jobType.GetCustomAttribute<QuartzTriggerAttribute>();
                if (attr != null)
                {
                    // 注册作业
                    var jobKey = new JobKey(jobType.Name); // 使用类名作为作业的唯一标识
                    q.AddJob(jobType, jobKey, opts => opts.WithIdentity(jobKey)); // 将作业注册到调度器

                    // 根据特性中定义的调度配置注册触发器
                    if (!string.IsNullOrEmpty(attr.CronExpression))
                    {
                        // 如果定义了 Cron 表达式，使用 Cron 调度
                        q.AddTrigger(opts => opts
                            .ForJob(jobKey)
                            .WithIdentity(attr.TriggerName)
                            .WithCronSchedule(attr.CronExpression));
                    }
                    else if (attr.IntervalInSeconds.HasValue && attr.IntervalInSeconds > 0)
                    {
                        // 如果定义了简单时间间隔，使用简单调度
                        q.AddTrigger(opts => opts
                            .ForJob(jobKey)
                            .WithIdentity(attr.TriggerName)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(attr.IntervalInSeconds.Value).RepeatForever()));
                    }
                }
            }
        });

        // 注册 Quartz 的托管服务
        services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
        return services;
    }
}
