import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { ApiBody, ApiOperation, ApiQuery, 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 { ApiProtectedEndpoint, ApiValidationError, ESTATE_ID_EXAMPLE, RESIDENT_ID_EXAMPLE, VISITOR_PASS_ID_EXAMPLE } from '../common/swagger-docs';
import { OfflineSyncDto } from './dto/offline.dto';
import { OfflineService } from './offline.service';

@ApiTags('Offline')
@ApiProtectedEndpoint()
@Controller({ path: 'offline', version: '1' })
export class OfflineController {
  constructor(private readonly offlineService: OfflineService) {}

  @Get('bootstrap')
  @RequireRole(UserRole.GUARD, UserRole.ESTATE_ADMIN, UserRole.SECURITY_SUPERVISOR)
  @RequireFeature(FeatureKey.OFFLINE_BOOTSTRAP)
  @ApiOperation({
    summary: 'Bootstrap offline gate data',
    description: 'Downloads active passes, active residents, and recent audit logs for offline-capable gate devices.'
  })
  @ApiQuery({ name: 'estateId', required: true, example: ESTATE_ID_EXAMPLE, description: 'Estate to bootstrap.' })
  @ApiResponse({
    status: 200,
    description: 'Offline data returned.',
    schema: {
      example: {
        serverTime: '2026-05-16T12:00:00.000Z',
        activePasses: [{ id: VISITOR_PASS_ID_EXAMPLE, estateId: ESTATE_ID_EXAMPLE, status: 'ACTIVE' }],
        residents: [{ id: RESIDENT_ID_EXAMPLE, name: 'Ade Okafor', unit: 'A12', phone: '+2348000000003' }],
        recentLogs: []
      }
    }
  })
  bootstrap(@CurrentUser() user: RequestUser, @Query('estateId') estateId: string) {
    return this.offlineService.bootstrap(user, estateId);
  }

  @Post('sync')
  @RequireRole(UserRole.GUARD, UserRole.ESTATE_ADMIN, UserRole.SECURITY_SUPERVISOR)
  @RequireFeature(FeatureKey.OFFLINE_SYNC)
  @ApiOperation({
    summary: 'Submit offline event batch',
    description:
      'Stores client offline event records idempotently by deviceId and clientEventId. Domain replay is not yet implemented.'
  })
  @ApiBody({ type: OfflineSyncDto })
  @ApiResponse({
    status: 201,
    description: 'Offline events accepted.',
    schema: {
      example: {
        accepted: 1,
        items: [
          {
            id: 'offline-sync-item-uuid',
            estateId: ESTATE_ID_EXAMPLE,
            deviceId: 'guard-device-001',
            clientEventId: 'offline-event-001',
            eventType: 'VISITOR_CHECKED_IN',
            status: 'APPLIED'
          }
        ]
      }
    }
  })
  @ApiValidationError()
  sync(@Body() dto: OfflineSyncDto, @CurrentUser() user: RequestUser) {
    return this.offlineService.sync(dto, user);
  }
}
