using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using StickyBoard.Api.Common; using StickyBoard.Core.DTOs.Common; using StickyBoard.Core.DTOs.SocialAndMessaging; using StickyBoard.Core.Services.SocialAndMessaging; namespace StickyBoard.Api.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] public sealed class InvitesController : ControllerBase { private readonly InviteService _invites; public InvitesController(InviteService invites) { _invites = invites; } // ------------------------------------------------------------ // CREATE INVITE // ------------------------------------------------------------ [HttpPost] public async Task>> Create( [FromBody] InviteCreateRequestDto dto, CancellationToken ct) { var senderId = User.GetUserId(); if (senderId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); dto.SenderId = senderId; var result = await _invites.CreateAsync(dto, ct); return Ok(ApiResponseDto.Ok(result)); } // ------------------------------------------------------------ // ACCEPT INVITE // ------------------------------------------------------------ [HttpPost("accept")] public async Task>> Accept( [FromBody] InviteAcceptRequestDto dto, CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); dto.AcceptingUserId = userId; var result = await _invites.AcceptAsync(dto, ct); return result is null ? NotFound(ApiResponseDto.Fail("Invalid or expired invite.")) : Ok(ApiResponseDto.Ok(result)); } // ------------------------------------------------------------ // REVOKE INVITE // ------------------------------------------------------------ [HttpPost("revoke")] public async Task>> Revoke( [FromBody] InviteRevokeRequestDto dto, CancellationToken ct) { var senderId = User.GetUserId(); if (senderId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); var ok = await _invites.RevokeAsync(dto.Token, ct); return ok ? Ok(ApiResponseDto.Ok(new { success = true })) : NotFound(ApiResponseDto.Fail("Invite not found or already handled.")); } // ------------------------------------------------------------ // SENT INVITES // ------------------------------------------------------------ [HttpGet("sent")] public async Task>>> GetSent( CancellationToken ct) { var senderId = User.GetUserId(); if (senderId == Guid.Empty) return Unauthorized(ApiResponseDto>.Fail("Invalid or missing token.")); var invites = await _invites.GetBySenderAsync(senderId, ct); return Ok(ApiResponseDto>.Ok(invites)); } // ------------------------------------------------------------ // LOOKUP BY EMAIL // ------------------------------------------------------------ [HttpGet("email")] public async Task>>> GetByEmail( [FromQuery] string email, CancellationToken ct) { if (string.IsNullOrWhiteSpace(email)) return BadRequest(ApiResponseDto>.Fail("Email is required.")); var invites = await _invites.GetByEmailAsync(email, ct); return Ok(ApiResponseDto>.Ok(invites)); } // ------------------------------------------------------------ // PUBLIC LOOKUP (NO AUTH) // ------------------------------------------------------------ [AllowAnonymous] [HttpGet("public/{token}")] public async Task>> GetPublic( string token, CancellationToken ct) { var invite = await _invites.GetByTokenAsync(token, ct); return invite is null ? NotFound(ApiResponseDto.Fail("Invite not found.")) : Ok(ApiResponseDto.Ok(invite)); } }