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

namespace CMSMicroservice.Infrastructure.BackgroundServices;

/// <summary>
/// سرویس یکباره (Migration) برای مقداردهی اولیه انبارداری از محصولات قدیمی.
/// محصولاتی که قبل از فعال‌سازی سیستم انبارداری ایجاد شده‌اند رکورد InventoryItem ندارند.
/// این Worker در استارتاپ اجرا شده، برای آنها رکورد می‌سازد و سپس متوقف می‌شود.
/// توجه: محصولات جدید از طریق CreateProductCommandHandler خودکار رکورد انبار دریافت می‌کنند.
/// این سرویس را می‌توانید بعد از اجرای اولیه از DI حذف کنید.
/// </summary>
public class InventoryInitializerService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly ILogger<InventoryInitializerService> _logger;

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

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

        _logger.LogInformation("InventoryInitializerService started — scanning products for missing inventory records...");

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

            var (regularCount, discountCount) = await InitializeAllProducts(context, inventoryService, stoppingToken);

            _logger.LogInformation(
                "InventoryInitializerService completed — initialized {RegularCount} regular products and {DiscountCount} discount products",
                regularCount, discountCount);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "InventoryInitializerService encountered an error");
        }

        // این Worker فقط یکبار اجرا می‌شود
        _logger.LogInformation("InventoryInitializerService finished — shutting down (one-time execution)");
    }

    private async Task<(int regularCount, int discountCount)> InitializeAllProducts(
        IApplicationDbContext context,
        IInventoryService inventoryService,
        CancellationToken ct)
    {
        var regularCount = 0;
        var discountCount = 0;

        // ── محصولات عادی ──
        // محصولاتی که هنوز InventoryItem برایشان ایجاد نشده
        var existingRegularProductIds = await context.InventoryItems
            .Where(i => !i.IsDeleted && i.ProductId != null)
            .Select(i => i.ProductId!.Value)
            .ToListAsync(ct);

        var regularProducts = await context.Products
            .Where(p => !p.IsDeleted && !existingRegularProductIds.Contains(p.Id))
            .Select(p => new { p.Id, p.Title, p.RemainingCount })
            .ToListAsync(ct);

        _logger.LogInformation("Found {Count} regular products without inventory records", regularProducts.Count);

        foreach (var product in regularProducts)
        {
            if (ct.IsCancellationRequested) break;

            try
            {
                var initialQty = Math.Max(0, product.RemainingCount);

                await inventoryService.InitializeInventoryAsync(
                    product.Id,
                    ProductType.RegularProduct,
                    initialQty,
                    warehouseId: null, // انبار پیش‌فرض (ID=1)
                    lowStockThreshold: 10,
                    ct);

                regularCount++;
                _logger.LogDebug(
                    "Initialized inventory for Regular Product Id={ProductId} ({Title}), Qty={Qty}",
                    product.Id, product.Title, initialQty);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex,
                    "Failed to initialize inventory for Regular Product Id={ProductId} ({Title})",
                    product.Id, product.Title);
            }
        }

        // ── محصولات تخفیفی ──
        var existingDiscountProductIds = await context.InventoryItems
            .Where(i => !i.IsDeleted && i.DiscountProductId != null)
            .Select(i => i.DiscountProductId!.Value)
            .ToListAsync(ct);

        var discountProducts = await context.DiscountProducts
            .Where(p => !p.IsDeleted && !existingDiscountProductIds.Contains(p.Id))
            .Select(p => new { p.Id, p.Title, p.RemainingCount })
            .ToListAsync(ct);

        _logger.LogInformation("Found {Count} discount products without inventory records", discountProducts.Count);

        foreach (var product in discountProducts)
        {
            if (ct.IsCancellationRequested) break;

            try
            {
                var initialQty = Math.Max(0, product.RemainingCount);

                await inventoryService.InitializeInventoryAsync(
                    product.Id,
                    ProductType.DiscountProduct,
                    initialQty,
                    warehouseId: null,
                    lowStockThreshold: 10,
                    ct);

                discountCount++;
                _logger.LogDebug(
                    "Initialized inventory for Discount Product Id={ProductId} ({Title}), Qty={Qty}",
                    product.Id, product.Title, initialQty);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex,
                    "Failed to initialize inventory for Discount Product Id={ProductId} ({Title})",
                    product.Id, product.Title);
            }
        }

        return (regularCount, discountCount);
    }
}
