import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Patch,
  Body,
  Param,
  Query,
  Res,
  Logger,
  Headers,
  UseGuards,
} from '@nestjs/common';
import type { Response as ExpressResponse } from 'express';
import { LiveBlogService } from './live-blog.service';
import {
  CreateLiveBlogDto,
  UpdateLiveBlogDto,
  FindLiveBlogsDto,
  CreateLiveBlogUpdateDto,
  UpdateLiveBlogUpdateDto,
} from './articles.dto';
import { LiveBlogStatus, UserRole } from './entities';
import { JwtAuthGuard } from './auth/jwt-auth.guard';
import { RolesGuard } from './auth/roles.guard';
import { Roles } from './auth/roles.decorator';
import { Public } from './auth/public.decorator';

@Controller('live-blogs')
export class LiveBlogController {
  private readonly logger = new Logger(LiveBlogController.name);

  constructor(private readonly liveBlogService: LiveBlogService) {}

  // Live Blog CRUD operations
  @Get('featured')
  @Public()
  getFeatured() {
    this.logger.log('GET /featured called');
    return this.liveBlogService.findPinned();
  }

  @Get('active')
  @Public()
  getActive() {
    return this.liveBlogService.findActive();
  }

  @Get('recent')
  @Public()
  getRecent() {
    return this.liveBlogService.getLiveBlogsWithRecentUpdates();
  }

  @Post()
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  create(@Body() dto: CreateLiveBlogDto) {
    return this.liveBlogService.create(dto);
  }

  @Get()
  @Public()
  findAll(@Query() dto: FindLiveBlogsDto) {
    return this.liveBlogService.findAll(dto);
  }

  @Get(':id')
  @Public()
  findOne(@Param('id') id: string) {
    return this.liveBlogService.findOne(id);
  }

  @Get('slug/:slug')
  @Public()
  findBySlug(@Param('slug') slug: string) {
    return this.liveBlogService.findBySlug(slug);
  }

  @Put(':id')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  update(@Param('id') id: string, @Body() dto: UpdateLiveBlogDto) {
    return this.liveBlogService.update(id, dto);
  }

  @Delete(':id')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  remove(@Param('id') id: string) {
    return this.liveBlogService.remove(id);
  }

  // Live Blog Updates CRUD operations
  @Post(':id/updates')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  createUpdate(
    @Param('id') liveBlogId: string,
    @Body() dto: CreateLiveBlogUpdateDto,
  ) {
    return this.liveBlogService.createUpdate(dto, liveBlogId);
  }

  @Get(':id/updates')
  @Public()
  findUpdates(
    @Param('id') liveBlogId: string,
    @Query('page') page = 1,
    @Query('limit') limit = 50,
  ) {
    return this.liveBlogService.findUpdates(
      liveBlogId,
      parseInt(page.toString()),
      parseInt(limit.toString()),
    );
  }

  @Put(':id/updates/:updateId')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  updateUpdate(
    @Param('id') liveBlogId: string,
    @Param('updateId') updateId: string,
    @Body() dto: UpdateLiveBlogUpdateDto,
  ) {
    return this.liveBlogService.updateUpdate(liveBlogId, updateId, dto);
  }

  @Delete(':id/updates/:updateId')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  removeUpdate(
    @Param('id') liveBlogId: string,
    @Param('updateId') updateId: string,
  ) {
    return this.liveBlogService.removeUpdate(liveBlogId, updateId);
  }

  @Patch(':id/archive')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  archive(@Param('id') id: string) {
    return this.liveBlogService.archive(id);
  }

  @Patch(':id/publish')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.CONTRIBUTOR)
  publish(@Param('id') id: string, @Query('status') status?: LiveBlogStatus) {
    return this.liveBlogService.publish(id, status || LiveBlogStatus.DRAFT);
  }

  // SSE endpoint for real-time updates
  @Get(':id/stream')
  @Public()
  stream(
    @Param('id') liveBlogId: string,
    @Res() response: ExpressResponse,
    @Headers('last-event-id') lastEventId?: string,
  ) {
    this.logger.log(`SSE connection request for live blog ${liveBlogId}`);

    if (lastEventId) {
      this.logger.log(`Client resuming with last event ID: ${lastEventId}`);
    }

    this.liveBlogService.createStream(liveBlogId, response);
  }
}
