using Microsoft.EntityFrameworkCore;
using Watcher.Data;

namespace Watcher.Services;

public class MetricCleanupService : BackgroundService
{
    private readonly ILogger<MetricCleanupService> _logger;
    private readonly IServiceProvider _serviceProvider;
    private readonly int _retentionDays;
    private readonly int _checkIntervalHours;
    private readonly bool _enabled;

    public MetricCleanupService(
        ILogger<MetricCleanupService> logger,
        IServiceProvider serviceProvider,
        IConfiguration configuration)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;

        // Konfiguration aus Environment Variablen laden
        _retentionDays = int.TryParse(
            configuration["DataRetention:MetricRetentionDays"] ??
            Environment.GetEnvironmentVariable("METRIC_RETENTION_DAYS"),
            out var days) ? days : 30; // Default: 30 Tage

        _checkIntervalHours = int.TryParse(
            configuration["DataRetention:CleanupIntervalHours"] ??
            Environment.GetEnvironmentVariable("METRIC_CLEANUP_INTERVAL_HOURS"),
            out var hours) ? hours : 24; // Default: 24 Stunden

        _enabled = bool.TryParse(
            configuration["DataRetention:Enabled"] ??
            Environment.GetEnvironmentVariable("METRIC_CLEANUP_ENABLED"),
            out var enabled) ? enabled : true; // Default: aktiviert

        _logger.LogInformation(
            "MetricCleanupService konfiguriert: Enabled={Enabled}, RetentionDays={Days}, IntervalHours={Hours}",
            _enabled, _retentionDays, _checkIntervalHours);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (!_enabled)
        {
            _logger.LogInformation("MetricCleanupService ist deaktiviert.");
            return;
        }

        // Warte 1 Minute nach Start, bevor der erste Cleanup läuft
        await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);

        var timer = new PeriodicTimer(TimeSpan.FromHours(_checkIntervalHours));

        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            try
            {
                await CleanupOldMetricsAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Fehler beim Cleanup alter Metriken.");
            }

            // Offset nach Cleanup
            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }

    private async Task CleanupOldMetricsAsync()
    {
        _logger.LogInformation("Starte Metric Cleanup für Daten älter als {Days} Tage...", _retentionDays);

        using var scope = _serviceProvider.CreateScope();
        var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

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

        try
        {
            // Anzahl der zu löschenden Einträge ermitteln
            var countToDelete = await context.Metrics
                .Where(m => m.Timestamp < cutoffDate)
                .CountAsync();

            if (countToDelete == 0)
            {
                _logger.LogInformation("Keine alten Metriken zum Löschen gefunden.");
                return;
            }

            _logger.LogInformation("Lösche {Count} Metriken vor {Date}...", countToDelete, cutoffDate);

            // Metriken löschen
            var deletedCount = await context.Metrics
                .Where(m => m.Timestamp < cutoffDate)
                .ExecuteDeleteAsync();

            _logger.LogInformation(
                "Metric Cleanup abgeschlossen: {DeletedCount} Einträge gelöscht.",
                deletedCount);

            // Optional: ContainerMetrics auch bereinigen
            var containerMetricsCount = await context.ContainerMetrics
                .Where(cm => cm.Timestamp < cutoffDate)
                .CountAsync();

            if (containerMetricsCount > 0)
            {
                var deletedContainerMetrics = await context.ContainerMetrics
                    .Where(cm => cm.Timestamp < cutoffDate)
                    .ExecuteDeleteAsync();

                _logger.LogInformation(
                    "ContainerMetrics Cleanup: {DeletedCount} Einträge gelöscht.",
                    deletedContainerMetrics);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Fehler beim Löschen alter Metriken aus der Datenbank.");
            throw;
        }
    }
}
