using LiteCqrs; using TeleWave.Api.Common; using TeleWave.Application.Broadcast; using TeleWave.Application.Broadcast.AddChannelAd; using TeleWave.Application.Broadcast.AddChannelShow; using TeleWave.Application.Broadcast.CreateChannel; using TeleWave.Application.Broadcast.CreateOverride; using TeleWave.Application.Broadcast.DeleteOverride; using TeleWave.Application.Broadcast.GetChannel; using TeleWave.Application.Broadcast.GetSchedule; using TeleWave.Application.Broadcast.ListChannels; using TeleWave.Application.Broadcast.RegenerateSchedule; using TeleWave.Application.Broadcast.RemoveChannelAd; using TeleWave.Application.Broadcast.RemoveChannelShow; using TeleWave.Application.Broadcast.UpdateChannelSettings; using TeleWave.Application.Broadcast.UpdateChannelShow; using TeleWave.Domain.Broadcast; using TeleWave.Infrastructure.Identity; namespace TeleWave.Api.Endpoints; public static class ChannelEndpoints { public static IEndpointRouteBuilder MapChannelEndpoints(this IEndpointRouteBuilder app) { var admin = app.MapGroup("/api/admin/channels") .WithTags("Admin.Channels") .RequireAuthorization(policy => policy.RequireRole(RoleNames.Admin)); admin.MapPost("", CreateChannel).Produces(StatusCodes.Status201Created); admin.MapGet("", ListChannels).Produces>(); admin.MapGet("/{id:guid}", GetChannel).Produces(); admin.MapPut("/{id:guid}/settings", UpdateSettings).Produces(StatusCodes.Status204NoContent); admin .MapPost("/{id:guid}/shows", AddShow) .Produces(StatusCodes.Status201Created); admin .MapPut("/{id:guid}/shows/{channelShowId:guid}", UpdateShow) .Produces(StatusCodes.Status204NoContent); admin .MapDelete("/{id:guid}/shows/{channelShowId:guid}", RemoveShow) .Produces(StatusCodes.Status204NoContent); admin .MapPost("/{id:guid}/ads", AddAd) .Produces(StatusCodes.Status201Created); admin .MapDelete("/{id:guid}/ads/{channelAdId:guid}", RemoveAd) .Produces(StatusCodes.Status204NoContent); admin .MapPost("/{id:guid}/overrides", CreateOverride) .Produces(StatusCodes.Status201Created); admin .MapDelete("/{id:guid}/overrides/{overrideId:guid}", DeleteOverride) .Produces(StatusCodes.Status204NoContent); admin.MapPost("/{id:guid}/regenerate", Regenerate).Produces(StatusCodes.Status204NoContent); admin .MapGet("/{id:guid}/schedule", GetSchedule) .Produces>(); return app; } private static async Task CreateChannel( CreateChannelCommand command, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(command, cancellationToken); return result.IsSuccess ? Results.Created( $"/api/admin/channels/{result.Value}", new CreatedIdResponse(result.Value) ) : result.ToHttpResult(); } private static async Task ListChannels(ISender sender, CancellationToken cancellationToken) { var result = await sender.Send(new ListChannelsQuery(), cancellationToken); return Results.Ok(result); } private static async Task GetChannel( Guid id, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(new GetChannelQuery(id), cancellationToken); return result.ToHttpResult(); } private static async Task UpdateSettings( Guid id, UpdateChannelSettingsBody body, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send( new UpdateChannelSettingsCommand( id, body.Name, body.IsEnabled, body.AdInsertion, body.AdsPerBreak, body.FillerAssetId ), cancellationToken ); return result.ToHttpResult(); } private static async Task AddShow( Guid id, AddChannelShowBody body, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send( new AddChannelShowCommand(id, body.ShowId, body.Weight, body.BlockMode, body.BlockValue), cancellationToken ); return result.IsSuccess ? Results.Created($"/api/admin/channels/{id}", new CreatedIdResponse(result.Value)) : result.ToHttpResult(); } private static async Task UpdateShow( Guid id, Guid channelShowId, UpdateChannelShowBody body, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send( new UpdateChannelShowCommand( id, channelShowId, body.Weight, body.BlockMode, body.BlockValue, body.IsEnabled ), cancellationToken ); return result.ToHttpResult(); } private static async Task RemoveShow( Guid id, Guid channelShowId, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(new RemoveChannelShowCommand(id, channelShowId), cancellationToken); return result.ToHttpResult(); } private static async Task AddAd( Guid id, AddChannelAdBody body, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(new AddChannelAdCommand(id, body.MediaAssetId), cancellationToken); return result.IsSuccess ? Results.Created($"/api/admin/channels/{id}", new CreatedIdResponse(result.Value)) : result.ToHttpResult(); } private static async Task RemoveAd( Guid id, Guid channelAdId, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(new RemoveChannelAdCommand(id, channelAdId), cancellationToken); return result.ToHttpResult(); } private static async Task CreateOverride( Guid id, CreateOverrideBody body, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send( new CreateProgrammingOverrideCommand( id, body.Mode, body.StartsAtUtc, body.EndsAtUtc, body.Shows ), cancellationToken ); return result.IsSuccess ? Results.Created($"/api/admin/channels/{id}", new CreatedIdResponse(result.Value)) : result.ToHttpResult(); } private static async Task DeleteOverride( Guid id, Guid overrideId, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send( new DeleteProgrammingOverrideCommand(id, overrideId), cancellationToken ); return result.ToHttpResult(); } private static async Task Regenerate( Guid id, ISender sender, CancellationToken cancellationToken ) { var result = await sender.Send(new RegenerateChannelScheduleCommand(id), cancellationToken); return result.ToHttpResult(); } private static async Task GetSchedule( Guid id, DateTimeOffset? from, DateTimeOffset? to, ISender sender, CancellationToken cancellationToken ) { var fromUtc = from ?? DateTimeOffset.UtcNow; var toUtc = to ?? fromUtc.AddDays(1); var result = await sender.Send( new GetChannelScheduleQuery(id, fromUtc, toUtc), cancellationToken ); return result.ToHttpResult(); } } public sealed record UpdateChannelSettingsBody( string Name, bool IsEnabled, AdInsertion AdInsertion, int AdsPerBreak, Guid? FillerAssetId ); public sealed record AddChannelShowBody(Guid ShowId, int Weight, BlockMode BlockMode, int BlockValue); public sealed record UpdateChannelShowBody( int Weight, BlockMode BlockMode, int BlockValue, bool IsEnabled ); public sealed record AddChannelAdBody(Guid MediaAssetId); public sealed record CreateOverrideBody( OverrideMode Mode, DateTimeOffset StartsAtUtc, DateTimeOffset EndsAtUtc, IReadOnlyList Shows );