using Microsoft.AspNetCore.Hosting;
using NexusReader.Application.Abstractions.Services;

namespace NexusReader.Infrastructure.Services;

/// <summary>
/// Infrastructure implementation of book storage using local filesystem.
/// All paths returned are relative to the web root.
/// </summary>
public class BookStorageService : IBookStorageService
{
    private readonly IWebHostEnvironment _environment;

    public BookStorageService(IWebHostEnvironment environment)
    {
        _environment = environment;
    }

    public async Task<string> SaveEbookAsync(byte[] data, string fileName)
    {
        using var stream = new MemoryStream(data);
        return await SaveEbookAsync(stream, fileName);
    }

    public async Task<string> SaveEbookAsync(Stream data, string fileName)
    {
        var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads");
        EnsureDirectoryExists(uploadsFolder);

        var uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
        var filePath = Path.Combine(uploadsFolder, uniqueFileName);
        
        using (var fileStream = new FileStream(filePath, FileMode.Create))
        {
            await data.CopyToAsync(fileStream);
        }
        
        // Use forward-slash explicitly: Path.Combine produces backslashes on Windows
        // which would cause 404s when stored as web-relative paths.
        return $"uploads/{uniqueFileName}";
    }

    public async Task<string?> SaveCoverAsync(byte[] data, string fileName)
    {
        if (data == null || data.Length == 0) return null;
        using var stream = new MemoryStream(data);
        return await SaveCoverAsync(stream, fileName);
    }

    public async Task<string?> SaveCoverAsync(Stream data, string fileName)
    {
        var coversFolder = Path.Combine(_environment.WebRootPath, "covers");
        EnsureDirectoryExists(coversFolder);

        var uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
        var filePath = Path.Combine(coversFolder, uniqueFileName);
        
        using (var fileStream = new FileStream(filePath, FileMode.Create))
        {
            await data.CopyToAsync(fileStream);
        }
        
        return $"covers/{uniqueFileName}";
    }

    private void EnsureDirectoryExists(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }
}
