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

namespace RealCV.Infrastructure.Jobs;

/// <summary>
/// GDPR compliance job that automatically deletes old CV check data
/// based on configured retention period.
/// </summary>
public sealed class DataRetentionJob
{
    private readonly ApplicationDbContext _dbContext;
    private readonly IFileStorageService _fileStorageService;
    private readonly ILogger<DataRetentionJob> _logger;
    private readonly int _retentionDays;

    public DataRetentionJob(
        ApplicationDbContext dbContext,
        IFileStorageService fileStorageService,
        IConfiguration configuration,
        ILogger<DataRetentionJob> logger)
    {
        _dbContext = dbContext;
        _fileStorageService = fileStorageService;
        _logger = logger;
        _retentionDays = configuration.GetValue<int>("DataRetention:CVCheckRetentionDays", 30);
    }

    public async Task ExecuteAsync(CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("Starting GDPR data retention job (retention: {Days} days)", _retentionDays);

        try
        {
            var cutoffDate = DateTime.UtcNow.AddDays(-_retentionDays);

            // Find old completed CV checks that should be deleted
            var oldChecks = await _dbContext.CVChecks
                .Include(c => c.Flags)
                .Where(c => c.CompletedAt != null && c.CompletedAt < cutoffDate)
                .Where(c => c.Status == CheckStatus.Completed || c.Status == CheckStatus.Failed)
                .ToListAsync(cancellationToken);

            if (oldChecks.Count == 0)
            {
                _logger.LogInformation("No CV checks older than {Days} days found for deletion", _retentionDays);
                return;
            }

            _logger.LogInformation("Found {Count} CV checks older than {Days} days for deletion", oldChecks.Count, _retentionDays);

            var deletedCount = 0;
            var fileDeletedCount = 0;

            foreach (var check in oldChecks)
            {
                try
                {
                    // Delete any remaining files (should already be deleted after processing, but be thorough)
                    if (!string.IsNullOrWhiteSpace(check.BlobUrl))
                    {
                        try
                        {
                            await _fileStorageService.DeleteAsync(check.BlobUrl);
                            fileDeletedCount++;
                            _logger.LogDebug("Deleted orphaned file for CV check {CheckId}", check.Id);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, "Failed to delete file for CV check {CheckId}", check.Id);
                        }
                    }

                    // Delete associated flags
                    _dbContext.CVFlags.RemoveRange(check.Flags);

                    // Delete the CV check record
                    _dbContext.CVChecks.Remove(check);
                    deletedCount++;

                    _logger.LogDebug("Marked CV check {CheckId} for deletion (created: {Created})",
                        check.Id, check.CreatedAt);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing CV check {CheckId} for deletion", check.Id);
                }
            }

            await _dbContext.SaveChangesAsync(cancellationToken);

            _logger.LogInformation(
                "GDPR data retention job completed. Deleted {DeletedCount} CV checks and {FileCount} orphaned files",
                deletedCount, fileDeletedCount);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error in GDPR data retention job");
            throw;
        }
    }
}
