import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsBoolean, IsEnum, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, ValidateIf, ValidateNested } from "class-validator";
import mongoose from "mongoose";

export class File {
    @ApiProperty({ example: 'id', required: true, description: 'File Id' })
    @IsNotEmpty({ message: 'File Id is required' })
    @IsString({ message: 'File Id must be a string' })
    id: string;

    @ApiProperty({ example: 'name', required: true, description: 'File Name' })
    @IsNotEmpty({ message: 'File Name is required' })
    @IsString({ message: 'File Name must be a string' })
    name: string;

    @ApiProperty({ example: 'mimeType', required: true, description: 'File Mime Type' })
    @IsNotEmpty({ message: 'File Mime Type is required' })
    @IsString({ message: 'File Mime Type must be a string' })
    mimeType: string;

    @ApiProperty({ example: 'size', required: true, description: 'File Size' })
    @IsNotEmpty({ message: 'File Size is required' })
    @IsNumber({}, { message: 'File Size must be a number' })
    size: number;
}


export class ChatDto {
    _id?: string | mongoose.Types.ObjectId;

    @ApiProperty({ example: 'Hello', required: true, description: 'Content' })
    @IsString({ message: 'Content must be a string' })
    @ValidateIf((o) => o.type !== 'file')
    content: string;

    @ApiProperty({ example: 'text', required: true, description: 'Type', enum: ['text', 'image', 'url', 'file'] })
    @IsEnum(['text', 'image', 'url', 'file'], { message: 'Type must be a enum' })
    @IsString({ message: 'Type must be a string' })
    type: 'text' | 'image' | 'url' | 'file';


    @ApiProperty({ example: File, required: true, description: 'File', type: File })
    @Type(() => File)
    // @IsOptional()
    @IsNotEmpty({ message: 'File is required' })
    @ValidateIf((o) => o.type === 'file')
    // @IsObject({ message: 'File must be a object' })
    @ValidateNested({ each: true, message: 'File must be a object' })
    file?: File;

    @ApiProperty({ example: { documentContent: '' }, required: false, description: 'Metadata including document content for file messages' })
    @IsOptional()
    @IsObject({ message: 'Metadata must be an object' })
    metadata?: { documentContent?: string; isVoiceMessage?: boolean };

    @ApiProperty({ example: 'gemini-2.5-flash', required: false, description: 'Per-message model override. When set, this model is used for this request only without mutating the user subscription default.' })
    @IsOptional()
    @IsString({ message: 'Model must be a string' })
    model?: string;

    @ApiProperty({ example: 'Be concise.', required: false, description: 'Optional system prompt override for this message.' })
    @IsOptional()
    @IsString()
    systemPrompt?: string;

    createdAt?: Date;
    updatedAt?: Date;
}


export class CreateConversationDto {
    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: false, description: 'Conversation Id' })
    @IsString({ message: 'Conversation Id must be a string' })
    conversationId: string | null | undefined;

    @ApiProperty({ example: ChatDto, required: true, description: 'Chat' })
    @IsObject({ message: 'Chat must be a object' })
    @ValidateNested({ each: true, message: 'Chat must be a object' })
    chat: ChatDto;

    @ApiProperty({ example: 'summary', required: false, description: 'Type', enum: ['summary', 'analysis', 'extract', 'translate'] })
    @IsOptional()
    @IsEnum(['summary', 'analysis', 'extract', 'translate'], { message: 'Type must be a enum' })
    @IsString({ message: 'Type must be a string' })
    instructionType?: 'summary' | 'analysis' | 'extract' | 'translate';

    @ApiProperty({ example: 'unified', required: false, description: 'Conversation kind: classic chat or unified chat (text + image)', enum: ['chat', 'unified'] })
    @IsOptional()
    @IsEnum(['chat', 'unified'], { message: 'mode must be one of chat / unified' })
    mode?: 'chat' | 'unified';
}


export class AppendImageMessageDto {
    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: false, description: 'Conversation Id (omit to create a new unified conversation)' })
    @IsOptional()
    @IsString()
    conversationId?: string;

    @ApiProperty({ example: 'A cat in a hat', required: true, description: 'The user prompt that produced the image' })
    @IsString()
    prompt: string;

    @ApiProperty({ example: ['https://cdn/.../img1.png'], required: true, description: 'URLs of the generated images' })
    images: string[];

    @ApiProperty({ example: '6890be...', required: false, description: 'image-history record id, for cross-reference' })
    @IsOptional()
    @IsString()
    imageHistoryId?: string;

    @ApiProperty({ example: 'flux-1.1-pro', required: false })
    @IsOptional()
    @IsString()
    model?: string;

    @ApiProperty({ example: '16:9', required: false })
    @IsOptional()
    @IsString()
    aspectRatio?: string;

    @ApiProperty({ example: 'Photorealistic', required: false })
    @IsOptional()
    @IsString()
    style?: string;
}


export class UpdateConversationDto {
    @ApiProperty({ example: 'title', required: false, description: 'Title' })
    @IsOptional()
    @IsString({ message: 'Title must be a string' })
    title: string;

    @ApiProperty({ example: true, required: false, description: 'Mark this conversation as favorite' })
    @IsOptional()
    @IsBoolean({ message: 'Favorite must be a boolean' })
    favorite: boolean;
}


export class RegenerateConversationDto {
    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: false, description: 'Conversation Id' })
    @IsOptional()
    @IsString({ message: 'Conversation Id must be a string' })
    conversationId?: string;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: false, description: 'Message Id' })
    @IsOptional()
    @IsString({ message: 'Message Id must be a string' })
    messageId?: string;

    @ApiProperty({ example: ChatDto, required: false, description: 'Chat' })
    @IsOptional()
    @IsObject({ message: 'Chat must be a object' })
    @ValidateNested({ each: true, message: 'Chat must be a object' })
    chat?: ChatDto;
}

export class UpdateMessageDto {
    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Conversation Id' })
    @IsString({ message: 'Conversation Id must be a string' })
    conversationId: string;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Message Id' })
    @IsString({ message: 'Message Id must be a string' })
    messageId: string;

    @ApiProperty({ example: ChatDto, required: true, description: 'Chat' })
    @IsObject({ message: 'Chat must be a object' })
    @ValidateNested({ each: true, message: 'Chat must be a object' })
    chat: ChatDto;
}




export class LikeDislikeConversationDto {
    @ApiProperty({ example: true, required: true, description: 'Like' })
    @IsOptional()
    @IsBoolean({ message: 'Like must be a boolean' })
    like: boolean;

    @ApiProperty({ example: false, required: true, description: 'Dislike' })
    @IsOptional()
    @IsBoolean({ message: 'Dislike must be a boolean' })
    dislike: boolean;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Conversation Id' })
    @IsString({ message: 'Conversation Id must be a string' })
    conversationId: string;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Message Id' })
    @IsString({ message: 'Message Id must be a string' })
    messageId: string;


    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: false, description: 'Part Id' })
    @IsOptional()
    @IsString({ message: 'Part Id must be a string' })
    partId: string;
}





export class CreateChatTestingDto {
    @ApiProperty({ example: 'Hi, How are you?', required: true, description: 'prompt' })
    @IsString({ message: 'Prompt must be a string' })
    prompt: string;

    @ApiProperty({ example: 'user', required: true, description: 'Testing for', enum: ['user', 'admin'] })
    @IsEnum(['user', 'admin'], { message: 'Testing for must be a enum' })
    @IsString({ message: 'Testing for must be a string' })
    role: 'user' | 'admin';
}




export class RetryConversationDto {
    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Conversation Id' })
    @IsString({ message: 'Conversation Id must be a string' })
    conversationId: string;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Message Id' })
    @IsString({ message: 'Message Id must be a string' })
    messageId: string;

    @ApiProperty({ example: '6589aa78f388292838d6e92b', required: true, description: 'Retry Id' })
    @IsString({ message: 'Retry Id must be a string' })
    retryId: string;
}
