namespace TeleWave.Application.Common.Interfaces;

/// <summary>
/// Части хранилища, которые считаются отдельно. Это не «папки», а ответ на вопрос «чем занят диск»:
/// сегменты программ и сегменты заставок лежат в одном каталоге, но растут по разным причинам,
/// и администратору важно видеть их порознь.
/// </summary>
public enum StorageArea
{
    /// <summary>HLS-сегменты программ — обычно это почти весь объём.</summary>
    Assets = 0,

    /// <summary>HLS-сегменты отрендеренных заставок.</summary>
    BumperAssets = 1,

    /// <summary>Исходники, оставленные после нарезки (<c>Storage:KeepOriginals</c>).</summary>
    Originals = 2,

    /// <summary>Автоматический inbox — то, что ещё не разобрано сканером.</summary>
    Inbox = 3,

    /// <summary>Ручной inbox — то, что админ забирает в шоу сам.</summary>
    ManualInbox = 4,

    /// <summary>Перевалочный каталог заливок: всё, что здесь залежалось, — след оборванной загрузки.</summary>
    Uploads = 5,

    /// <summary>Звук и фоны блоков заставок (сырые файлы, не нарезка).</summary>
    BumperSources = 6,

    /// <summary>Общий реестр изображений: постеры, кадры, логотипы.</summary>
    Images = 7,

    /// <summary>Всё прочее под корнем хранилища — обычно ноль, а если нет, то это и надо увидеть.</summary>
    Other = 8,
}

/// <param name="Bytes">Объём области, байт.</param>
/// <param name="Files">Число файлов — по нему видно, что «пусто» и «много мелочи» это разные беды.</param>
public sealed record StorageAreaUsage(StorageArea Area, long Bytes, int Files);

/// <param name="RootPath">Корень хранилища — на сервере их может быть несколько, и надо видеть, о каком речь.</param>
/// <param name="VolumeTotalBytes">Размер тома целиком; 0 — файловая система не отдала метрику.</param>
/// <param name="VolumeFreeBytes">Свободно на томе. Свободное место делится со всем, что есть на диске.</param>
/// <param name="MinFreeSpaceBytes">Порог, ниже которого загрузка отклоняется; едет вместе с цифрами тома, чтобы их было с чем сравнить.</param>
/// <param name="ComputedAt">Когда посчитано: обход дерева кэшируется, и возраст цифры надо показывать.</param>
public sealed record StorageUsage(
    string RootPath,
    long VolumeTotalBytes,
    long VolumeFreeBytes,
    long StorageBytes,
    int StorageFiles,
    long MinFreeSpaceBytes,
    IReadOnlyList<StorageAreaUsage> Areas,
    DateTimeOffset ComputedAt
);

/// <summary>
/// Порт подсчёта занятого места. Размеров в БД нет и не будет: правда о диске лежит на диске,
/// а любое дублирование в таблицах разошлось бы с ней при первой же ручной правке файлов.
///
/// Обход дерева стоит дорого (сегментов — сотни тысяч), поэтому результат кэшируется реализацией,
/// а <paramref name="refresh"/> — это явная кнопка «пересчитать» в админке.
/// </summary>
public interface IStorageInspector
{
    Task<StorageUsage> InspectAsync(
        IReadOnlySet<Guid> generatedAssetIds,
        bool refresh,
        CancellationToken cancellationToken
    );
}
