import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
} from '@nestjs/swagger';
import { type JwtPayload, CurrentUser, JwtAuthGuard } from '@modules/auth';
import { QuotaGuard, RequireQuota } from '@modules/subscriptions';
import { CreateSavedSearchCommand } from '../../application/commands/create-saved-search/create-saved-search.command';
import { type CreateSavedSearchResult } from '../../application/commands/create-saved-search/create-saved-search.handler';
import { DeleteSavedSearchCommand } from '../../application/commands/delete-saved-search/delete-saved-search.command';
import { UpdateSavedSearchCommand } from '../../application/commands/update-saved-search/update-saved-search.command';
import { type UpdateSavedSearchResult } from '../../application/commands/update-saved-search/update-saved-search.handler';
import { type SavedSearchDetail } from '../../application/queries/get-saved-search/get-saved-search.handler';
import { GetSavedSearchQuery } from '../../application/queries/get-saved-search/get-saved-search.query';
import { type SavedSearchListResult } from '../../application/queries/get-saved-searches/get-saved-searches.handler';
import { GetSavedSearchesQuery } from '../../application/queries/get-saved-searches/get-saved-searches.query';
import { CreateSavedSearchDto, UpdateSavedSearchDto, SavedSearchListDto } from '../dto/saved-search.dto';

@ApiTags('saved-searches')
@ApiBearerAuth('JWT')
@UseGuards(JwtAuthGuard)
@Controller('saved-searches')
export class SavedSearchController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  @Post()
  @UseGuards(QuotaGuard)
  @RequireQuota('searches_saved')
  @ApiOperation({ summary: 'Lưu tìm kiếm', description: 'Lưu bộ lọc tìm kiếm để nhận thông báo khi có kết quả mới' })
  @ApiResponse({ status: 201, description: 'Tìm kiếm đã được lưu' })
  @ApiResponse({ status: 400, description: 'Dữ liệu không hợp lệ' })
  @ApiResponse({ status: 401, description: 'Chưa đăng nhập' })
  @ApiResponse({ status: 403, description: 'Đã đạt giới hạn gói đăng ký' })
  async create(
    @Body() dto: CreateSavedSearchDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<CreateSavedSearchResult> {
    return this.commandBus.execute(
      new CreateSavedSearchCommand(
        user.sub,
        dto.name,
        dto.filters,
        dto.alertEnabled ?? true,
      ),
    );
  }

  @Get()
  @ApiOperation({ summary: 'Danh sách tìm kiếm đã lưu', description: 'Lấy danh sách tìm kiếm đã lưu của người dùng' })
  @ApiResponse({ status: 200, description: 'Danh sách tìm kiếm đã lưu' })
  @ApiResponse({ status: 401, description: 'Chưa đăng nhập' })
  async list(
    @Query() dto: SavedSearchListDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<SavedSearchListResult> {
    return this.queryBus.execute(
      new GetSavedSearchesQuery(user.sub, dto.page ?? 1, dto.limit ?? 20),
    );
  }

  @Get(':id')
  @ApiOperation({ summary: 'Chi tiết tìm kiếm đã lưu', description: 'Lấy chi tiết một tìm kiếm đã lưu' })
  @ApiParam({ name: 'id', description: 'ID tìm kiếm đã lưu' })
  @ApiResponse({ status: 200, description: 'Chi tiết tìm kiếm đã lưu' })
  @ApiResponse({ status: 401, description: 'Chưa đăng nhập' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy' })
  async getById(
    @Param('id') id: string,
    @CurrentUser() user: JwtPayload,
  ): Promise<SavedSearchDetail> {
    return this.queryBus.execute(
      new GetSavedSearchQuery(id, user.sub),
    );
  }

  @Patch(':id')
  @ApiOperation({ summary: 'Cập nhật tìm kiếm đã lưu', description: 'Cập nhật tên, bộ lọc hoặc trạng thái thông báo' })
  @ApiParam({ name: 'id', description: 'ID tìm kiếm đã lưu' })
  @ApiResponse({ status: 200, description: 'Đã cập nhật' })
  @ApiResponse({ status: 401, description: 'Chưa đăng nhập' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy' })
  async update(
    @Param('id') id: string,
    @Body() dto: UpdateSavedSearchDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<UpdateSavedSearchResult> {
    return this.commandBus.execute(
      new UpdateSavedSearchCommand(
        id,
        user.sub,
        dto.name,
        dto.filters,
        dto.alertEnabled,
      ),
    );
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Xóa tìm kiếm đã lưu', description: 'Xóa một tìm kiếm đã lưu' })
  @ApiParam({ name: 'id', description: 'ID tìm kiếm đã lưu' })
  @ApiResponse({ status: 200, description: 'Đã xóa' })
  @ApiResponse({ status: 401, description: 'Chưa đăng nhập' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy' })
  async delete(
    @Param('id') id: string,
    @CurrentUser() user: JwtPayload,
  ): Promise<{ deleted: boolean }> {
    return this.commandBus.execute(
      new DeleteSavedSearchCommand(id, user.sub),
    );
  }
}
