using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using RealCV.Domain.Enums;
using RealCV.Infrastructure.Data;

namespace RealCV.Infrastructure.Jobs;

/// <summary>
/// Hangfire job that resets monthly CV check usage for users whose billing period has ended.
/// This job should run daily to catch users whose subscriptions renewed.
/// </summary>
public sealed class ResetMonthlyUsageJob
{
    private readonly ApplicationDbContext _dbContext;
    private readonly ILogger<ResetMonthlyUsageJob> _logger;

    public ResetMonthlyUsageJob(
        ApplicationDbContext dbContext,
        ILogger<ResetMonthlyUsageJob> logger)
    {
        _dbContext = dbContext;
        _logger = logger;
    }

    public async Task ExecuteAsync(CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("Starting monthly usage reset job");

        try
        {
            var now = DateTime.UtcNow;

            // Reset usage for paid users whose billing period has ended
            // The webhook handler already resets usage when subscription renews,
            // but this catches any edge cases or delays in webhook delivery
            var paidUsersToReset = await _dbContext.Users
                .Where(u => u.Plan != UserPlan.Free)
                .Where(u => u.CurrentPeriodEnd != null && u.CurrentPeriodEnd <= now)
                .Where(u => u.ChecksUsedThisMonth > 0)
                .Where(u => u.SubscriptionStatus == "active")
                .ToListAsync(cancellationToken);

            foreach (var user in paidUsersToReset)
            {
                user.ChecksUsedThisMonth = 0;
                _logger.LogInformation(
                    "Reset usage for paid user {UserId} - billing period ended {PeriodEnd}",
                    user.Id, user.CurrentPeriodEnd);
            }

            // Reset usage for free users on the 1st of each month
            if (now.Day == 1)
            {
                var freeUsersToReset = await _dbContext.Users
                    .Where(u => u.Plan == UserPlan.Free)
                    .Where(u => u.ChecksUsedThisMonth > 0)
                    .ToListAsync(cancellationToken);

                foreach (var user in freeUsersToReset)
                {
                    user.ChecksUsedThisMonth = 0;
                    _logger.LogInformation("Reset usage for free user {UserId}", user.Id);
                }

                _logger.LogInformation("Reset usage for {Count} free users", freeUsersToReset.Count);
            }

            await _dbContext.SaveChangesAsync(cancellationToken);

            _logger.LogInformation(
                "Monthly usage reset job completed. Reset {PaidCount} paid users",
                paidUsersToReset.Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error in monthly usage reset job");
            throw;
        }
    }
}
