import { CurrentUser } from "@edr/api-common";
import {
  SUPPORT_ATTACHMENT_MAX_PER_MESSAGE,
  SupportAuthorRole,
} from "@edr/types";
import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Query,
  UploadedFiles,
  UseInterceptors,
} from "@nestjs/common";
import { FilesInterceptor } from "@nestjs/platform-express";
import { ApiBody, ApiConsumes, ApiOperation, ApiTags } from "@nestjs/swagger";

import {
  AuthUserPayload,
  resolveAuthUserId,
} from "../../common/resolve-auth-user-id";
import {
  SUPPORT_ATTACHMENT_FIELD,
  supportAttachmentMulterOptions,
} from "./attachment-upload.options";
import { ListConversationsQueryDto } from "./dto/list-conversations-query.dto";
import { ListMessagesQueryDto } from "./dto/list-messages-query.dto";
import { SendMessageDto } from "./dto/send-message.dto";
import { StartConversationDto } from "./dto/start-conversation.dto";
import { SupportChatService } from "./support-chat.service";

/** Backoffice (agent) support-chat endpoints. Shared inbox over all companies. */
@ApiTags("support-chat-agent")
@Controller("support/agent")
export class SupportChatAgentController {
  constructor(private readonly service: SupportChatService) {}

  @Get("conversations")
  @ApiOperation({ summary: "List all support threads (shared inbox)" })
  list(@Query() query: ListConversationsQueryDto) {
    return this.service.listForAgents(query);
  }

  @Post("conversations")
  @ApiOperation({
    summary: "Start chatting with a company (returns the thread if one exists)",
  })
  start(@Body() body: StartConversationDto) {
    return this.service.startWithCompany(body.companyId);
  }

  @Get("conversations/:id/messages")
  @ApiOperation({
    summary: "List messages in a thread (newest page first)",
    description:
      "Keyset-paginated backwards from the newest message. Omit `before` for " +
      "the newest page, then pass the previous response's `nextCursor` to walk " +
      "back through history. `nextCursor: null` means the thread's start.",
  })
  messages(
    @Param("id", ParseUUIDPipe) id: string,
    @Query() query: ListMessagesQueryDto,
  ) {
    return this.service.getMessages(id, query);
  }

  @Post("conversations/:id/messages")
  @UseInterceptors(
    FilesInterceptor(
      SUPPORT_ATTACHMENT_FIELD,
      SUPPORT_ATTACHMENT_MAX_PER_MESSAGE,
      supportAttachmentMulterOptions,
    ),
  )
  // Accepts multipart (text + files) or plain JSON (text only) — Multer passes
  // non-multipart requests straight through, so existing JSON clients are
  // unaffected.
  @ApiConsumes("multipart/form-data", "application/json")
  @ApiBody({
    schema: {
      type: "object",
      properties: {
        body: { type: "string" },
        attachments: {
          type: "array",
          items: { type: "string", format: "binary" },
        },
      },
    },
  })
  @ApiOperation({ summary: "Reply as an agent, optionally with attachments" })
  send(
    @CurrentUser() user: AuthUserPayload,
    @Param("id", ParseUUIDPipe) id: string,
    @Body() body: SendMessageDto,
    @UploadedFiles() attachments?: Express.Multer.File[],
  ) {
    return this.service.sendAsAgent(
      id,
      resolveAuthUserId(user),
      body.body,
      attachments ?? [],
    );
  }

  @Post("conversations/:id/read")
  @ApiOperation({ summary: "Mark a thread read (agent side)" })
  read(
    @CurrentUser() user: AuthUserPayload,
    @Param("id", ParseUUIDPipe) id: string,
  ) {
    return this.service.markAgentRead(id, resolveAuthUserId(user));
  }

  @Get("unread-count")
  @ApiOperation({ summary: "Count unread threads (agent side)" })
  unread(@CurrentUser() user: AuthUserPayload) {
    return this.service.unreadCount(
      SupportAuthorRole.AGENT,
      resolveAuthUserId(user),
    );
  }
}
