using Dapper;
using Microsoft.Extensions.Logging;
using Quartz;
using SIGCM2.Infrastructure.Persistence;

namespace SIGCM2.Infrastructure.Audit.Jobs;

/// <summary>
/// UDT-010 (#REQ-AUD-6, #REQ-SEC-5) — annual retention enforcement:
/// - Purges rows from dbo.AuditEvent older than 10 years.
/// - Purges rows from dbo.SecurityEvent older than 5 years.
/// - Temporal history tables are purged automatically by the engine via
///   HISTORY_RETENTION_PERIOD = 10 YEARS configured in V010.
/// - Intended schedule: cron '0 0 3 1 1 ?' (Jan 1 at 03:00 UTC).
///
/// Row-based DELETE is the conservative choice for the first generation of this
/// job — avoids requiring filegroup switching logic. When volumes warrant, the
/// job can be upgraded to SWITCH OUT + DROP for partition-level drop.
/// </summary>
[DisallowConcurrentExecution]
public sealed class AuditRetentionEnforcerJob : IJob
{
    public const string CronSchedule = "0 0 3 1 1 ?";

    private readonly SqlConnectionFactory _factory;
    private readonly ILogger<AuditRetentionEnforcerJob> _logger;
    private readonly TimeProvider _timeProvider;

    public AuditRetentionEnforcerJob(SqlConnectionFactory factory, ILogger<AuditRetentionEnforcerJob> logger, TimeProvider timeProvider)
    {
        _factory = factory;
        _logger = logger;
        _timeProvider = timeProvider;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        var ct = context.CancellationToken;
        await using var conn = _factory.CreateConnection();
        await conn.OpenAsync(ct);

        var now = _timeProvider.GetUtcNow().UtcDateTime;
        var auditCutoff = now.AddYears(-10);
        var securityCutoff = now.AddYears(-5);

        var auditDeleted = await conn.ExecuteAsync(
            "DELETE FROM dbo.AuditEvent WHERE OccurredAt < @Cutoff;",
            new { Cutoff = auditCutoff });

        var securityDeleted = await conn.ExecuteAsync(
            "DELETE FROM dbo.SecurityEvent WHERE OccurredAt < @Cutoff;",
            new { Cutoff = securityCutoff });

        _logger.LogInformation(
            "AuditRetentionEnforcerJob completed — AuditEvent purged {AuditDeleted} rows (< {AuditCutoff:yyyy-MM-dd}), " +
            "SecurityEvent purged {SecurityDeleted} rows (< {SecurityCutoff:yyyy-MM-dd})",
            auditDeleted, auditCutoff, securityDeleted, securityCutoff);
    }
}
