import type { ChannelAttachmentDto } from '@mosaicstack/types';
import { Transform, Type } from 'class-transformer';
import {
  IsNotEmpty,
  IsObject,
  IsOptional,
  IsString,
  IsUUID,
  MaxLength,
  ValidateNested,
} from 'class-validator';

export class ChatRequestDto {
  @IsOptional()
  @IsUUID()
  conversationId?: string;

  @IsString()
  @MaxLength(10_000)
  content!: string;
}

export class ChatSocketMessageDto {
  @IsOptional()
  @IsUUID()
  conversationId?: string;

  @IsString()
  @MaxLength(10_000)
  content!: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  provider?: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  modelId?: string;

  @IsOptional()
  @IsUUID()
  agentId?: string;

  /** Validated channel attachment references; binary content is not embedded. */
  attachments?: readonly ChannelAttachmentDto[];
}

/**
 * Task Five, group 2 — the frozen pi-rpc `turn:send` selection triple.
 *
 * Each id is a required, non-empty, bounded string. There is no `@IsOptional` and no extra
 * field: under `forbidNonWhitelisted` an unknown selection key is rejected, and a missing id
 * fails `@IsString` (undefined is not a string) rather than silently passing.
 */
export class HarnessTurnSelectionDto {
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  harnessId!: string;

  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  providerId!: string;

  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  modelId!: string;
}

/**
 * Task Five, group 2 — the frozen wire contract for a pi-rpc `turn:send`.
 *
 * Validated through the production `ValidationPipe({ whitelist, forbidNonWhitelisted, transform })`:
 * a UUID conversation id; `content` trimmed then bounded to 1..10_000 characters (whitespace-only
 * collapses to empty and fails `@IsNotEmpty`); a nested `selection` object recursed with an
 * explicit `@Type` (a bare `@ValidateNested` is masked green by class-validator's empty-metadata
 * `unknownValue`); and a UUID-v4 idempotency key. No `provider`/`modelId`/`attachments` or other
 * authority field is declared, so `forbidNonWhitelisted` rejects every unknown top-level key.
 */
export class HarnessTurnSendDto {
  @IsUUID()
  conversationId!: string;

  @Transform(({ value }) => (typeof value === 'string' ? value.trim() : value))
  @IsString()
  @IsNotEmpty()
  @MaxLength(10_000)
  content!: string;

  @IsObject()
  @ValidateNested()
  @Type(() => HarnessTurnSelectionDto)
  selection!: HarnessTurnSelectionDto;

  @IsUUID('4')
  idempotencyKey!: string;
}
