using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.Storage.Abstractions;
using TakeoutSaaS.Application.Storage.Contracts;
using TakeoutSaaS.Application.Storage.Extensions;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.MiniApi.Contracts.Requests;

namespace TakeoutSaaS.MiniApi.Controllers;

/// <summary>
/// 小程序文件上传。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/mini/v{version:apiVersion}/files")]
public sealed class FilesController(IFileStorageService fileStorageService) : BaseApiController
{
    /// <summary>
    /// 上传图片或文件。
    /// </summary>
    /// <param name="request">表单请求，包含文件与类型。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>上传结果，包含访问链接等信息。</returns>
    [HttpPost("upload")]
    [Consumes("multipart/form-data")]
    [RequestFormLimits(MultipartBodyLengthLimit = 30 * 1024 * 1024)]
    [ProducesResponseType(typeof(ApiResponse<FileUploadResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<FileUploadResponse>), StatusCodes.Status400BadRequest)]
    public async Task<ApiResponse<FileUploadResponse>> Upload([FromForm] FileUploadFormRequest request, CancellationToken cancellationToken)
    {
        // 1. 校验文件有效性
        if (request.File is null || request.File.Length == 0)
        {
            return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "文件不能为空");
        }
        // 2. 解析上传类型
        if (!UploadFileTypeParser.TryParse(request.Type, out var uploadType))
        {
            return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "上传类型不合法");
        }
        // 3. 提取请求来源
        var origin = Request.Headers["Origin"].FirstOrDefault() ?? Request.Headers["Referer"].FirstOrDefault();
        await using var stream = request.File.OpenReadStream();
        // 4. 调用存储服务执行上传
        var result = await fileStorageService.UploadAsync(
            new UploadFileRequest(uploadType, stream, request.File.FileName, request.File.ContentType ?? string.Empty, request.File.Length, origin),
            cancellationToken);
        // 5. 返回上传结果
        return ApiResponse<FileUploadResponse>.Ok(result);
    }
}
