using CoreUpload.Events;
using CoreUpload.Providers;

namespace CoreUpload.Demos;

/// <summary>
/// The save half of the upload story, wired for the whole demo app.
///
/// <para>Uploads land in a TEMPORARY store first (swept after
/// <c>CoreUploadOptions.TempFileExpiry</c>); nothing is permanent until your code
/// makes it so. This handler is that code: it runs after every successful upload
/// and copies the file to <c>wwwroot/uploads</c> under a server-generated name.
/// Without a handler like this, an upload "succeeds" and then quietly disappears
/// - the single most-reported integration surprise.</para>
/// </summary>
public sealed class SaveUploadsToDisk : IUploadEventHandler
{
    private readonly IUploaderProvider _provider;
    private readonly IWebHostEnvironment _env;
    private readonly ILogger<SaveUploadsToDisk> _logger;

    public SaveUploadsToDisk(IUploaderProvider provider, IWebHostEnvironment env, ILogger<SaveUploadsToDisk> logger)
    {
        _provider = provider;
        _env = env;
        _logger = logger;
    }

    public async Task OnFileUploadedAsync(FileUploadedEvent e, CancellationToken ct = default)
    {
        var uploadsRoot = Path.Combine(_env.WebRootPath, "uploads");
        Directory.CreateDirectory(uploadsRoot);

        // Never build the destination from the client's file name - it is attacker
        // -controlled text. Keep only the extension.
        var savedName = Guid.NewGuid().ToString("N") + Path.GetExtension(e.FileName ?? string.Empty);

        await _provider.CopyToAsync(e.FileGuid, Path.Combine(uploadsRoot, savedName), ct);

        _logger.LogInformation("Saved upload {Original} as /uploads/{Saved} ({Bytes} bytes)",
            e.FileName, savedName, e.FileSize);
    }
}
