using Microsoft.Extensions.Configuration;
using SolutionErp.Application.Common.Interfaces;

namespace SolutionErp.Infrastructure.Storage;

public class LocalFileStorage : IFileStorage
{
    private readonly string _root;

    public LocalFileStorage(IConfiguration config)
    {
        var root = config["Uploads:RootPath"] ?? "uploads";
        // Make absolute (relative paths resolve against ContentRoot)
        _root = Path.GetFullPath(root);
        Directory.CreateDirectory(_root);
    }

    private string Full(string rel)
    {
        var full = Path.GetFullPath(Path.Combine(_root, rel));
        // Guard against path traversal — resolved full path must stay inside root
        if (!full.StartsWith(_root, StringComparison.OrdinalIgnoreCase))
            throw new UnauthorizedAccessException("Path traversal blocked.");
        return full;
    }

    public async Task<string> SaveAsync(string relativePath, Stream content, CancellationToken ct = default)
    {
        var full = Full(relativePath);
        Directory.CreateDirectory(Path.GetDirectoryName(full)!);
        await using var fs = File.Create(full);
        await content.CopyToAsync(fs, ct);
        return relativePath.Replace('\\', '/');
    }

    public Task<Stream> OpenReadAsync(string relativePath, CancellationToken ct = default)
    {
        var full = Full(relativePath);
        if (!File.Exists(full)) throw new FileNotFoundException(relativePath);
        return Task.FromResult<Stream>(File.OpenRead(full));
    }

    public Task DeleteAsync(string relativePath, CancellationToken ct = default)
    {
        var full = Full(relativePath);
        if (File.Exists(full)) File.Delete(full);
        return Task.CompletedTask;
    }

    public bool Exists(string relativePath) => File.Exists(Full(relativePath));
}
