import { BadRequestException, Body, Controller, Get, Headers, Param, Patch, Post, Query } from '@nestjs/common'; import { IiosTicketState } from '@prisma/client'; import { SupportService } from './support.service'; import { AssignmentService } from './assignment.service'; import { SessionVerifier } from '../platform/session.verifier'; import type { MessagePrincipal } from '../identity/actor.resolver'; import { AvailabilityDto, CallbackDto, CreateQueueDto, CreateTicketDto, EscalateDto, PatchTicketDto, } from './support.dto'; @Controller('v1/support') export class SupportController { constructor( private readonly support: SupportService, private readonly assignment: AssignmentService, private readonly session: SessionVerifier, ) {} @Post('tickets') async createTicket(@Body() body: CreateTicketDto, @Headers('authorization') auth?: string) { return this.support.createTicket(this.principal(auth), body); } @Post('escalate') async escalate(@Body() body: EscalateDto, @Headers('authorization') auth?: string) { return this.support.escalate(body.threadId, this.principal(auth), body.subject); } @Get('tickets') async listTickets(@Query('scope') scope?: string, @Headers('authorization') auth?: string) { return this.support.listTickets(this.principal(auth), { scope: scope === 'assigned' ? 'assigned' : 'mine' }); } @Patch('tickets/:id') async patchTicket(@Param('id') id: string, @Body() body: PatchTicketDto, @Headers('authorization') auth?: string) { return this.support.transition(id, this.principal(auth), body.state as IiosTicketState, body.reason); } @Post('callbacks') async callback(@Body() body: CallbackDto, @Headers('authorization') auth?: string) { return this.support.requestCallback(this.principal(auth), { preferChannel: body.preferChannel, preferredTime: body.preferredTime ? new Date(body.preferredTime) : undefined, notes: body.notes, ticketId: body.ticketId, }); } // ─── admin / agent ──────────────────────────────────────────────── @Post('queues') async createQueue(@Body() body: CreateQueueDto, @Headers('authorization') auth?: string) { return this.assignment.createQueue(this.principal(auth), body.name); } @Post('queues/:id/members') async joinQueue(@Param('id') id: string, @Headers('authorization') auth?: string) { return this.assignment.addMember(id, this.principal(auth)); } @Patch('members/me/availability') async availability(@Body() body: AvailabilityDto, @Headers('authorization') auth?: string) { return this.assignment.setAvailability(this.principal(auth), body.state); } private principal(authorization?: string): MessagePrincipal { const token = (authorization ?? '').replace(/^Bearer\s+/i, ''); if (!token) throw new BadRequestException('Authorization bearer token is required'); return this.session.verify(token); } }