import {
  IsBoolean,
  IsIn,
  IsObject,
  IsOptional,
  IsString,
  MaxLength,
  MinLength,
  ValidateNested,
} from 'class-validator';
import { Transform, TransformFnParams, Type } from 'class-transformer';
import { AI_DRIVERS, AiDriver } from '../../../../integrations/ai/ai.types';

/**
 * Optional per-role model override. `chatModel` swaps the model id; `driver`
 * (optional) switches the provider — when set it must be a supported driver and
 * its creds must already exist (enforced at resolve time with a clear 503).
 */
export class RoleModelConfigDto {
  @IsOptional()
  @IsIn(AI_DRIVERS)
  driver?: AiDriver;

  // Free-form provider model id (providers add models constantly, so we don't
  // pin an allow-list). We still reject empty/whitespace-only garbage at the API
  // boundary: trim first, then require a non-empty, bounded string. An invalid
  // model still surfaces as a clear provider 503 at resolve time, not here.
  @IsOptional()
  @Transform(({ value }: TransformFnParams) =>
    typeof value === 'string' ? value.trim() : value,
  )
  @IsString()
  @MinLength(1)
  @MaxLength(200)
  chatModel?: string;
}

/** Admin create payload for an agent role. */
export class CreateAgentRoleDto {
  @IsString()
  @MaxLength(200)
  name: string;

  @IsOptional()
  @IsString()
  @MaxLength(32)
  emoji?: string;

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

  @IsString()
  @MaxLength(20000)
  instructions: string;

  // null/omitted => use the workspace default model.
  @IsOptional()
  @IsObject()
  @ValidateNested()
  @Type(() => RoleModelConfigDto)
  modelConfig?: RoleModelConfigDto | null;

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

  // Whether picking this role auto-sends a launch message and starts the chat.
  // Omitted => default true (preserves the previous always-auto-start behavior).
  @IsOptional()
  @IsBoolean()
  autoStart?: boolean;

  // Optional custom auto-start text. Trimmed at the boundary (like chatModel);
  // empty/whitespace-only => the client falls back to its default launch message.
  @IsOptional()
  @Transform(({ value }: TransformFnParams) =>
    typeof value === 'string' ? value.trim() : value,
  )
  @IsString()
  @MaxLength(2000)
  launchMessage?: string;
}

/** Admin update payload for an agent role (all fields optional). */
export class UpdateAgentRoleDto {
  @IsOptional()
  @IsString()
  @MaxLength(200)
  name?: string;

  @IsOptional()
  @IsString()
  @MaxLength(32)
  emoji?: string;

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

  @IsOptional()
  @IsString()
  @MaxLength(20000)
  instructions?: string;

  @IsOptional()
  @IsObject()
  @ValidateNested()
  @Type(() => RoleModelConfigDto)
  modelConfig?: RoleModelConfigDto | null;

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

  // Whether picking this role auto-sends a launch message and starts the chat.
  @IsOptional()
  @IsBoolean()
  autoStart?: boolean;

  // Optional custom auto-start text. Trimmed at the boundary (like chatModel);
  // empty/whitespace-only => the client falls back to its default launch message.
  @IsOptional()
  @Transform(({ value }: TransformFnParams) =>
    typeof value === 'string' ? value.trim() : value,
  )
  @IsString()
  @MaxLength(2000)
  launchMessage?: string;
}
