import {
  Controller,
  Get,
  Put,
  Param,
  Query,
  Req,
  Sse,
  UseGuards,
} from '@nestjs/common';
import { Request } from 'express';
import { Observable, map } from 'rxjs';
import { NotificationsService } from './notifications.service';
import { NotificationQueryDto } from './dto/notification.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RequirePermission } from '../auth/decorators/permission.decorator';

interface AuthenticatedUser {
  id: number;
  username: string;
  permissions: string[];
}

interface AuthenticatedRequest extends Request {
  user: AuthenticatedUser;
}

@UseGuards(JwtAuthGuard)
@RequirePermission('notification:view')
@Controller('notifications')
export class NotificationsController {
  constructor(private readonly service: NotificationsService) {}

  @Get()
  async findAll(
    @Req() req: AuthenticatedRequest,
    @Query() query: NotificationQueryDto,
  ) {
    const userId = req.user.id;
    return this.service.findByUser(userId, query.after, query.limit ?? 20);
  }

  @Get('unread-count')
  async unreadCount(@Req() req: AuthenticatedRequest) {
    const userId = req.user.id;
    const count = await this.service.getUnreadCount(userId);
    return { count };
  }

  @Sse('stream')
  stream(@Req() req: AuthenticatedRequest): Observable<MessageEvent> {
    const userId = req.user.id;
    req.on('close', () => {
      this.service.unsubscribe(userId);
    });
    return this.service.subscribe(userId).pipe(
      map((notification) => ({
        data: JSON.stringify({
          id: notification.id,
          type: notification.type,
          title: notification.title,
          content: notification.content,
          link: notification.link,
          createdAt: notification.createdAt,
        }),
      } as MessageEvent)),
    );
  }

  @Put(':id/read')
  async markRead(
    @Param('id') id: string,
    @Req() req: AuthenticatedRequest,
  ) {
    await this.service.markRead(+id, req.user.id);
    return { success: true };
  }

  @Put('read-all')
  async markAllRead(@Req() req: AuthenticatedRequest) {
    await this.service.markAllRead(req.user.id);
    return { success: true };
  }
}
