import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Req, UseGuards, } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { AcceptOrganizationInviteDto } from './dto/accept-organization-invite.dto'; import { CreateConnectionRequestDto } from './dto/create-connection-request.dto'; import { InviteOrganizationDto } from './dto/invite-organization.dto'; import { PreviewOrganizationInviteDto } from './dto/preview-organization-invite.dto'; import { RespondConnectionRequestDto } from './dto/respond-connection-request.dto'; import { OrganizationService } from './organization.service'; /** * Counterpart orgs (clinic↔lab). * * - `/connections` — OrganizationLink rows (connection requests + links created by invites). * - `/invite`, `/invitations/*` — signup invitation tokens (orgs not yet on DyoLink). */ @ApiTags('organizations') @ApiBearerAuth('JWT-auth') @Controller('organizations') export class OrganizationController { constructor(private readonly organizationService: OrganizationService) {} @Get('invitations/preview') @ApiOperation({ summary: 'Preview organization invite by token (public)' }) previewInvite(@Query() query: PreviewOrganizationInviteDto) { return this.organizationService.previewInvite(query.token); } @Get('invitations') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'List invitation history for current organization' }) listInvitations(@Req() req: { user: { id: string; organizationId?: string } }) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.listInvitationHistory(req.user.id, organizationId); } @Post('invitations/accept') @ApiOperation({ summary: 'Accept organization invite and create/link counterpart org (public)' }) acceptInvite(@Body() dto: AcceptOrganizationInviteDto) { return this.organizationService.acceptInvite(dto); } @Get('search') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Search counterpart organizations (active subscription only)', }) search( @Req() req: { user: { id: string; organizationId?: string } }, @Query('q') q = '', ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.searchCounterpartOrganizations(req.user.id, organizationId, q); } @Get('connections/pending-count') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Count incoming pending connection requests for sidebar badge' }) countPendingConnections(@Req() req: { user: { id: string; organizationId?: string } }) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.countIncomingPendingConnections(req.user.id, organizationId); } @Get('connections') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'List counterpart connections for current organization' }) listConnections(@Req() req: { user: { id: string; organizationId?: string } }) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.list(req.user.id, organizationId); } @Post('connections') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Create pending connection request to an existing subscribed counterpart org', }) createConnectionRequest( @Req() req: { user: { id: string; organizationId?: string } }, @Body() dto: CreateConnectionRequestDto, ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.createConnectionRequest(req.user.id, organizationId, dto); } @Patch('connections/:connectionId/respond') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Accept or reject a pending connection request for current organization' }) respondToConnectionRequest( @Req() req: { user: { id: string; organizationId?: string } }, @Param('connectionId') connectionId: string, @Body() dto: RespondConnectionRequestDto, ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.respondToConnectionRequest( req.user.id, organizationId, connectionId, dto, ); } @Delete('connections/:connectionId') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Remove an active connection' }) deleteConnection( @Req() req: { user: { id: string; organizationId?: string } }, @Param('connectionId') connectionId: string, ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.deleteConnection(req.user.id, organizationId, connectionId); } @Post('invitations/:invitationId/link') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Get a shareable invite link for a pending invitation' }) getInvitationLink( @Req() req: { user: { id: string; organizationId?: string } }, @Param('invitationId') invitationId: string, ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.getInvitationLink(req.user.id, organizationId, invitationId); } @Post('invite') @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Create invite link for owner of not-yet-subscribed counterpart org' }) inviteOrganization( @Req() req: { user: { id: string; organizationId?: string } }, @Body() dto: InviteOrganizationDto, ) { const organizationId = this.organizationService.getOrganizationIdFromUser(req.user); return this.organizationService.inviteOrganization(req.user.id, organizationId, dto); } }