using Microsoft.AspNetCore.Mvc;
using WebClientTpos.Server.Infrastructure;

namespace WebClientTpos.Server.Controllers;

/// <summary>
/// EN: Storage controller — proxies to StorageService for file uploads/downloads (MinIO).
/// VI: Controller lưu trữ — proxy đến StorageService cho upload/download file (MinIO).
/// </summary>
[ApiController]
[Route("api/bff")]
public class StorageController : ControllerBase
{
    private readonly HttpClient _storage;

    public StorageController(IHttpClientFactory httpClientFactory)
    {
        _storage = httpClientFactory.CreateClient("StorageService");
    }

    /// <summary>
    /// EN: Upload a file (image) to storage.
    /// VI: Upload file (ảnh) lên storage.
    /// </summary>
    [HttpPost("files/upload")]
    [RequestSizeLimit(10_485_760)] // 10MB
    public async Task<IActionResult> UploadFile(IFormFile file, [FromQuery] string? accessLevel = "public")
    {
        using var content = new MultipartFormDataContent();
        using var stream = file.OpenReadStream();
        var streamContent = new StreamContent(stream);
        streamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.ContentType);
        content.Add(streamContent, "file", file.FileName);

        var response = await _storage.PostAsync($"/api/v1/files/upload?accessLevel={accessLevel}", content);
        var body = await response.Content.ReadAsStringAsync();
        return new ContentResult
        {
            StatusCode = (int)response.StatusCode,
            Content = body,
            ContentType = response.Content.Headers.ContentType?.ToString() ?? "application/json"
        };
    }

    /// <summary>
    /// EN: Download a file by ID.
    /// VI: Tải file theo ID.
    /// </summary>
    [HttpGet("files/{fileId:guid}/download")]
    public async Task<IActionResult> DownloadFile(Guid fileId)
    {
        var response = await _storage.GetAsync($"/api/v1/files/{fileId}/download");
        if (!response.IsSuccessStatusCode)
        {
            var errBody = await response.Content.ReadAsStringAsync();
            return new ContentResult
            {
                StatusCode = (int)response.StatusCode,
                Content = errBody,
                ContentType = "application/json"
            };
        }
        var fileStream = await response.Content.ReadAsStreamAsync();
        var contentType = response.Content.Headers.ContentType?.ToString() ?? "application/octet-stream";
        var fileName = response.Content.Headers.ContentDisposition?.FileName?.Trim('"') ?? "file";
        return File(fileStream, contentType, fileName);
    }

    /// <summary>
    /// EN: List files with pagination and optional search.
    ///     Returns empty result on auth failure (StorageService JWT validation in local dev).
    /// VI: Liệt kê files có phân trang và tìm kiếm tùy chọn.
    ///     Trả kết quả rỗng khi lỗi auth (StorageService JWT validation khi chạy local dev).
    /// </summary>
    [HttpGet("files")]
    public async Task<IActionResult> GetFiles([FromQuery] int skip = 0, [FromQuery] int take = 50, [FromQuery] string? search = null)
    {
        var qs = $"?skip={skip}&take={take}";
        if (!string.IsNullOrEmpty(search)) qs += $"&search={Uri.EscapeDataString(search)}";
        var response = await _storage.GetAsync($"/api/v1/files{qs}");
        if (response.StatusCode is System.Net.HttpStatusCode.Unauthorized or System.Net.HttpStatusCode.Forbidden)
            return Ok(new { success = true, data = new { files = Array.Empty<object>(), totalCount = 0 } });
        return await response.ToActionResultAsync();
    }

    /// <summary>
    /// EN: Delete a file by ID.
    /// VI: Xóa file theo ID.
    /// </summary>
    [HttpDelete("files/{fileId:guid}")]
    public Task<IActionResult> DeleteFile(Guid fileId) =>
        _storage.DeleteAsync($"/api/v1/files/{fileId}").ProxyAsync();

    /// <summary>
    /// EN: Get a pre-signed download URL for a file.
    /// VI: Lấy URL tải file có chữ ký.
    /// </summary>
    [HttpGet("files/{fileId:guid}/download-url")]
    public Task<IActionResult> GetDownloadUrl(Guid fileId) =>
        _storage.GetAsync($"/api/v1/files/{fileId}/download-url").ProxyAsync();

    /// <summary>
    /// EN: List folders, optionally filtered by parent.
    ///     Returns empty array on auth failure (StorageService JWT validation in local dev).
    /// VI: Liệt kê thư mục, lọc theo thư mục cha nếu có.
    ///     Trả array rỗng khi lỗi auth (StorageService JWT validation khi chạy local dev).
    /// </summary>
    [HttpGet("folders")]
    public async Task<IActionResult> GetFolders([FromQuery] Guid? parentId = null)
    {
        var qs = parentId.HasValue ? $"?parentId={parentId}" : "";
        var response = await _storage.GetAsync($"/api/v1/storage/folders{qs}");
        if (response.StatusCode is System.Net.HttpStatusCode.Unauthorized or System.Net.HttpStatusCode.Forbidden)
            return Ok(new { success = true, data = Array.Empty<object>() });
        return await response.ToActionResultAsync();
    }

    /// <summary>
    /// EN: Create a folder.
    /// VI: Tạo thư mục.
    /// </summary>
    [HttpPost("folders")]
    public Task<IActionResult> CreateFolder([FromBody] System.Text.Json.JsonElement body) =>
        _storage.PostAsJsonAsync("/api/v1/storage/folders", body).ProxyAsync();

    /// <summary>
    /// EN: Delete a folder by ID.
    /// VI: Xóa thư mục theo ID.
    /// </summary>
    [HttpDelete("folders/{folderId:guid}")]
    public Task<IActionResult> DeleteFolder(Guid folderId) =>
        _storage.DeleteAsync($"/api/v1/storage/folders/{folderId}").ProxyAsync();
}
