using Knot.Modules.Stories.Application.Stories.Commands.AddStoryReaction;
using Knot.Modules.Stories.Application.Stories.Commands.AddStoryReply;
using Knot.Modules.Stories.Application.Stories.Commands.RemoveStoryReaction;
using Knot.Modules.Stories.Application.Stories.Queries.GetStoryReplies;
using Knot.Modules.Stories.Application.DTOs;
using Knot.Modules.Stories.Application.Stories.Commands.CreateStory;
using Knot.Modules.Stories.Application.Stories.Commands.DeleteStory;
using Knot.Modules.Stories.Application.Stories.Commands.ViewStory;
using Knot.Modules.Stories.Application.Stories.Queries.GetStories;
using Knot.Modules.Stories.Application.Stories.Queries.GetStoryViewers;
using Knot.Modules.Stories.Application.Stories.Queries.GetUserStories;
using Knot.Shared.Kernel;
using Knot.Shared.Kernel.Storage;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;

namespace Knot.Modules.Stories.Presentation.Endpoints;

public record AddReactionRequest(string Emoji);
public record AddReplyRequest(string Content);

public static class StoriesEndpoints
{
    public static void MapStoriesEndpoints(this WebApplication app)
    {
        var group = app.MapGroup("api/stories").RequireAuthorization();

        group.MapGet("", async (ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new GetStoriesQuery(userContext.UserId), ct);
            return Results.Ok(result.Value);
        });

        group.MapPost("", async ([FromBody] CreateStoryRequest request, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new CreateStoryCommand(userContext.UserId, request.Type, request.MediaUrl, request.Content, request.BgColor, request.IsMuted), ct);
            return Results.Ok(new { id = result.Value });
        });

        group.MapPost("video", async (HttpRequest req, ISender sender, IUserContext userContext, [FromServices] IFileStorageService fileStorage, CancellationToken ct) =>
        {
            if (!req.HasFormContentType) return Results.BadRequest("No file uploaded");
            var form = await req.ReadFormAsync(ct);
            var file = form.Files.FirstOrDefault();
            if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded");

            using var stream = file.OpenReadStream();
            var fileId = await fileStorage.UploadFileAsync(stream, file.FileName, file.ContentType);
            return Results.Ok(new { url = $"/api/files/{fileId}" });
        }).DisableAntiforgery();

        group.MapGet("user/{userId:guid}", async ([FromRoute] Guid userId, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new GetUserStoriesQuery(userContext.UserId, userId), ct);
            return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound();
        });

        group.MapPost("{id:guid}/view", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new ViewStoryCommand(userContext.UserId, id), ct);
            return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound();
        });

        group.MapGet("{id:guid}/viewers", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new GetStoryViewersQuery(userContext.UserId, id), ct);
            if (result.IsFailure) return result.Error.Code == "Unauthorized" ? Results.Forbid() : Results.NotFound();
            return Results.Ok(result.Value);
        });

        group.MapPost("{id:guid}/reaction", async ([FromRoute] Guid id, [FromBody] AddReactionRequest req, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new AddStoryReactionCommand(userContext.UserId, id, req.Emoji), ct);
            return result.IsSuccess ? Results.Ok(new { message = "Reaction added" }) : Results.NotFound();
        });

        group.MapPost("{id:guid}/reaction/delete", async ([FromRoute] Guid id, [FromQuery] string emoji, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new RemoveStoryReactionCommand(userContext.UserId, id, emoji), ct);
            return result.IsSuccess ? Results.Ok(new { message = "Reaction removed" }) : Results.NotFound();
        });

        group.MapPost("{id:guid}/reply", async ([FromRoute] Guid id, [FromBody] AddReplyRequest req, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new AddStoryReplyCommand(userContext.UserId, id, req.Content), ct);
            return result.IsSuccess ? Results.Ok(new { message = "Reply added" }) : Results.NotFound();
        });

        group.MapGet("{id:guid}/replies", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new GetStoryRepliesQuery(userContext.UserId, id), ct);
            return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound();
        });

        group.MapDelete("{id:guid}", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) =>
        {
            var result = await sender.Send(new DeleteStoryCommand(userContext.UserId, id), ct);
            if (result.IsFailure) return result.Error.Code == "Unauthorized" ? Results.Forbid() : Results.NotFound();
            return Results.Ok(result.Value);
        });
    }
}


