using System.Security.Claims;
using Books.Api.Authorization;
using Books.Api.Commands.Attachments;
using Books.Api.Domain;
using Books.Api.Domain.Attachments;
using Books.Api.EventFlow.ReadModels;
using Books.Api.EventFlow.Repositories;
using Books.Api.Infrastructure.FileStorage;
using EventFlow;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Books.Api.Controllers;
///
/// REST API for attachment (bilag) file operations.
/// GraphQL doesn't handle file uploads well, so we use REST for this.
///
[ApiController]
[Route("api/attachments")]
[Authorize]
public class AttachmentController(
ICommandBus commandBus,
IAttachmentRepository attachmentRepository,
IFileStorageService fileStorage,
ICompanyAccessService companyAccess,
ILogger logger) : ControllerBase
{
///
/// Upload one or more attachments for a company.
///
/// Company ID
/// Optional draft ID to link attachments to
/// Files to upload
[HttpPost("upload")]
[RequestSizeLimit(50 * 1024 * 1024)] // 50MB max total
public async Task Upload(
[FromQuery] string companyId,
[FromQuery] string? draftId,
[FromForm] List files,
CancellationToken cancellationToken)
{
// Validate company access
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new { error = "NOT_AUTHENTICATED", message = "You must be authenticated to upload attachments" });
}
// Check if user can write (Accountant or Owner role)
var canWrite = await companyAccess.CanWriteAsync(companyId, cancellationToken);
if (!canWrite)
{
return Forbid();
}
if (files.Count == 0)
{
return BadRequest(new { error = "NO_FILES", message = "No files provided" });
}
var results = new List