using System.ComponentModel.DataAnnotations;
using Asp.Versioning;
using Baya.Application.Features.Bnpl.Commands.RevertBnplOrder;
using Baya.Application.Features.Bnpl.Commands.SettleBnplOrder;
using Baya.Application.Features.Bnpl.Commands.VerifyBnplOrder;
using Baya.Application.Features.Bnpl.Queries.GetBnplOrderStatus;
using Baya.Application.Models.Bnpl;
using Baya.Infrastructure.Identity.Identity.PermissionManager;
using Baya.WebFramework.Attributes;
using Baya.WebFramework.BaseController;
using Baya.WebFramework.ServiceConfiguration;
using Mediator;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;

namespace Baya.Web.Api.Controllers.V1;

/// <summary>
/// Admin-only BNPL operations console: manually drive verify/settle (also driven by the provider callback) and
/// the payout-/refund-sensitive full revert, plus read an order. The revert reverses through the provider only
/// (customer ↔ provider ↔ Balinyaar) and surfaces the async ~7–10-business-day customer ETA. Rate-limited as
/// money endpoints.
/// </summary>
[ApiVersion("1")]
[ApiController]
[Route("api/v{version:apiVersion}/admin_bnpl")]
[Authorize(ConstantPolicies.DynamicPermission)]
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
[Display(Description = "Admin BNPL verify/settle/revert + order status")]
public sealed class AdminBnplController(ISender sender) : BaseController
{
    [HttpPost("{id}/[action]")]
    [ProducesOkApiResponseType<bool>]
    public async Task<IActionResult> Verify(long id, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(new VerifyBnplOrderCommand(id), cancellationToken));

    [HttpPost("{id}/[action]")]
    [ProducesOkApiResponseType<bool>]
    public async Task<IActionResult> Settle(long id, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(new SettleBnplOrderCommand(id), cancellationToken));

    [HttpPost("{id}/[action]")]
    [ProducesOkApiResponseType<RevertBnplResult>]
    public async Task<IActionResult> Revert(long id, RevertBnplBody body, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(
            new RevertBnplOrderCommand(id, body.RefundPercentage, body.TicketId, body.ReasonNotes), cancellationToken));

    [HttpGet("{id}")]
    [ProducesOkApiResponseType<BnplOrderStatusDto>]
    public async Task<IActionResult> Get(long id, CancellationToken cancellationToken)
        => OperationResult(await sender.Send(new GetBnplOrderStatusQuery(id, AdminView: true), cancellationToken));

    /// <summary>The revert body (the order id comes from the route). Omit <c>refund_percentage</c> for a full revert.</summary>
    public record RevertBnplBody(decimal? RefundPercentage, long? TicketId, string? ReasonNotes);
}
