import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  Query,
  UseGuards,
  Request,
  UseInterceptors,
  UploadedFiles,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { AuthGuard } from '@/modules/auth/auth.guard';
import { OptionalAuthGuard } from '@/modules/auth/optional-auth.guard';
import { FeatureFlagGuard } from '@/modules/feature-flags/feature-flag.guard';
import { RequireFeature } from '@/modules/feature-flags/require-feature.decorator';
import { SensitiveRateLimitGuard } from '@/middleware/sensitive-rate-limit.guard';
import { AttestationGuard } from '@/middleware/attestation.guard';
import { ReportsService } from '@/modules/pets/reports.service';
import {
  CreateReportDto,
  UpdateReportDto,
  ReportMyPetDto,
  AddCommentDto,
  AddRewardDto,
  MarkReunitedDto,
  SearchReportsDto,
} from './pets.dto';
import { imageUploadOptions } from '@/utils/image/image-upload.options';

@Controller('pet/reports')
@UseGuards(FeatureFlagGuard)
@RequireFeature('section_reports_enabled')
export class ReportsController {
  constructor(private readonly reportsService: ReportsService) {}

  // ── Public browse routes (OptionalAuthGuard — token enriches results but is not required) ──

  @Get()
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  getAllReports(@Request() req, @Query() query: any) {
    return this.reportsService.getAllReports(req.user?.id ?? null, query);
  }

  @Get('reunited')
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  getReunitedReports(@Query('limit') limit?: string, @Query('offset') offset?: string) {
    return this.reportsService.getReunitedReports(limit, offset);
  }

  @Get('stats')
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  getReportStats() {
    return this.reportsService.getReportStats();
  }

  @Get('filter-options')
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  getReportFilterOptions() {
    return this.reportsService.getReportFilterOptions();
  }

  @Post('search')
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  searchReports(@Request() req, @Body() body: SearchReportsDto) {
    // Express maps the POST body into the same query shape getAllReports consumes.
    const query: Record<string, unknown> = {
      page: body.page ?? 0,
      limit: body.limit ?? 20,
      ...(body.status ? { status: body.status } : {}),
      ...(body.suburb ? { suburb: body.suburb } : {}),
      ...(body.pet_type ? { pet_type: body.pet_type } : {}),
      ...(body.breed?.length ? { breed: body.breed } : {}),
      ...(body.color?.length ? { color: body.color } : {}),
      ...(body.saved !== undefined ? { saved: String(body.saved) } : {}),
      ...(body.lat !== undefined ? { lat: body.lat } : {}),
      ...(body.lng !== undefined ? { lng: body.lng } : {}),
      ...(body.radius !== undefined ? { radius: body.radius } : {}),
    };
    return this.reportsService.getAllReports(req.user?.id ?? null, query);
  }

  // ── Authenticated-only routes ──

  @Get('mine')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  getMyReports(@Request() req, @Query() query: any) {
    return this.reportsService.getAllReports(req.user.id, { ...query, mine: 'true' });
  }

  @Post()
  @UseGuards(AuthGuard, SensitiveRateLimitGuard, AttestationGuard)
  @UseInterceptors(FileFieldsInterceptor([{ name: 'photos', maxCount: 15 }], imageUploadOptions(5)))
  @HttpCode(HttpStatus.CREATED)
  createReport(
    @Request() req,
    @Body() body: CreateReportDto,
    @UploadedFiles() files?: { photos?: Express.Multer.File[] },
  ) {
    return this.reportsService.createReport(req.user.id, body, files);
  }

  @Post('my-pet')
  @UseGuards(AuthGuard, SensitiveRateLimitGuard, AttestationGuard)
  @UseInterceptors(FileFieldsInterceptor([{ name: 'photos', maxCount: 15 }], imageUploadOptions(5)))
  @HttpCode(HttpStatus.CREATED)
  reportMyPet(
    @Request() req,
    @Body() body: ReportMyPetDto,
    @UploadedFiles() files?: { photos?: Express.Multer.File[] },
  ) {
    return this.reportsService.reportMyPet(req.user.id, body, files);
  }

  @Put(':id')
  @UseGuards(AuthGuard)
  @UseInterceptors(FileFieldsInterceptor([{ name: 'photos', maxCount: 15 }], imageUploadOptions(5)))
  @HttpCode(HttpStatus.OK)
  updateReport(
    @Request() req,
    @Param('id') id: string,
    @Body() body: UpdateReportDto,
    @UploadedFiles() files?: { photos?: Express.Multer.File[] },
  ) {
    return this.reportsService.updateReport(id, req.user.id, body, files);
  }

  @Delete(':id')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  deleteReport(@Request() req, @Param('id') id: string) {
    return this.reportsService.deleteReport(id, req.user.id);
  }

  @Post(':id/like')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  toggleLike(@Request() req, @Param('id') id: string) {
    return this.reportsService.toggleLike(id, req.user.id);
  }

  @Post(':id/comments')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.CREATED)
  addComment(@Request() req, @Param('id') id: string, @Body() body: AddCommentDto) {
    return this.reportsService.addComment(id, req.user.id, body);
  }

  @Post(':id/reward')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  addReward(@Param('id') id: string, @Body() body: AddRewardDto) {
    return this.reportsService.addReward(id, body);
  }

  @Post(':id/boost')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  boostReport(@Param('id') id: string) {
    return this.reportsService.boostReport(id);
  }

  @Post(':id/reunite')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  markReunited(@Request() req, @Param('id') id: string, @Body() body: MarkReunitedDto) {
    return this.reportsService.markReunited(id, req.user.id, body);
  }

  @Post(':id/save')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  savePet(@Request() req, @Param('id') id: string) {
    return this.reportsService.savePet(id, req.user.id);
  }

  @Delete(':id/save')
  @UseGuards(AuthGuard)
  @HttpCode(HttpStatus.OK)
  unsavePet(@Request() req, @Param('id') id: string) {
    return this.reportsService.unsavePet(id, req.user.id);
  }

  // ── Single report (public, UUID param) — must be last to avoid shadowing named routes ──

  @Get(':id')
  @UseGuards(OptionalAuthGuard)
  @HttpCode(HttpStatus.OK)
  getReportById(@Request() req, @Param('id') id: string) {
    return this.reportsService.getReportById(id, req.user?.id ?? null);
  }
}
