using Application.Abstractions.Hub;
using Application.Abstractions.Notification;
using Domain.Entities.Notifications.ValueObject;
using Infrastructure.Hubs;
using Web.Api.Common;
using MediatR;
using Microsoft.AspNetCore.SignalR;

namespace Web.Api.Endpoints.Donation;

/// <summary>크루 방송 시작 — 세션 생성 + 크루원에게 초대 알림</summary>
internal sealed class CrewSessionStart : IEndpoint
{
    public void MapEndpoint(IEndpointRouteBuilder app)
    {
        app.MapPost("api/crew/session/start", async (
            Application.Features.Api.Crew.StartSession.Command body,
            ISender sender,
            IHubContext<AppHub, IAppHubClient> appHub,
            INotificationService notificationService,
            Application.Abstractions.Data.IAppDbContext db,
            CancellationToken ct
        ) => {
            var data = await sender.Send(body, ct);

            // 크루원들에게 초대 알림 발송
            var consents = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
                .ToListAsync(
                    Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
                        .AsNoTracking(db.CrewSessionConsent)
                        .Where(c => c.CrewSessionID == data.CrewSessionID)
                        .Join(db.CrewMember, c => c.CrewMemberID, m => m.ID, (c, m) => new { m.MemberID, m.Nickname }),
                    ct
                );

            foreach (var member in consents)
            {
                await notificationService.SendAsync(
                    member.MemberID,
                    NotificationType.CrewInvitation,
                    "크루 방송 초대",
                    $"크루 방송 '{body.Title}'에 초대되었습니다. 참여 동의를 해주세요.",
                    $"/crew/consent/{data.CrewSessionID}",
                    "CrewSession", data.CrewSessionID, null, ct
                );

                // AppHub 실시간 푸시
                await appHub.Clients.Group($"member:{member.MemberID}").ReceiveCrewInvitation(new
                {
                    CrewSessionID = data.CrewSessionID,
                    Title = body.Title,
                    CrewID = body.CrewID
                });
            }

            return ApiResponse.Ok(data);
        })
        .WithTags("Crew")
        .RequireAuthorization();
    }
}