using Microsoft.Extensions.Logging;

namespace TeleWave.Infrastructure.Media;

/// <summary>
/// Уборка перевалочного каталога <c>uploads/</c>: удаляет файлы, которых не касались дольше порога.
/// После регистрации ассета файл уходит в <c>originals/</c>, а токен загрузки нигде не хранится —
/// значит, всё залежавшееся в <c>uploads/</c> это след оборванной заливки или аварийного рестарта,
/// и подобрать его некому.
/// </summary>
public static class UploadsCleaner
{
    /// <summary>
    /// Один проход. Порог считается от времени последней записи, а не создания: идущая многочасовая
    /// заливка правит файл и под него не попадает.
    /// </summary>
    public static void Sweep(MediaPathResolver paths, TimeSpan retention, ILogger logger)
    {
        try
        {
            if (!Directory.Exists(paths.UploadsDir))
                return;

            var deadline = DateTime.UtcNow - retention;
            foreach (var path in Directory.EnumerateFiles(paths.UploadsDir))
                DeleteIfStale(path, deadline, logger);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Ошибка уборки uploads/");
        }
    }

    private static void DeleteIfStale(string path, DateTime deadline, ILogger logger)
    {
        try
        {
            var file = new FileInfo(path);
            if (!file.Exists || file.LastWriteTimeUtc > deadline)
                return;

            // Метрики снимаем до удаления: после него FileInfo их уже не отдаст.
            var size = file.Length;
            var lastWrite = file.LastWriteTimeUtc;
            file.Delete();
            logger.LogInformation(
                "Удалён брошенный файл загрузки {Name} ({Size} байт, последняя запись {LastWrite:u})",
                file.Name,
                size,
                lastWrite
            );
        }
        catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
        {
            // Файл занят или права не те — попробуем на следующем тике.
            logger.LogWarning(ex, "Не удалось удалить файл загрузки {Path}", path);
        }
    }
}
