import { LogActivity } from '@/common/decorators/activity-log.decorator';
import {
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Patch,
  Query,
  Req,
  UnauthorizedException,
  UseGuards,
} from '@nestjs/common';
import type { Request } from 'express';

import { Roles } from '@/casl/roles.decorator';
import { RolesGuard } from '@/casl/roles.guard';
import { JwtAuthGuard } from '@/modules/auth/jwt-auth.guard';

import { GetSystemNotificationsQueryDto } from './dto/get-system-notifications-query.dto';
import { MobileSystemNotificationsService } from './mobile-system-notifications.service';

const NOTIFICATION_READ_ROLES = [
  'admin',
  'ministry',
  'private_sector',
  'cdc_g-psf',
  'cdc',
  'cefp',
];

type AuthenticatedRequest = Request & {
  user?: {
    id?: number;
  };
};

@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(...NOTIFICATION_READ_ROLES)
@Controller('mobile/system-notifications')
export class MobileSystemNotificationsController {
  constructor(
    private readonly systemNotificationsService: MobileSystemNotificationsService,
  ) {}

  @Get()
  findAll(
    @Req() request: AuthenticatedRequest,
    @Query() query: GetSystemNotificationsQueryDto,
  ) {
    return this.systemNotificationsService.findAllForCurrentUser(
      this.getCurrentUserId(request),
      query,
    );
  }

  @Get('unread-count')
  unreadCount(@Req() request: AuthenticatedRequest) {
    return this.systemNotificationsService.unreadCountForCurrentUser(
      this.getCurrentUserId(request),
    );
  }

  @Get(':id')
  findOne(
    @Req() request: AuthenticatedRequest,
    @Param('id', ParseIntPipe) id: number,
  ) {
    return this.systemNotificationsService.findOneForCurrentUser(
      id,
      this.getCurrentUserId(request),
    );
  }

  @Patch('read-all')
  @LogActivity({
    summaryOnly: true,
    module: 'system-notifications',
    action: 'MARK_READ',
    reference: 'mobile/system-notifications/read-all',
    countField: 'updated',
  })
  markAllAsRead(@Req() request: AuthenticatedRequest) {
    return this.systemNotificationsService.markAllAsReadForCurrentUser(
      this.getCurrentUserId(request),
    );
  }

  @Patch(':id/read')
  @LogActivity({
    snapshot: { source: 'systemNotification', idParam: 'id' },
    module: 'system-notifications',
    action: 'MARK_READ',
    reference: 'mobile/system-notifications/:id/read',
  })
  markAsRead(
    @Req() request: AuthenticatedRequest,
    @Param('id', ParseIntPipe) id: number,
  ) {
    return this.systemNotificationsService.markAsReadForCurrentUser(
      id,
      this.getCurrentUserId(request),
    );
  }

  @Delete('all')
  @LogActivity({
    summaryOnly: true,
    module: 'system-notifications',
    action: 'DELETE',
    reference: 'mobile/system-notifications/all',
    countField: 'deleted',
  })
  softDeleteAll(@Req() request: AuthenticatedRequest) {
    return this.systemNotificationsService.softDeleteAllForCurrentUser(
      this.getCurrentUserId(request),
    );
  }

  @Delete(':id')
  @LogActivity({
    snapshot: { source: 'systemNotification', idParam: 'id' },
    module: 'system-notifications',
    action: 'DELETE',
    reference: 'mobile/system-notifications/:id',
  })
  softDelete(
    @Req() request: AuthenticatedRequest,
    @Param('id', ParseIntPipe) id: number,
  ) {
    return this.systemNotificationsService.softDeleteForCurrentUser(
      id,
      this.getCurrentUserId(request),
    );
  }

  private getCurrentUserId(request: AuthenticatedRequest): number {
    const userId = Number(request.user?.id);

    if (!Number.isInteger(userId) || userId <= 0) {
      throw new UnauthorizedException('Invalid authenticated user.');
    }

    return userId;
  }
}
