import { Type } from 'class-transformer';
import { IsBoolean, IsIn, IsNotEmpty, IsNumber, IsOptional, IsString, Length, Matches, Max, Min, ValidateIf } from 'class-validator';
import { MALL_SKIN_ITEMS } from '../mall/mall_catalog';

export const TEST_LAB_MAP_IDS = ['whale_port', 'work_zone', 'whale_cafe'] as const;
export type TestLabMapId = (typeof TEST_LAB_MAP_IDS)[number];
export const TEST_LAB_SKIN_IDS = MALL_SKIN_ITEMS.map((item) => item.skinId).filter((skinId): skinId is string => Boolean(skinId));
const TEST_LAB_NICKNAME_PATTERN = /^[\u4E00-\u9FFF A-Za-z0-9_-]+$/;

export class CreateTestLabActorDto {
  @IsString()
  @IsNotEmpty()
  @Length(1, 32)
  @Matches(TEST_LAB_NICKNAME_PATTERN, { message: '昵称仅支持中文、字母、数字、空格、下划线和连字符' })
  nickname: string;

  @IsIn(TEST_LAB_MAP_IDS)
  mapId: TestLabMapId;

  @Type(() => Number)
  @IsNumber()
  @Min(-8192)
  @Max(8192)
  x: number;

  @Type(() => Number)
  @IsNumber()
  @Min(-8192)
  @Max(8192)
  y: number;

  @IsOptional()
  @IsIn(TEST_LAB_SKIN_IDS)
  skinId?: string;
}

export class UpdateTestLabActorDto {
  @IsOptional()
  @IsBoolean()
  online?: boolean;

  @ValidateIf((value) => value.mapId !== undefined)
  @IsIn(TEST_LAB_MAP_IDS)
  mapId?: TestLabMapId;

  @IsOptional()
  @Type(() => Number)
  @IsNumber()
  @Min(-8192)
  @Max(8192)
  x?: number;

  @IsOptional()
  @Type(() => Number)
  @IsNumber()
  @Min(-8192)
  @Max(8192)
  y?: number;

  @IsOptional()
  @IsIn(TEST_LAB_SKIN_IDS)
  skinId?: string;
}

export class TestLabMessageDto {
  @IsIn(['local', 'global', 'private'])
  scope: 'local' | 'global' | 'private';

  @IsString()
  @IsNotEmpty()
  @Length(1, 1000)
  content: string;

  @ValidateIf((value) => value.scope === 'private')
  @IsString()
  @IsNotEmpty()
  targetUserId?: string;
}

export class TestLabSocialActionDto {
  @IsIn(['friend_request', 'friend_accept', 'friend_reject', 'block'])
  action: 'friend_request' | 'friend_accept' | 'friend_reject' | 'block';

  @IsString()
  @IsNotEmpty()
  targetUserId: string;
}

export class TestLabRoomPolicyDto {
  @IsIn(['friends', 'public', 'closed'])
  roomVisitPolicy: 'friends' | 'public' | 'closed';
}
