import {
  IsString,
  IsOptional,
  IsNumber,
  IsBoolean,
  IsEnum,
  IsInt,
  Min,
  MaxLength,
  Matches,
  ValidateIf,
} from 'class-validator';
import { Type } from 'class-transformer';
import { COMPANY_ID_PATTERN } from '../error-codes';

export enum GeoPolicy {
  STRICT_BLOCK = 'STRICT_BLOCK',
  ALLOW_WITH_FLAG = 'ALLOW_WITH_FLAG',
  SKIP = 'SKIP',
}

export enum AccessMode {
  PUBLIC = 'PUBLIC',
  SIGNED = 'SIGNED',
}

export class CreateCheckpointDto {
  @IsString()
  @MaxLength(200)
  name!: string;

  @IsOptional()
  @IsString()
  description?: string;

  @IsOptional()
  @IsString()
  @MaxLength(500)
  address?: string;

  @IsString()
  timezone!: string;

  @IsNumber()
  @Type(() => Number)
  latitude!: number;

  @IsNumber()
  @Type(() => Number)
  longitude!: number;

  @IsOptional()
  @IsEnum(GeoPolicy)
  geoPolicy?: GeoPolicy;

  @IsOptional()
  @IsNumber()
  @Min(100)
  @Type(() => Number)
  geoRadius?: number;

  @IsOptional()
  @IsNumber()
  @Min(10)
  @Type(() => Number)
  geoAccuracyThreshold?: number;

  @IsOptional()
  @IsBoolean()
  allowUnauthenticatedCheckin?: boolean;

  // v1.5
  @IsOptional()
  @IsEnum(AccessMode)
  accessMode?: AccessMode;

  @IsOptional()
  @ValidateIf((_, v) => v !== null)
  @IsInt()
  @Min(60)
  @Type(() => Number)
  qrRotationSeconds?: number | null;

  @IsOptional()
  @IsInt()
  @Min(0)
  @Type(() => Number)
  qrGraceSeconds?: number;

  @IsOptional()
  @IsBoolean()
  sharedCheckinEnabled?: boolean;

  @IsOptional()
  @IsString()
  @MaxLength(64)
  @Matches(COMPANY_ID_PATTERN)
  sharedCompanyId?: string;

  @IsOptional()
  @IsString()
  @MaxLength(200)
  sharedCompanyLabel?: string;
}

export class UpdateCheckpointDto {
  @IsOptional()
  @IsString()
  @MaxLength(200)
  name?: string;

  @IsOptional()
  @IsString()
  description?: string;

  @IsOptional()
  @IsString()
  @MaxLength(500)
  address?: string;

  @IsOptional()
  @IsString()
  timezone?: string;

  @IsOptional()
  @IsNumber()
  @Type(() => Number)
  latitude?: number;

  @IsOptional()
  @IsNumber()
  @Type(() => Number)
  longitude?: number;

  @IsOptional()
  @IsEnum(GeoPolicy)
  geoPolicy?: GeoPolicy;

  @IsOptional()
  @IsNumber()
  @Min(100)
  @Type(() => Number)
  geoRadius?: number;

  @IsOptional()
  @IsNumber()
  @Min(10)
  @Type(() => Number)
  geoAccuracyThreshold?: number;

  @IsOptional()
  @IsBoolean()
  allowUnauthenticatedCheckin?: boolean;

  @IsOptional()
  @IsBoolean()
  isActive?: boolean;

  // v1.5
  @IsOptional()
  @IsEnum(AccessMode)
  accessMode?: AccessMode;

  @IsOptional()
  @ValidateIf((_, v) => v !== null)
  @IsInt()
  @Min(60)
  @Type(() => Number)
  qrRotationSeconds?: number | null;

  @IsOptional()
  @IsInt()
  @Min(0)
  @Type(() => Number)
  qrGraceSeconds?: number;

  @IsOptional()
  @IsBoolean()
  sharedCheckinEnabled?: boolean;

  @IsOptional()
  @IsString()
  @MaxLength(64)
  @Matches(COMPANY_ID_PATTERN)
  sharedCompanyId?: string;

  @IsOptional()
  @IsString()
  @MaxLength(200)
  sharedCompanyLabel?: string;
}
