import {
  Controller,
  DefaultValuePipe,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  ParseIntPipe,
  ParseUUIDPipe,
  Post,
  Query,
  Sse,
  UseGuards,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import type { Observable } from 'rxjs';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import { SkipTransform } from '../../common/decorators/skip-transform.decorator';
import type { PublicUser } from '../user/user.service';
import {
  NotificationService,
  type NotificationListResult,
} from './notification.service';

// 알림 컨트롤러 — 모든 엔드포인트 인증 필요(본인 수신함 전용)
@ApiTags('Notification')
@Controller('notifications')
@UseGuards(JwtAuthGuard)
export class NotificationController {
  constructor(private readonly notificationService: NotificationService) {}

  @Get()
  @ApiOperation({ summary: '내 알림 목록 (페이지네이션 + 미읽음 수)' })
  @ApiResponse({ status: 200, description: '조회 성공' })
  list(
    @CurrentUser() user: PublicUser,
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
    @Query('size', new DefaultValuePipe(20), ParseIntPipe) size: number,
  ): Promise<NotificationListResult> {
    return this.notificationService.listFor(user.id, page, size);
  }

  @Post(':id/read')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '알림 단건 읽음 처리' })
  @ApiResponse({ status: 200, description: '처리 성공(미읽음 수 반환)' })
  markRead(
    @CurrentUser() user: PublicUser,
    @Param('id', ParseUUIDPipe) id: string,
  ): Promise<{ unreadCount: number }> {
    return this.notificationService.markRead(user.id, id);
  }

  @Post('read-all')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '알림 전체 읽음 처리' })
  @ApiResponse({ status: 200, description: '처리 성공' })
  markAllRead(
    @CurrentUser() user: PublicUser,
  ): Promise<{ unreadCount: number }> {
    return this.notificationService.markAllRead(user.id);
  }

  // 실시간 스트림(SSE) — 표준 응답 래퍼를 건너뛰고 text/event-stream 으로 흘려보낸다.
  // 인증은 access_token 쿠키(EventSource withCredentials)로 연결 시점에 1회 검증된다.
  @Sse('stream')
  @SkipTransform()
  @ApiOperation({ summary: '실시간 알림 스트림 (SSE)' })
  stream(@CurrentUser() user: PublicUser): Observable<MessageEvent> {
    return this.notificationService.streamFor(user.id);
  }
}
