import { Body, Controller, Post } from '@nestjs/common';
import { ApiBadRequestResponse, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { UserRole } from '@prisma/client';
import { CurrentUser } from '../common/current-user.decorator';
import { RequireRole } from '../auth/require-role.decorator';
import { RequestUser } from '../common/request-user';
import { FeatureKey } from '../features/feature-catalog';
import { RequireFeature } from '../features/require-feature.decorator';
import {
  ApiNotFoundError,
  ApiProtectedEndpoint,
  ApiValidationError,
  ESTATE_ID_EXAMPLE,
  GUARD_ID_EXAMPLE,
  VISIT_SESSION_ID_EXAMPLE,
  VISITOR_PASS_ID_EXAMPLE
} from '../common/swagger-docs';
import { CheckinService } from './checkin.service';
import { CheckoutDto, ManualCheckinDto, ScanCheckinDto } from './dto/checkin.dto';

@ApiTags('Checkin')
@ApiProtectedEndpoint()
@Controller({ path: 'checkin', version: '1' })
export class CheckinController {
  constructor(private readonly checkinService: CheckinService) {}

  @Post('scan')
  @RequireRole(UserRole.GUARD)
  @RequireFeature(FeatureKey.CHECKIN_SCAN)
  @ApiOperation({
    summary: 'Check in visitor by QR token',
    description:
      'Validates guard identity, estate scope, pass status, validity window, and remaining entries before creating a visit session.'
  })
  @ApiBody({ type: ScanCheckinDto })
  @ApiResponse({
    status: 201,
    description: 'Visitor checked in.',
    schema: {
      example: {
        id: VISIT_SESSION_ID_EXAMPLE,
        estateId: ESTATE_ID_EXAMPLE,
        visitorPassId: VISITOR_PASS_ID_EXAMPLE,
        guardId: GUARD_ID_EXAMPLE,
        deviceId: 'gate-tablet-001',
        entryGate: 'Main Gate',
        status: 'CHECKED_IN',
        checkinTime: '2026-05-16T12:00:00.000Z'
      }
    }
  })
  @ApiBadRequestResponse({
    description: 'Pass is inactive, expired, outside validity window, exhausted, or guard identity does not match.',
    schema: { example: { statusCode: 400, message: 'Visitor pass has no remaining entries', error: 'Bad Request' } }
  })
  @ApiNotFoundError('Visitor pass or active guard')
  @ApiValidationError()
  scan(@Body() dto: ScanCheckinDto, @CurrentUser() user: RequestUser) {
    return this.checkinService.checkinByQr(dto, user);
  }

  @Post('manual')
  @RequireRole(UserRole.GUARD)
  @RequireFeature(FeatureKey.CHECKIN_MANUAL)
  @ApiOperation({
    summary: 'Check in visitor by manual code',
    description:
      'Uses the manual visitor code instead of QR token, then applies the same guard, estate, status, time-window, and entry-count validation.'
  })
  @ApiBody({ type: ManualCheckinDto })
  @ApiResponse({
    status: 201,
    description: 'Visitor checked in.',
    schema: {
      example: {
        id: VISIT_SESSION_ID_EXAMPLE,
        estateId: ESTATE_ID_EXAMPLE,
        visitorPassId: VISITOR_PASS_ID_EXAMPLE,
        guardId: GUARD_ID_EXAMPLE,
        deviceId: 'gate-tablet-001',
        entryGate: 'Main Gate',
        status: 'CHECKED_IN'
      }
    }
  })
  @ApiBadRequestResponse({
    description: 'Pass is inactive, expired, outside validity window, exhausted, or guard identity does not match.',
    schema: { example: { statusCode: 400, message: 'Visitor pass is outside its validity window', error: 'Bad Request' } }
  })
  @ApiNotFoundError('Visitor pass or active guard')
  @ApiValidationError()
  manual(@Body() dto: ManualCheckinDto, @CurrentUser() user: RequestUser) {
    return this.checkinService.checkinByCode(dto, user);
  }

  @Post('checkout')
  @RequireRole(UserRole.GUARD)
  @RequireFeature(FeatureKey.CHECKOUT)
  @ApiOperation({
    summary: 'Check out visitor',
    description: 'Closes an open visit session and records exit gate, checkout time, and checkout audit log.'
  })
  @ApiBody({ type: CheckoutDto })
  @ApiResponse({
    status: 201,
    description: 'Visitor checked out.',
    schema: {
      example: {
        id: VISIT_SESSION_ID_EXAMPLE,
        estateId: ESTATE_ID_EXAMPLE,
        visitorPassId: VISITOR_PASS_ID_EXAMPLE,
        guardId: GUARD_ID_EXAMPLE,
        deviceId: 'gate-tablet-001',
        exitGate: 'Main Gate',
        status: 'CHECKED_OUT',
        checkoutTime: '2026-05-16T13:00:00.000Z'
      }
    }
  })
  @ApiBadRequestResponse({
    description: 'Visit session is already checked out or guard identity does not match.',
    schema: { example: { statusCode: 400, message: 'Visit session is already checked out', error: 'Bad Request' } }
  })
  @ApiNotFoundError('Visit session or active guard')
  @ApiValidationError()
  checkout(@Body() dto: CheckoutDto, @CurrentUser() user: RequestUser) {
    return this.checkinService.checkout(dto, user);
  }
}
