import { Controller, Get, Body, Param, UseGuards, Query, Patch, Put, Post } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiHeader } from '@nestjs/swagger';
import { NotificationService } from '../services/notification.service';
import { NotificationPreferenceService } from '../services/notification-preference.service';
import { AuthGuard } from '../../auth/guards/auth.guard';
import { UserId } from '../../../common/decorators/user-id.decorator';
import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard';
import { RestId } from '../../../common/decorators/rest-id.decorator';
import { UpdatePreferenceDto } from '../dto/update-preference.dto';
import { CreatePreferenceDto } from '../dto/create-preference.dto';
import { AdminId } from 'src/common/decorators/admin-id.decorator';
import { API_HEADER_SLUG } from 'src/common/constants/index';
import { NotificationMessage } from 'src/common/enums/message.enum';
import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { Permission } from 'src/common/enums/permission.enum';

@ApiTags('notifications')
@Controller()
export class NotificationsController {
  constructor(
    private readonly notificationService: NotificationService,
    private readonly preferenceService: NotificationPreferenceService,
  ) { }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Get('public/notifications')
  @ApiOperation({ summary: 'Get user restaurant notifications' })
  @ApiHeader(API_HEADER_SLUG)
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Number of items to return (default: 50)' })
  @ApiQuery({
    name: 'cursor',
    required: false,
    type: String,
    description: 'Cursor for pagination (ID of the last item from previous page)',
  })
  @ApiQuery({ name: 'status', required: false, enum: ['seen', 'unseen'], description: 'Filter by notification status' })
  async getUserNotifications(
    @UserId() userId: string,
    @RestId() restaurantId: string,
    @Query('limit') limit?: number,
    @Query('cursor') cursor?: string,
    @Query('status') status?: 'seen' | 'unseen',
  ) {
    return await this.notificationService.findByUserAndRestaurant(
      userId,
      restaurantId,
      limit ? parseInt(limit.toString(), 10) : 50,
      cursor,
      status,
    );
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Get('public/notifications/unseen-count')
  @ApiOperation({ summary: 'Get unseen notifications count for user' })
  @ApiHeader(API_HEADER_SLUG)
  async getUserUnseenCount(@UserId() userId: string, @RestId() restaurantId: string) {
    const count = await this.notificationService.countUnseenByUserAndRestaurant(userId, restaurantId);
    return { count };
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Put('public/notifications/:id')
  @ApiOperation({ summary: 'Read a notification ' })
  @ApiParam({ name: 'id', description: 'Notification  ID' })
  async readNotificationUser(@RestId() restaurantId: string, @Param('id') id: string, @UserId() userId: string) {
    await this.notificationService.readNotificationAsUser(id, userId, restaurantId);
    return { message: NotificationMessage.READ_SUCCESS };
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Put('public/notifications/read/all')
  @ApiOperation({ summary: 'Read all notification ' })
  async readAllNotificationUser(@RestId() restaurantId: string, @UserId() userId: string) {
    await this.notificationService.readAllNotifsAsUser(userId, restaurantId);
    return { message: NotificationMessage.READ_SUCCESS };
  }
  /* ***************** Admin Endpoints ***************** */

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Get('admin/notifications')
  @ApiOperation({ summary: 'Get Admin  notifications' })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({
    name: 'cursor',
    required: false,
    type: String,
    description: 'Cursor for pagination (ID of the last item from previous page)',
  })
  @ApiQuery({ name: 'status', required: false, enum: ['seen', 'unseen'], description: 'Filter by notification status' })
  async getAdminNotifications(
    @AdminId() adminId: string,
    @RestId() restaurantId: string,
    @Query('limit') limit?: number,
    @Query('cursor') cursor?: string,
    @Query('status') status?: 'seen' | 'unseen',
  ) {
    const parsedLimit = limit ? parseInt(limit.toString(), 10) : 50;
    return await this.notificationService.findByRestaurant(restaurantId, adminId, parsedLimit, cursor, status);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Get('admin/notifications/unseen-count')
  @ApiOperation({ summary: 'Get unseen notifications count for admin' })
  async getAdminUnseenCount(@AdminId() adminId: string, @RestId() restaurantId: string) {
    const count = await this.notificationService.countUnseenByRestaurant(adminId, restaurantId);
    return { count };
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Put('admin/notifications/:id')
  @ApiOperation({ summary: 'Read a notification ' })
  @ApiParam({ name: 'id', description: 'Notification  ID' })
  async readNotificationAdmin(@RestId() restaurantId: string, @AdminId() adminId: string, @Param('id') id: string) {
    await this.notificationService.readNotificationAdmin(id, adminId, restaurantId);
    return { message: NotificationMessage.READ_SUCCESS };
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Put('admin/notifications/read/all')
  @ApiOperation({ summary: 'Read all notification ' })
  async readAllNotificationAdmin(@RestId() restaurantId: string, @AdminId() adminId: string, @Param('id') id: string) {
    await this.notificationService.readAllNotifsAsAdmin(adminId, restaurantId);
    return { message: NotificationMessage.READ_SUCCESS };
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SETTINGS)
  @Get('admin/notification-preferences')
  @ApiOperation({ summary: 'Get all notification preferences for a restaurant' })
  async getPreferences(@RestId() restaurantId: string) {
    return this.preferenceService.findByRestaurant(restaurantId);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SETTINGS)
  @Patch('admin/notification-preferences/:id')
  @ApiOperation({ summary: 'Update notification channels' })
  @ApiParam({ name: 'id', description: 'Notification preference ID' })
  async updatePreference(
    @RestId() restaurantId: string,
    @Param('id') preferenceId: string,
    @Body() dto: UpdatePreferenceDto,
  ) {
    return this.preferenceService.updatePreference(preferenceId, restaurantId, dto);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SETTINGS)
  @Post('admin/notification-preferences')
  @ApiOperation({ summary: 'Create notification preference' })
  async createPreference(
    @RestId() restaurantId: string,
    @Body() dto: CreatePreferenceDto,
  ) {
    return this.preferenceService.create(restaurantId, dto);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Get('admin/notifications/sms-usage')
  @ApiOperation({ summary: 'Get SMS usage for my restaurant' })
  async getRestaurantSmsUsage(@RestId() restaurantId: string) {
    const smsCount = await this.notificationService.getSmsCountByRestaurantId(restaurantId);
    return { smsCount };
  }

  // super admin endpoints

  @UseGuards(SuperAdminAuthGuard)
  @ApiBearerAuth()
  @Get('super-admin/notifications/sms-count')
  @ApiOperation({ summary: 'Get SMS count for each restaurant with pagination' })
  @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default: 1)', minimum: 1 })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default: 10)', minimum: 1 })
  async getSmsCount(
    @Query('page') page?: number,
    @Query('limit') limit?: number,
  ) {
    const parsedPage = page ? parseInt(page.toString(), 10) : 1;
    const parsedLimit = limit ? parseInt(limit.toString(), 10) : 10;
    return await this.notificationService.getSmsCountByRestaurant(parsedPage, parsedLimit);
  }
}
