using foodmarket.Domain.Inventory;
using foodmarket.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Api.Background;

/// <summary>Hangfire-джобы для регулярной чистки исторических данных:
/// <c>StockMovement</c> старше 2 лет (компенсирует разрастание таблицы при
/// большом обороте продаж), <c>SuperAdminAuditLog</c> старше 90 дней. Период
/// можно поменять через конфиг <c>Hangfire:Retention:*</c>.
///
/// Реализованы как scoped-сервис, чтобы Hangfire разрешил <see cref="AppDbContext"/>
/// и фильтр tenant'а корректно (контекст НЕТ tenant'а — но cleanup идёт без
/// tenant-фильтра через IgnoreQueryFilters, потому что это межтенантная задача).</summary>
public class HousekeepingJobs
{
    private readonly AppDbContext _db;
    private readonly IConfiguration _cfg;
    private readonly ILogger<HousekeepingJobs> _log;

    public HousekeepingJobs(AppDbContext db, IConfiguration cfg, ILogger<HousekeepingJobs> log)
    {
        _db = db;
        _cfg = cfg;
        _log = log;
    }

    /// <summary>Удаляет <see cref="StockMovement"/> старше N дней (по умолчанию 730).
    /// Stock-инвариант (Stock.Quantity ≡ Σ StockMovement) ломается на удалённых
    /// записях, поэтому удаляем ТОЛЬКО действительно старые движения — там
    /// невозможно сослаться через unpost (документы уже закрыты).
    ///
    /// Возвращает количество удалённых строк (для логов/мониторинга).</summary>
    public async Task<int> PruneStockMovementsAsync(CancellationToken ct = default)
    {
        var days = _cfg.GetValue("Hangfire:Retention:StockMovementDays", 730);
        var threshold = DateTime.UtcNow.AddDays(-days);

        var deleted = await _db.StockMovements
            .IgnoreQueryFilters()
            .Where(m => m.OccurredAt < threshold)
            .ExecuteDeleteAsync(ct);
        _log.LogInformation("Hangfire/PruneStockMovements: удалено {Count} движений старше {Threshold:O}",
            deleted, threshold);
        return deleted;
    }

    /// <summary>Удаляет <c>super_admin_audit_log</c> старше N дней (по умолчанию 90).
    /// SuperAdmin'ские действия в каждой орге — отдельный аудит, для compliance
    /// храним недолго (квартал) и зачищаем.</summary>
    public async Task<int> PruneAuditLogAsync(CancellationToken ct = default)
    {
        var days = _cfg.GetValue("Hangfire:Retention:AuditLogDays", 90);
        var threshold = DateTime.UtcNow.AddDays(-days);

        var deleted = await _db.SuperAdminAuditLogs
            .IgnoreQueryFilters()
            .Where(a => a.CreatedAt < threshold)
            .ExecuteDeleteAsync(ct);
        _log.LogInformation("Hangfire/PruneAuditLog: удалено {Count} записей старше {Threshold:O}",
            deleted, threshold);
        return deleted;
    }
}
