using System.Security.Claims; namespace GuestOps.Web; public static class PaymentEndpoints { public static void Map(RouteGroupBuilder api,bool preview) { var group=api.MapGroup("/payments").RequireRateLimiting("pms").RequireAuthorization(Access.ProviderLookup); group.MapGet("/status",(HttpContext c,IConfiguration config)=>{var p=preview?null:NmiProfile.Read(config,Session.Hotel(c));return Results.Ok(new{configured=p!=null,createsConfigured=p?.CreatesEnabled==true,sandbox=p?.BaseUrl=="https://sandbox.nmi.com",preview});}); group.MapGet("/requests",async(HttpContext c,IStore store)=>Results.Ok((await store.List(Session.Hotel(c))).OrderByDescending(p=>p.UpdatedAt).Select(p=>p.View()))); group.MapPost("/requests",async(PaymentInput input,HttpContext c,PaymentWork work,IStore store)=>{ if(preview)return Results.BadRequest(new{error="Real payment creation is disabled in preview."}); var p=await work.Propose(Session.Hotel(c),c.User.FindFirstValue(ClaimTypes.NameIdentifier)!,input);await Session.Audit(store,c,"Prepared payment request for review");return Results.Ok(p.View()); }).RequireAuthorization(Access.ProviderProposal); group.MapPost("/requests/{id}/create",async(string id,PaymentApproval input,HttpContext c,PaymentWork work,IStore store)=>{ var p=await store.Get(Session.Hotel(c),id);if(p==null)return Results.NotFound();if(preview)return Results.BadRequest(); var result=await work.Create(p,input.Version,c.User.FindFirstValue(ClaimTypes.NameIdentifier)!,input.EmailAndAmountApproved,c.RequestAborted);await Session.Audit(store,c,"Payment creation result: "+result.State);return Results.Ok(result.View()); }).RequireAuthorization(Access.ExternalApproval); group.MapPost("/requests/{id}/check",async(string id,VersionInput input,HttpContext c,PaymentWork work,IStore store)=>{ var p=await store.Get(Session.Hotel(c),id);if(p==null)return Results.NotFound();if(preview)return Results.BadRequest(); var result=await work.Check(p,input.Version,c.RequestAborted);await Session.Audit(store,c,"Checked payment invoice: "+result.State);return Results.Ok(result.View()); }).RequireAuthorization(Access.ExternalApproval); group.MapPost("/requests/{id}/cancel",async(string id,VersionInput input,HttpContext c,PaymentWork work,IStore store)=>{ var p=await store.Get(Session.Hotel(c),id);if(p==null)return Results.NotFound();if(preview)return Results.BadRequest(); var result=await work.Cancel(p,input.Version);await Session.Audit(store,c,"Cancelled unsubmitted payment proposal");return Results.Ok(result.View()); }).RequireAuthorization(Access.ExternalApproval); group.MapPut("/controls",async(PmsControlsInput input,HttpContext c,IStore store,IConfiguration config)=>{ if(input.Enabled&&(preview||NmiProfile.Read(config,Session.Hotel(c))?.CreatesEnabled!=true))return Results.BadRequest(new{error="Administrator payment enablement and sandbox acceptance are required first."}); var hotel=await store.Get(Session.Hotel(c),Session.Hotel(c));if(hotel==null)return Results.NotFound();hotel.PaymentsEnabled=input.Enabled;hotel.Version=input.Version+1; if(!await store.Replace(hotel.HotelId,hotel.Id,input.Version,hotel))return Input.Conflict();await Session.Audit(store,c,"Updated payment creation control");return Results.Ok(hotel); }).RequireAuthorization(Access.Integrations); } }