// ============================================================
// HANGFIRE JOB TEMPLATE
// Generated by MORPH Framework
// ============================================================

using Hangfire;
using Microsoft.Extensions.Logging;

namespace MyProject.Application.Features.{Feature}.Jobs;

/// <summary>
/// Background job for processing {Feature}.
/// Uses Hangfire for scheduling and retry handling.
/// </summary>
public class {Feature}ProcessorJob(
    I{Feature}Service service,
    I{Feature}AnalyzerAgent analyzer,
    ILogger<{Feature}ProcessorJob> logger) : I{Feature}ProcessorJob
{
    /// <summary>
    /// Executes the {Feature} processing job.
    /// </summary>
    /// <param name="id">The {Feature} ID to process</param>
    /// <param name="cancellationToken">Cancellation token</param>
    [AutomaticRetry(Attempts = 3, DelaysInSeconds = new[] { 60, 300, 900 })]
    [Queue("default")]
    [JobDisplayName("{Feature} Processing - ID: {0}")]
    public async Task ExecuteAsync(int id, CancellationToken cancellationToken)
    {
        logger.LogInformation("Starting {Feature} processing for ID {Id}", id);

        try
        {
            // Get the entity
            var item = await service.GetByIdAsync(id, cancellationToken);
            if (item is null)
            {
                logger.LogWarning("{Feature} with ID {Id} not found, skipping", id);
                return;
            }

            // Check if already processed
            if (item.Status == {Feature}Status.Completed)
            {
                logger.LogInformation("{Feature} {Id} already completed, skipping", id);
                return;
            }

            // Perform analysis (if applicable)
            var analysisData = new {Feature}Data(item.Name);
            var analysis = await analyzer.AnalyzeAsync(analysisData, cancellationToken);

            logger.LogInformation(
                "{Feature} {Id} analyzed. Confidence: {Confidence:P0}",
                id, analysis.ConfidenceScore);

            // Update status
            // Note: You might need to add a method to update with analysis results
            // await service.CompleteWithAnalysisAsync(id, analysis, cancellationToken);

            logger.LogInformation("Completed {Feature} processing for ID {Id}", id);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to process {Feature} {Id}", id);
            throw; // Re-throw to trigger Hangfire retry
        }
    }
}

// ============================================================
// RECURRING JOB CONFIGURATION
// ============================================================
//
// For scheduled/recurring jobs, configure in Program.cs:
//
// // Run every hour
// RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
//     "{feature}-processor",
//     job => job.ExecuteAsync(0, CancellationToken.None),
//     Cron.Hourly);
//
// // Run daily at midnight
// RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
//     "{feature}-daily-processor",
//     job => job.ExecuteAsync(0, CancellationToken.None),
//     Cron.Daily);
//
// // Custom cron expression (every 15 minutes)
// RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
//     "{feature}-frequent-processor",
//     job => job.ExecuteAsync(0, CancellationToken.None),
//     "*/15 * * * *");
//
// ============================================================

// ============================================================
// BATCH JOB TEMPLATE
// ============================================================

/// <summary>
/// Batch job for processing multiple {Feature}s.
/// </summary>
public class {Feature}BatchProcessorJob(
    I{Feature}Service service,
    I{Feature}ProcessorJob itemProcessor,
    ILogger<{Feature}BatchProcessorJob> logger)
{
    /// <summary>
    /// Processes all pending {Feature}s.
    /// </summary>
    [AutomaticRetry(Attempts = 1)]
    [Queue("batch")]
    [JobDisplayName("{Feature} Batch Processing")]
    public async Task ProcessAllPendingAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("Starting batch processing for pending {Feature}s");

        var items = await service.GetAllAsync(cancellationToken);
        var pending = items.Where(x => x.Status == {Feature}Status.Pending).ToList();

        logger.LogInformation("Found {Count} pending {Feature}s to process", pending.Count);

        foreach (var item in pending)
        {
            // Enqueue individual processing jobs
            BackgroundJob.Enqueue<I{Feature}ProcessorJob>(
                job => job.ExecuteAsync(item.Id, CancellationToken.None));
        }

        logger.LogInformation("Enqueued {Count} processing jobs", pending.Count);
    }
}

// ============================================================
// HANGFIRE CONFIGURATION
// ============================================================
//
// In Program.cs:
//
// // Add Hangfire services
// builder.Services.AddHangfire(config => config
//     .SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
//     .UseSimpleAssemblyNameTypeSerializer()
//     .UseRecommendedSerializerSettings()
//     .UseSqlServerStorage(connectionString, new SqlServerStorageOptions
//     {
//         CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
//         SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
//         QueuePollInterval = TimeSpan.Zero,
//         UseRecommendedIsolationLevel = true,
//         DisableGlobalLocks = true
//     }));
//
// builder.Services.AddHangfireServer(options =>
// {
//     options.Queues = new[] { "default", "batch" };
//     options.WorkerCount = Environment.ProcessorCount * 2;
// });
//
// // Register jobs
// builder.Services.AddScoped<I{Feature}ProcessorJob, {Feature}ProcessorJob>();
// builder.Services.AddScoped<{Feature}BatchProcessorJob>();
//
// // In app pipeline
// app.UseHangfireDashboard("/hangfire", new DashboardOptions
// {
//     Authorization = new[] { new HangfireAuthorizationFilter() }
// });
//
// ============================================================
