using Collaboration.Application.DTOs.Requests;
using Collaboration.Application.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace Collaboration.Api.Controllers;
[Authorize]
[ApiController]
[Route("api/collab")]
[Produces("application/json")]
public class CollabSessionController : ControllerBase
{
private readonly ICollabSessionService _service;
private Guid UserId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
private Guid OrgId => Guid.Parse(User.FindFirstValue("orgId")!);
private string DisplayName => User.FindFirstValue("displayName") ?? "Unknown";
public CollabSessionController(ICollabSessionService service) => _service = service;
/// Create a new ad-hoc or scheduled session.
[HttpPost("sessions")]
[ProducesResponseType(typeof(Application.DTOs.Responses.SessionResponse), 201)]
public async Task Create([FromBody] CreateSessionRequest request, CancellationToken ct)
{
var result = await _service.CreateAsync(request, UserId, OrgId, DisplayName, ct);
return CreatedAtAction(nameof(GetById), new { id = result.SessionId }, result);
}
/// Get session by ID.
[HttpGet("sessions/{id:guid}")]
public async Task GetById(Guid id, CancellationToken ct)
{
var result = await _service.GetAsync(id, OrgId, ct);
return result is null ? NotFound() : Ok(result);
}
/// Get all sessions I'm currently active in.
[HttpGet("sessions/active")]
public async Task GetActive(CancellationToken ct) =>
Ok(await _service.GetActiveSessionsAsync(UserId, OrgId, ct));
/// Get my upcoming scheduled sessions.
[HttpGet("sessions/scheduled")]
public async Task GetScheduled(CancellationToken ct) =>
Ok(await _service.GetScheduledSessionsAsync(UserId, OrgId, ct));
/// Start, pause, resume, or end a session.
[HttpPatch("sessions/{id:guid}/status")]
public async Task UpdateStatus(
Guid id, [FromBody] UpdateSessionStatusRequest request, CancellationToken ct)
{
var result = await _service.UpdateStatusAsync(id, request, UserId, OrgId, ct);
return Ok(result);
}
/// Join a session directly (in-org, by ID).
[HttpGet("sessions/{id:guid}/join")]
public async Task Join(Guid id, CancellationToken ct)
{
var result = await _service.JoinAsync(id, UserId, OrgId, DisplayName, ct);
return Ok(result);
}
/// Invite specific users to a session.
[HttpPost("sessions/{id:guid}/invites/users")]
public async Task InviteUsers(
Guid id, [FromBody] InviteUsersRequest request, CancellationToken ct)
{
await _service.SendUserInvitesAsync(id, request, UserId, OrgId, ct);
return NoContent();
}
/// Create a shareable invite link for a session.
[HttpPost("sessions/{id:guid}/invites/link")]
public async Task CreateLinkInvite(
Guid id, [FromBody] CreateLinkInviteRequest request, CancellationToken ct)
{
var result = await _service.CreateLinkInviteAsync(id, request, UserId, OrgId, ct);
return Ok(result);
}
/// Get my pending invites.
[HttpGet("invites/pending")]
public async Task GetPendingInvites(CancellationToken ct) =>
Ok(await _service.GetPendingInvitesAsync(UserId, ct));
/// Resolve an invite token and join the session.
[HttpPost("invites/{token}/join")]
public async Task JoinViaToken(string token, CancellationToken ct)
{
var result = await _service.JoinViaTokenAsync(token, UserId, OrgId, DisplayName, ct);
return Ok(result);
}
/// Accept or decline an invite.
[HttpPatch("invites/{id:guid}/respond")]
public async Task RespondToInvite(
Guid id, [FromBody] RespondToInviteRequest request, CancellationToken ct)
{
await _service.RespondToInviteAsync(id, request, UserId, ct);
return NoContent();
}
/// Grant control to another participant (Host only).
[HttpPost("sessions/{id:guid}/control/grant")]
public async Task GrantControl(
Guid id, [FromBody] GrantControlRequest request, CancellationToken ct)
{
await _service.GrantControlAsync(id, request, UserId, OrgId, ct);
return NoContent();
}
/// Revoke control and return it to host (Host only).
[HttpPost("sessions/{id:guid}/control/revoke")]
public async Task RevokeControl(Guid id, CancellationToken ct)
{
await _service.RevokeControlAsync(id, UserId, OrgId, ct);
return NoContent();
}
}
[Authorize]
[ApiController]
[Route("api/collab/config")]
[Produces("application/json")]
public class CollabConfigController : ControllerBase
{
private readonly ICollabConfigService _service;
private Guid OrgId => Guid.Parse(User.FindFirstValue("orgId")!);
public CollabConfigController(ICollabConfigService service) => _service = service;
/// Get org collaboration configuration.
[HttpGet]
public async Task Get(CancellationToken ct) =>
Ok(await _service.GetAsync(OrgId, ct));
/// Update org collaboration configuration (Admin only).
[HttpPut]
[Authorize(Policy = "CollabAdmin")]
public async Task Update([FromBody] UpdateCollabConfigRequest request, CancellationToken ct) =>
Ok(await _service.UpdateAsync(OrgId, request, ct));
}