namespace PSLauncher.Core.Lan;

/// <summary>
/// Une entrée du cache local des ZIPs PROSERVE déjà téléchargés. Le SHA-256 est
/// stocké dans un fichier sidecar <c>.sha256</c> à côté du ZIP — calculé une seule
/// fois au moment du Promote (déjà connu via le manifest signé), pas re-hashé à
/// chaque ListCached() (un md5 sur 14 Go prendrait 30s-3min).
/// </summary>
public sealed record CachedZip(string Version, string Path, long SizeBytes, string Sha256, DateTime ModifiedUtc);

/// <summary>
/// Cache local des ZIPs PROSERVE. Sert deux usages :
/// 1. Permet à un PC en mode serveur LAN de servir les ZIPs aux peers du LAN.
/// 2. Permet le rollback ou la réinstall instantanée d'une version sans re-DL.
///
/// Stockage : <c>%LocalAppData%\PSLauncher\downloads\proserve-{version}.zip</c>
/// (mêmechemin que les .partial du DownloadStateStore, le ZIP final y atterrit
/// déjà après VerifyAndFinalizeAsync). Le sidecar <c>.sha256</c> contient le
/// hash en hex pour servir les peers sans re-calcul.
///
/// Pruning : conserve les <c>keepLatest</c> plus récents par mtime, MAIS ne
/// supprime jamais un ZIP dont la version est encore installée (cf.
/// <see cref="PSLauncher.Core.Installations.IInstallationRegistry.Scan"/>).
/// </summary>
public interface IZipCacheStore
{
    /// <summary>Chemin canonique du ZIP pour cette version (qu'il existe ou non).</summary>
    string GetCachedZipPath(string version);

    /// <summary>Vrai si on a un ZIP + sidecar SHA-256 valide pour cette version.</summary>
    bool TryGetCachedEntry(string version, out CachedZip entry);

    /// <summary>
    /// Promeut un ZIP final (post-VerifyAndFinalizeAsync) au statut "caché".
    /// Si <paramref name="srcPath"/> est déjà au bon endroit (= GetCachedZipPath),
    /// no-op sur le fichier — écrit juste le sidecar SHA. Sinon, déplace.
    /// </summary>
    Task PromoteAsync(string srcPath, string version, string sha256, CancellationToken ct);

    /// <summary>
    /// Supprime les ZIPs hors top-N par mtime. Skip silencieusement les versions
    /// encore installées localement (peu importe leur âge).
    /// </summary>
    Task PruneAsync(int keepLatest, CancellationToken ct);

    /// <summary>Liste tous les ZIPs cachés valides (avec sidecar SHA présent).</summary>
    IReadOnlyList<CachedZip> ListCached();

    /// <summary>
    /// Supprime AGRESSIVEMENT le ZIP + sidecar SHA d'une version donnée du cache
    /// local, peu importe son âge ou si la version est encore installée. Utilisé
    /// dans deux cas :
    /// <list type="number">
    ///   <item>Échec de vérif SHA après DL : on évacue l'éventuel ZIP cache de
    ///     la version concernée pour ne pas servir du contenu obsolète aux peers
    ///     LAN (et pour forcer un re-DL complet au prochain Install).</item>
    ///   <item>Action manuelle "Forcer re-téléchargement" depuis le menu UI :
    ///     l'opérateur veut purger explicitement (typiquement quand la source
    ///     OVH est en cache CDN stale et qu'il a besoin d'un re-DL frais).</item>
    /// </list>
    /// Best-effort : log les erreurs I/O mais ne throw pas.
    /// </summary>
    Task InvalidateAsync(string version, CancellationToken ct);
}
