import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  Put,
  Query,
  Req,
} from "@nestjs/common";
import { NotificationsService } from "./notifications.service.js";
import {
  sendNotificationSchema,
  sendNotificationBatchSchema,
} from "./notifications.dto.js";
import type { SendNotificationDto } from "./notifications.dto.js";
import {
  Permissions,
  RequirePermission,
} from "../middleware/permission.guard.js";
import type { AuthenticatedRequest } from "../middleware/auth.middleware.js";
import { PermissionDeniedError } from "../shared/errors/application-error.js";

@Controller("notifications")
export class NotificationsController {
  constructor(private readonly service: NotificationsService) {}

  @Post()
  @RequirePermission(Permissions.MSG_NOTIFICATION_SEND)
  async send(@Body() body: unknown): Promise<{ success: true; data: unknown }> {
    const dto: SendNotificationDto = sendNotificationSchema.parse(body);
    const result = await this.service.send(dto);
    return { success: true, data: result };
  }

  @Post("batch")
  @RequirePermission(Permissions.MSG_NOTIFICATION_SEND)
  async createBatch(
    @Body() body: unknown,
  ): Promise<{ success: true; data: unknown }> {
    const dtos: SendNotificationDto[] = sendNotificationBatchSchema.parse(body);
    const result = await this.service.createBatch(dtos);
    return { success: true, data: result };
  }

  @Get("user/:userId")
  @RequirePermission(Permissions.MSG_NOTIFICATION_READ)
  async listByUser(
    @Param("userId") userId: string,
    @Query("unread") unread: string,
  ): Promise<{ success: true; data: unknown }> {
    const result = await this.service.listByUser(userId, unread === "true");
    return { success: true, data: result };
  }

  @Get("user/:userId/page")
  @RequirePermission(Permissions.MSG_NOTIFICATION_READ)
  async listByUserPaginated(
    @Param("userId") userId: string,
    @Query("page") page: string,
    @Query("pageSize") pageSize: string,
  ): Promise<{ success: true; data: unknown }> {
    const pageNum = Number(page) > 0 ? Number(page) : 1;
    const pageSizeNum = Number(pageSize) > 0 ? Number(pageSize) : 20;
    const result = await this.service.listByUserWithPagination(
      userId,
      pageNum,
      pageSizeNum,
    );
    return { success: true, data: result };
  }

  @Put(":id/read")
  @RequirePermission(Permissions.MSG_NOTIFICATION_MANAGE)
  async markAsRead(@Param("id") id: string): Promise<{ success: true }> {
    await this.service.markAsRead(id);
    return { success: true };
  }

  @Get("search")
  @RequirePermission(Permissions.MSG_NOTIFICATION_READ)
  async search(
    @Req() req: AuthenticatedRequest,
    @Query("q") q: string,
    @Query("userId") userIdParam: string,
  ): Promise<{ success: true; data: unknown }> {
    const userId = req.userId ?? userIdParam;
    if (!userId) {
      throw new PermissionDeniedError("MSG_NOTIFICATION_READ");
    }
    const result = await this.service.search(userId, q);
    return { success: true, data: result };
  }
}
