import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Query,
} from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import {
  IsDateString,
  IsEnum,
  IsOptional,
  IsString,
  IsUUID,
} from 'class-validator';
import { AccessBadgeType, AccessDirection } from '@prisma/client';
import { AccessService } from './access.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 IssueBadgeDto {
  @IsUUID() userId!: string;
  @IsUUID() complexId!: string;
  @IsOptional() @IsEnum(AccessBadgeType) type?: AccessBadgeType;
  @IsOptional() @IsString() label?: string;
  @IsOptional() @IsDateString() validUntil?: string;
  @IsOptional() @IsString() plateNumber?: string;
}

class VerifyAccessDto {
  @IsUUID() complexId!: string;
  @IsOptional() @IsString() code?: string;
  @IsOptional() @IsString() plateImageBase64?: string;
  @IsOptional() @IsEnum(AccessDirection) direction?: AccessDirection;
  @IsOptional() @IsString() gate?: string;
  @IsOptional() @IsString() apiKey?: string;
}

@ApiTags('access')
@ApiBearerAuth()
@Controller('access')
export class AccessController {
  constructor(private readonly service: AccessService) {}

  @Post('badges')
  @Roles('SUPERADMIN', 'SYNDIC', 'GARDIEN')
  issue(@CurrentUser() user: AuthenticatedUser, @Body() dto: IssueBadgeDto) {
    return this.service.issueBadge(user, {
      ...dto,
      validUntil: dto.validUntil ? new Date(dto.validUntil) : undefined,
    });
  }

  @Get('badges')
  list(@CurrentUser() user: AuthenticatedUser, @Query('complexId') complexId?: string) {
    return this.service.listBadges(user, complexId);
  }

  @Delete('badges/:id')
  @Roles('SUPERADMIN', 'SYNDIC', 'GARDIEN')
  revoke(@CurrentUser() user: AuthenticatedUser, @Param('id') id: string) {
    return this.service.revokeBadge(user, id);
  }

  @Get('logs')
  @Roles('SUPERADMIN', 'SYNDIC', 'GARDIEN')
  logs(
    @CurrentUser() user: AuthenticatedUser,
    @Query('complexId') complexId: string,
    @Query('limit') limit?: string,
  ) {
    return this.service.listLogs(user, complexId, limit ? Number(limit) : 100);
  }

  /**
   * Gate/hardware endpoint — public but should be protected by mutual TLS
   * or API key in production. In dev, accept a simple apiKey matching env.
   */
  @Public()
  @Post('verify')
  verify(@Body() dto: VerifyAccessDto) {
    const expected = process.env.GATE_API_KEY;
    if (expected && dto.apiKey !== expected) {
      return { granted: false, error: 'Invalid API key' };
    }
    return this.service.verify(dto);
  }
}
