import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import type { PublicUser } from '../user/user.service';
import {
  ScheduleService,
  type ScheduleAttendee,
  type ScheduleCategoryResponse,
  type ScheduleEventResponse,
} from './schedule.service';
import {
  CreateScheduleCategoryDto,
  UpdateScheduleCategoryDto,
} from './dto/schedule-category.dto';
import {
  CreateScheduleEventDto,
  UpdateScheduleEventDto,
} from './dto/schedule-event.dto';

// YYYY-MM-DD 형식 검증(쿼리 파라미터용)
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;

// 일정(전사 공유 캘린더) 컨트롤러 — 인증 사용자면 누구나 조회·관리 가능.
@ApiTags('Schedule')
@Controller('schedule')
@UseGuards(JwtAuthGuard)
export class ScheduleController {
  constructor(private readonly scheduleService: ScheduleService) {}

  // ----- 카테고리 -----

  @Get('categories')
  @ApiOperation({ summary: '일정 카테고리 목록' })
  @ApiResponse({ status: 200, description: '조회 성공' })
  listCategories(): Promise<ScheduleCategoryResponse[]> {
    return this.scheduleService.listCategories();
  }

  @Post('categories')
  @ApiOperation({ summary: '일정 카테고리 생성' })
  @ApiResponse({ status: 201, description: '생성 성공' })
  createCategory(
    @Body() dto: CreateScheduleCategoryDto,
  ): Promise<ScheduleCategoryResponse> {
    return this.scheduleService.createCategory(dto);
  }

  @Patch('categories/:id')
  @ApiOperation({ summary: '일정 카테고리 수정' })
  @ApiResponse({ status: 200, description: '수정 성공' })
  updateCategory(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateScheduleCategoryDto,
  ): Promise<ScheduleCategoryResponse> {
    return this.scheduleService.updateCategory(id, dto);
  }

  @Delete('categories/:id')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '일정 카테고리 삭제(포함 일정도 삭제)' })
  @ApiResponse({ status: 200, description: '삭제 성공' })
  async deleteCategory(
    @Param('id', ParseUUIDPipe) id: string,
  ): Promise<{ success: boolean }> {
    await this.scheduleService.deleteCategory(id);
    return { success: true };
  }

  // ----- 참석자 선택 풀 -----

  @Get('people')
  @ApiOperation({ summary: '참석자 선택용 사용자 목록' })
  @ApiResponse({ status: 200, description: '조회 성공' })
  listPeople(): Promise<ScheduleAttendee[]> {
    return this.scheduleService.listPeople();
  }

  // ----- 일정 -----

  @Get('events')
  @ApiOperation({ summary: '일정 목록(기간 겹침)' })
  @ApiResponse({ status: 200, description: '조회 성공' })
  listEvents(
    @Query('start') start: string,
    @Query('end') end: string,
  ): Promise<ScheduleEventResponse[]> {
    if (!start || !end || !DATE_RE.test(start) || !DATE_RE.test(end)) {
      throw new BadRequestException(
        'start, end 쿼리(YYYY-MM-DD)가 필요합니다.',
      );
    }
    return this.scheduleService.listEvents(start, end);
  }

  @Post('events')
  @ApiOperation({ summary: '일정 생성' })
  @ApiResponse({ status: 201, description: '생성 성공' })
  createEvent(
    @CurrentUser() user: PublicUser,
    @Body() dto: CreateScheduleEventDto,
  ): Promise<ScheduleEventResponse> {
    return this.scheduleService.createEvent(dto, {
      id: user.id,
      name: user.name,
    });
  }

  @Patch('events/:id')
  @ApiOperation({ summary: '일정 수정' })
  @ApiResponse({ status: 200, description: '수정 성공' })
  updateEvent(
    @CurrentUser() user: PublicUser,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateScheduleEventDto,
  ): Promise<ScheduleEventResponse> {
    return this.scheduleService.updateEvent(id, dto, {
      id: user.id,
      name: user.name,
    });
  }

  @Delete('events/:id')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '일정 삭제' })
  @ApiResponse({ status: 200, description: '삭제 성공' })
  async deleteEvent(
    @CurrentUser() user: PublicUser,
    @Param('id', ParseUUIDPipe) id: string,
  ): Promise<{ success: boolean }> {
    await this.scheduleService.deleteEvent(id, {
      id: user.id,
      name: user.name,
    });
    return { success: true };
  }
}
