import { IsNotEmpty, IsArray, IsEnum, IsOptional, IsString, IsDateString, ArrayMinSize, IsInt, IsPositive, ArrayUnique } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { AccessScopeEnum } from 'src/common/enum/access-scope.enum';
import { AccessStateEnum } from 'src/common/enum/access-state.enum';
import { Type } from 'class-transformer';

/**
 * DTO for bulk updating program access for multiple users
 * Supports adding new users and modifying/removing existing user access in a single operation
 */
export class BulkUpdateProgramAccessDto {
  @ApiProperty({
    description: 'Array of user IDs to update access for',
    type: [Number],
    example: [101, 205, 321],
  })
  @IsNotEmpty()
  @IsArray()
  @ArrayMinSize(1)
  @ArrayUnique()
  @IsInt({ each: true })
  @IsPositive({ each: true })
  @Type(() => Number)
  userIds: number[];

  @ApiPropertyOptional({
    description: 'Access scope for the users',
    enum: AccessScopeEnum,
    example: AccessScopeEnum.VIEW_ONLY,
  })
  @IsEnum(AccessScopeEnum)
  @IsOptional()
  accessScope?: AccessScopeEnum;

  @ApiPropertyOptional({
    description: 'State of the access mapping',
    enum: AccessStateEnum,
    example: AccessStateEnum.ACTIVE,
  })
  @IsEnum(AccessStateEnum)
  @IsOptional()
  state?: AccessStateEnum;

  @ApiPropertyOptional({
    description: 'When the access becomes effective (ISO 8601 format)',
    example: '2026-03-28T00:00:00.000Z',
  })
  @IsOptional()
  @IsDateString()
  effectiveFrom?: string;

  @ApiPropertyOptional({
    description: 'When the access expires (ISO 8601 format)',
    example: '2026-12-31T23:59:59.000Z',
  })
  @IsOptional()
  @IsDateString()
  effectiveTill?: string;

  @ApiPropertyOptional({
    description: 'Reason for updating access',
    example: 'Bulk access update for approved participants',
  })
  @IsOptional()
  @IsString()
  reason?: string;

  @ApiPropertyOptional({
    description: 'Additional metadata',
    example: { source: 'bulk_admin_update' },
  })
  @IsOptional()
  meta?: Record<string, any>;
}
