using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using Asp.Versioning;
using Baya.Application.Features.Payouts.Commands.ReconcilePayoutBatch;
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>
/// The async PAYA/SATNA payout <b>reconciliation callback</b> (refinement-phase-8, 6.3). The real bank rail
/// accepts a payout as <c>submitted</c> and calls back later with the settled outcome, flipping each payout
/// <c>submitted → paid/failed</c> (the mock rail collapsed this into the submit). Authenticated by
/// <b>signature</b>, not a user session, so it is anonymous to the auth pipeline; the callback is HMAC-verified and
/// idempotent (a replayed callback re-driving an already-settled payout is a no-op). Shares the deliberate
/// bursty-tolerant <c>webhook</c> rate policy with the PSP/BNPL callbacks.
/// </summary>
[ApiVersion("1")]
[ApiController]
[Route("api/v{version:apiVersion}/webhooks")]
[AllowAnonymous]
[EnableRateLimiting(RateLimitingServiceExtension.WebhookPolicy)]
[Display(Description = "PAYA/SATNA payout reconciliation callbacks (signature-authenticated, idempotent)")]
public sealed class WebhooksPayoutsController(ISender sender) : BaseController
{
    [HttpPost("payouts/{provider}")]
    [ProducesOkApiResponseType<bool>]
    public async Task<IActionResult> Payouts(string provider, CancellationToken cancellationToken)
    {
        using var reader = new StreamReader(Request.Body, Encoding.UTF8, leaveOpen: true);
        var rawBody = await reader.ReadToEndAsync(cancellationToken);

        var headers = Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToString(), StringComparer.OrdinalIgnoreCase);

        return OperationResult(await sender.Send(new ReconcilePayoutBatchCommand(provider, headers, rawBody), cancellationToken));
    }
}
