import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
} from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import {
  IsArray,
  IsBoolean,
  IsDateString,
  IsEnum,
  IsOptional,
  IsString,
  IsUUID,
} from 'class-validator';
import { AnnouncementAudience, ParkingReportStatus } from '@prisma/client';
import { CommunityService } from './community.service';
import { Roles } from '../../common/decorators/roles.decorator';
import { Public } from '../../common/decorators/public.decorator';
import {
  CurrentUser,
  AuthenticatedUser,
} from '../../common/decorators/current-user.decorator';

class CreateVisitorPassDto {
  @IsUUID() complexId!: string;
  @IsString() visitorName!: string;
  @IsOptional() @IsString() visitorPhone?: string;
  @IsOptional() @IsString() purpose?: string;
  @IsOptional() @IsDateString() validFrom?: string;
  @IsDateString() validUntil!: string;
}

class ScanVisitorPassDto {
  @IsString() qrToken!: string;
}

class CreateParkingReportDto {
  @IsUUID() complexId!: string;
  @IsString() plateNumber!: string;
  @IsOptional() @IsString() spot?: string;
  @IsOptional() @IsString() photoUrl?: string;
  @IsOptional() @IsString() description?: string;
}

class UpdateParkingStatusDto {
  @IsEnum(ParkingReportStatus) status!: ParkingReportStatus;
}

class CreateAnnouncementDto {
  @IsUUID() complexId!: string;
  @IsString() title!: string;
  @IsString() body!: string;
  @IsOptional() @IsEnum(AnnouncementAudience) audience?: AnnouncementAudience;
  @IsOptional() @IsDateString() expiresAt?: string;
  @IsOptional() @IsBoolean() pinned?: boolean;
}

class CreateThreadDto {
  @IsString() complexId!: string;
  @IsString() subject!: string;
  @IsArray() @IsString({ each: true }) participantIds!: string[];
}

class PostMessageDto {
  @IsString() body!: string;
}

@ApiTags('community')
@ApiBearerAuth()
@Controller()
export class CommunityController {
  constructor(private readonly service: CommunityService) {}

  // ----- Visitor passes -----

  @Post('visitor-passes')
  createPass(@CurrentUser() u: AuthenticatedUser, @Body() dto: CreateVisitorPassDto) {
    return this.service.createVisitorPass(u, {
      ...dto,
      validFrom: dto.validFrom ? new Date(dto.validFrom) : undefined,
      validUntil: new Date(dto.validUntil),
    });
  }

  @Get('visitor-passes')
  listPasses(
    @CurrentUser() u: AuthenticatedUser,
    @Query('complexId') complexId?: string,
  ) {
    return this.service.listVisitorPasses(u, complexId);
  }

  @Delete('visitor-passes/:id')
  revokePass(@CurrentUser() u: AuthenticatedUser, @Param('id') id: string) {
    return this.service.revokeVisitorPass(u, id);
  }

  /** Gate scanner — public with API key (hardware station) */
  @Public()
  @Post('visitor-passes/scan')
  scan(@Body() dto: ScanVisitorPassDto & { apiKey?: string }) {
    const expected = process.env.GATE_API_KEY;
    if (expected && dto.apiKey !== expected) {
      return { granted: false, reason: 'BAD_API_KEY' };
    }
    return this.service.scanVisitorPass(dto.qrToken);
  }

  // ----- Parking reports -----

  @Post('parking-reports')
  report(@CurrentUser() u: AuthenticatedUser, @Body() dto: CreateParkingReportDto) {
    return this.service.createParkingReport(u, dto);
  }

  @Get('parking-reports')
  listReports(@CurrentUser() u: AuthenticatedUser, @Query('complexId') complexId?: string) {
    return this.service.listParkingReports(u, complexId);
  }

  @Get('parking-reports/resolve/:plate')
  @Roles('SUPERADMIN', 'SYNDIC', 'GARDIEN')
  resolvePlate(@CurrentUser() u: AuthenticatedUser, @Param('plate') plate: string) {
    return this.service.resolvePlate(u, plate);
  }

  @Patch('parking-reports/:id/status')
  @Roles('SUPERADMIN', 'SYNDIC', 'GARDIEN')
  updateStatus(
    @CurrentUser() u: AuthenticatedUser,
    @Param('id') id: string,
    @Body() dto: UpdateParkingStatusDto,
  ) {
    return this.service.updateParkingStatus(u, id, dto.status);
  }

  // ----- Announcements -----

  @Post('announcements')
  @Roles('SUPERADMIN', 'SYNDIC')
  createAnn(@CurrentUser() u: AuthenticatedUser, @Body() dto: CreateAnnouncementDto) {
    return this.service.createAnnouncement(u, {
      ...dto,
      expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : undefined,
    });
  }

  @Get('announcements')
  listAnn(@CurrentUser() u: AuthenticatedUser, @Query('complexId') complexId: string) {
    return this.service.listAnnouncements(u, complexId);
  }

  @Delete('announcements/:id')
  @Roles('SUPERADMIN', 'SYNDIC')
  deleteAnn(@CurrentUser() u: AuthenticatedUser, @Param('id') id: string) {
    return this.service.deleteAnnouncement(u, id);
  }

  // ----- Messaging -----

  @Post('message-threads')
  createThread(@CurrentUser() u: AuthenticatedUser, @Body() dto: CreateThreadDto) {
    return this.service.createThread(u, dto);
  }

  @Get('message-threads')
  listThreads(@CurrentUser() u: AuthenticatedUser, @Query('complexId') complexId?: string) {
    return this.service.listThreads(u, complexId);
  }

  @Get('message-threads/:id/messages')
  listMessages(@CurrentUser() u: AuthenticatedUser, @Param('id') id: string) {
    return this.service.listMessages(u, id);
  }

  @Post('message-threads/:id/messages')
  post(
    @CurrentUser() u: AuthenticatedUser,
    @Param('id') id: string,
    @Body() dto: PostMessageDto,
  ) {
    return this.service.postMessage(u, id, dto.body);
  }
}
