/**
 * Notifications Controller
 *
 * API endpoints for managing in-app notifications.
 */

import { Controller, Get, Post, Param, Query, Req, UseGuards } from "@nestjs/common";
import { RateLimit, RateLimitGuard } from "@bff/core/rate-limiting/index.js";
import type { RequestWithUser } from "@bff/modules/auth/auth.types.js";
import { NotificationService } from "./notifications.service.js";
import {
  notificationListResponseSchema,
  notificationUnreadCountResponseSchema,
  notificationIdParamSchema,
  type NotificationListResponse,
} from "@customer-portal/domain/notifications";
import { notificationQuerySchema } from "@customer-portal/domain/notifications";
import { actionAckResponseSchema, type ActionAckResponse } from "@customer-portal/domain/common";
import { createZodDto, ZodResponse } from "nestjs-zod";

class NotificationQueryDto extends createZodDto(notificationQuerySchema) {}
class NotificationIdParamDto extends createZodDto(notificationIdParamSchema) {}
class NotificationListResponseDto extends createZodDto(notificationListResponseSchema) {}
class NotificationUnreadCountResponseDto extends createZodDto(
  notificationUnreadCountResponseSchema
) {}
class ActionAckResponseDto extends createZodDto(actionAckResponseSchema) {}

@Controller("notifications")
@UseGuards(RateLimitGuard)
export class NotificationsController {
  constructor(private readonly notificationService: NotificationService) {}

  /**
   * Get notifications for the current user
   */
  @Get()
  @RateLimit({ limit: 60, ttl: 60 })
  @ZodResponse({ description: "Get notifications", type: NotificationListResponseDto })
  async getNotifications(
    @Req() req: RequestWithUser,
    @Query() query: NotificationQueryDto
  ): Promise<NotificationListResponse> {
    return this.notificationService.getNotifications(req.user.id, {
      limit: Math.min(query.limit, 50), // Cap at 50
      offset: query.offset,
      includeRead: query.includeRead,
    });
  }

  /**
   * Get unread notification count for the current user
   */
  @Get("unread-count")
  @RateLimit({ limit: 120, ttl: 60 })
  @ZodResponse({ description: "Get unread count", type: NotificationUnreadCountResponseDto })
  async getUnreadCount(@Req() req: RequestWithUser): Promise<{ count: number }> {
    const count = await this.notificationService.getUnreadCount(req.user.id);
    return { count };
  }

  /**
   * Mark a specific notification as read
   */
  @Post(":id/read")
  @RateLimit({ limit: 60, ttl: 60 })
  @ZodResponse({ description: "Mark as read", type: ActionAckResponseDto })
  async markAsRead(
    @Req() req: RequestWithUser,
    @Param() params: NotificationIdParamDto
  ): Promise<ActionAckResponse> {
    await this.notificationService.markAsRead(params.id, req.user.id);
    return {};
  }

  /**
   * Mark all notifications as read
   */
  @Post("read-all")
  @RateLimit({ limit: 10, ttl: 60 })
  @ZodResponse({ description: "Mark all as read", type: ActionAckResponseDto })
  async markAllAsRead(@Req() req: RequestWithUser): Promise<ActionAckResponse> {
    await this.notificationService.markAllAsRead(req.user.id);
    return {};
  }

  /**
   * Dismiss a notification (hide from UI)
   */
  @Post(":id/dismiss")
  @RateLimit({ limit: 60, ttl: 60 })
  @ZodResponse({ description: "Dismiss notification", type: ActionAckResponseDto })
  async dismiss(
    @Req() req: RequestWithUser,
    @Param() params: NotificationIdParamDto
  ): Promise<ActionAckResponse> {
    await this.notificationService.dismiss(params.id, req.user.id);
    return {};
  }
}
