using System.ComponentModel.DataAnnotations;
using Asp.Versioning;
using Baya.Application.Features.Reviews.Commands.AttachReviewTags;
using Baya.Application.Features.Reviews.Commands.ModerateReview;
using Baya.Application.Models.Reviews;
using Baya.Infrastructure.Identity.Identity.PermissionManager;
using Baya.WebFramework.Attributes;
using Baya.WebFramework.BaseController;
using Mediator;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Baya.Web.Api.Controllers.V1;

/// <summary>
/// Review write surface. Tagging a review is for its author (or a moderator, enforced in the handler); the
/// moderation transition is admin/moderator-only (the narrower <see cref="ConstantPolicies.DynamicPermission"/>
/// policy overrides the controller-level authorize).
/// </summary>
[ApiVersion("1")]
[ApiController]
[Route("api/v{version:apiVersion}/reviews")]
[Authorize]
[Display(Description = "Review tagging (owner/moderator) and moderation transitions (admin)")]
public sealed class ReviewsController(ISender sender) : BaseController
{
    [HttpPost("{reviewId}/tags")]
    [ProducesOkApiResponseType<ReviewTagsResult>]
    public async Task<IActionResult> Tags(long reviewId, AttachReviewTagsBody body, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(new AttachReviewTagsCommand(reviewId, body.TagCodes), cancellationToken));

    [HttpPatch("{reviewId}/status")]
    [Authorize(ConstantPolicies.DynamicPermission)]
    [ProducesOkApiResponseType<ModerateReviewResult>]
    public async Task<IActionResult> Status(long reviewId, ModerateReviewBody body, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(new ModerateReviewCommand(reviewId, body.Action, body.Reason), cancellationToken));

    /// <summary>Tag-attach body (the review id comes from the route).</summary>
    public record AttachReviewTagsBody(IReadOnlyList<string> TagCodes);

    /// <summary>Moderation body (the review id comes from the route): <c>publish</c>|<c>hide</c>|<c>reject</c>|<c>unpublish</c>.</summary>
    public record ModerateReviewBody(string Action, string? Reason);
}
