using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities.Club;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace CMSMicroservice.Infrastructure.BackgroundServices;

/// <summary>
/// سرویس یکباره برای Seed کردن ClubMembershipCycle برای عضویت‌های فعال موجود.
/// عضویت‌هایی که قبل از اضافه شدن سیستم Cycle ایجاد شده‌اند رکورد ندارند.
/// این Worker در استارتاپ اجرا شده، برای آنها CycleNumber=1 می‌سازد و سپس متوقف می‌شود.
/// 
/// فعال/غیرفعال از appsettings:
///   "SeedWorkers": { "MagicWalletCycleSeed": { "Enabled": true } }
/// 
/// بعد از اجرای موفق، Enabled را false کنید.
/// </summary>
public class MagicWalletCycleSeedService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly ILogger<MagicWalletCycleSeedService> _logger;

    public MagicWalletCycleSeedService(
        IServiceScopeFactory scopeFactory,
        ILogger<MagicWalletCycleSeedService> logger)
    {
        _scopeFactory = scopeFactory;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // صبر کوتاه برای اطمینان از آماده شدن دیتابیس
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _logger.LogInformation("MagicWalletCycleSeedService started — scanning active memberships without cycles...");

        try
        {
            using var scope = _scopeFactory.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<IApplicationDbContext>();

            var seededCount = await SeedMissingCycles(context, stoppingToken);

            _logger.LogInformation(
                "MagicWalletCycleSeedService completed — seeded {Count} ClubMembershipCycle records",
                seededCount);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "MagicWalletCycleSeedService encountered an error");
        }

        _logger.LogInformation(
            "MagicWalletCycleSeedService finished — shutting down (one-time execution). " +
            "Set SeedWorkers:MagicWalletCycleSeed:Enabled to false in appsettings.");
    }

    private async Task<int> SeedMissingCycles(IApplicationDbContext context, CancellationToken ct)
    {
        // پیدا کردن عضویت‌های فعالی که هنوز Cycle ندارند
        var membershipIdsWithCycle = await context.ClubMembershipCycles
            .Where(c => !c.IsDeleted)
            .Select(c => c.ClubMembershipId)
            .Distinct()
            .ToListAsync(ct);

        var membershipsWithoutCycle = await context.ClubMemberships
            .Where(cm => !cm.IsDeleted && cm.IsActive && !membershipIdsWithCycle.Contains(cm.Id))
            .Select(cm => new
            {
                cm.Id,
                cm.UserId,
                cm.ActivatedAt
            })
            .ToListAsync(ct);

        if (membershipsWithoutCycle.Count == 0)
        {
            _logger.LogInformation("No active memberships without cycles found — nothing to seed");
            return 0;
        }

        _logger.LogInformation("Found {Count} active memberships without ClubMembershipCycle — seeding...",
            membershipsWithoutCycle.Count);

        var seeded = 0;
        foreach (var cm in membershipsWithoutCycle)
        {
            if (ct.IsCancellationRequested) break;

            try
            {
                var cycle = new ClubMembershipCycle
                {
                    UserId = cm.UserId,
                    ClubMembershipId = cm.Id,
                    CycleNumber = 1,
                    PackagePurchasedAt = cm.ActivatedAt ?? DateTime.UtcNow,
                    IsCurrentCycle = true,
                    PurchaseMethod = 0,
                    PackageAmount = 0
                };

                context.ClubMembershipCycles.Add(cycle);
                seeded++;

                _logger.LogDebug(
                    "Seeded ClubMembershipCycle for UserId={UserId}, MembershipId={MembershipId}, ActivatedAt={ActivatedAt}",
                    cm.UserId, cm.Id, cm.ActivatedAt);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex,
                    "Failed to seed cycle for MembershipId={MembershipId}, UserId={UserId}",
                    cm.Id, cm.UserId);
            }
        }

        await context.SaveChangesAsync(ct);

        return seeded;
    }
}
