import { BadRequestException, Body, Controller, Get, Headers, Param, Patch, Post, Query, UseGuards } 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 { ContextAttestationGuard } from '../platform/context-attestation.guard';
import type { MessagePrincipal } from '../identity/actor.resolver';
import {
  AssignTicketDto,
  AvailabilityDto,
  CallbackDto,
  CreateQueueDto,
  CreateTicketDto,
  EscalateDto,
  PatchTicketDto,
} from './support.dto';

@Controller('v1/support')
@UseGuards(ContextAttestationGuard)
export class SupportController {
  constructor(
    private readonly support: SupportService,
    private readonly assignment: AssignmentService,
    private readonly session: SessionVerifier,
  ) {}

  @Post('tickets')
  async createTicket(
    @Body() body: CreateTicketDto,
    @Headers('idempotency-key') idempotencyKey?: string,
    @Headers('authorization') auth?: string,
  ) {
    return this.support.createTicket(this.principal(auth), body, idempotencyKey);
  }

  @Post('escalate')
  async escalate(@Body() body: EscalateDto, @Headers('authorization') auth?: string) {
    return this.support.escalate(body.threadId, this.principal(auth), body.subject, body.metadata);
  }

  @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);
  }

  /** Manually assign a ticket to a specific actor (by userId) — generic assignment override. */
  @Post('tickets/:id/assignee')
  async assign(@Param('id') id: string, @Body() body: AssignTicketDto, @Headers('authorization') auth?: string) {
    return this.support.assignTo(id, this.principal(auth), body.userId);
  }

  @Post('callbacks')
  async callback(
    @Body() body: CallbackDto,
    @Headers('idempotency-key') idempotencyKey?: string,
    @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,
      },
      idempotencyKey,
    );
  }

  // ─── 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));
  }

  @Post('agents/me/join')
  async joinDefault(@Headers('authorization') auth?: string) {
    return this.assignment.joinDefault(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);
  }
}
