import { TaskStatus, TaskPriority, ProjectStatus, EntityType } from "@prisma/client";
import {
  IsUUID,
  IsEnum,
  IsOptional,
  IsString,
  IsInt,
  Min,
  Max,
  MaxLength,
  IsDateString,
  IsArray,
  ValidateNested,
  IsBoolean,
} from "class-validator";
import { Type } from "class-transformer";

export class TaskFilter {
  @IsOptional()
  @IsEnum(TaskStatus, { message: "status must be a valid TaskStatus" })
  status?: TaskStatus;

  @IsOptional()
  @IsArray()
  @IsEnum(TaskStatus, { each: true, message: "statuses must be valid TaskStatus values" })
  statuses?: TaskStatus[];

  @IsOptional()
  @IsEnum(TaskPriority, { message: "priority must be a valid TaskPriority" })
  priority?: TaskPriority;

  @IsOptional()
  @IsArray()
  @IsEnum(TaskPriority, { each: true, message: "priorities must be valid TaskPriority values" })
  priorities?: TaskPriority[];

  @IsOptional()
  @IsUUID("4", { message: "assigneeId must be a valid UUID" })
  assigneeId?: string;

  @IsOptional()
  @IsUUID("4", { message: "projectId must be a valid UUID" })
  projectId?: string;

  @IsOptional()
  @IsDateString({}, { message: "dueDateFrom must be a valid ISO 8601 date string" })
  dueDateFrom?: Date;

  @IsOptional()
  @IsDateString({}, { message: "dueDateTo must be a valid ISO 8601 date string" })
  dueDateTo?: Date;

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

  @IsOptional()
  @IsBoolean()
  unassigned?: boolean;
}

export class EventFilter {
  @IsOptional()
  @IsUUID("4", { message: "projectId must be a valid UUID" })
  projectId?: string;

  @IsOptional()
  @IsDateString({}, { message: "startFrom must be a valid ISO 8601 date string" })
  startFrom?: Date;

  @IsOptional()
  @IsDateString({}, { message: "startTo must be a valid ISO 8601 date string" })
  startTo?: Date;

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

  @IsOptional()
  @IsBoolean()
  upcoming?: boolean;
}

export class ProjectFilter {
  @IsOptional()
  @IsEnum(ProjectStatus, { message: "status must be a valid ProjectStatus" })
  status?: ProjectStatus;

  @IsOptional()
  @IsArray()
  @IsEnum(ProjectStatus, { each: true, message: "statuses must be valid ProjectStatus values" })
  statuses?: ProjectStatus[];

  @IsOptional()
  @IsDateString({}, { message: "startDateFrom must be a valid ISO 8601 date string" })
  startDateFrom?: Date;

  @IsOptional()
  @IsDateString({}, { message: "startDateTo must be a valid ISO 8601 date string" })
  startDateTo?: Date;
}

export class BrainQueryDto {
  @IsUUID("4", { message: "workspaceId must be a valid UUID" })
  workspaceId!: string;

  @IsOptional()
  @IsString()
  @MaxLength(500, { message: "query must not exceed 500 characters" })
  query?: string;

  @IsOptional()
  @IsArray()
  @IsEnum(EntityType, { each: true, message: "entities must be valid EntityType values" })
  entities?: EntityType[];

  @IsOptional()
  @ValidateNested()
  @Type(() => TaskFilter)
  tasks?: TaskFilter;

  @IsOptional()
  @ValidateNested()
  @Type(() => EventFilter)
  events?: EventFilter;

  @IsOptional()
  @ValidateNested()
  @Type(() => ProjectFilter)
  projects?: ProjectFilter;

  @IsOptional()
  @IsString()
  @MaxLength(500, { message: "search must not exceed 500 characters" })
  search?: string;

  @IsOptional()
  @Type(() => Number)
  @IsInt({ message: "limit must be an integer" })
  @Min(1, { message: "limit must be at least 1" })
  @Max(100, { message: "limit must not exceed 100" })
  limit?: number;
}

export class BrainContextDto {
  @IsUUID("4", { message: "workspaceId must be a valid UUID" })
  workspaceId!: string;

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

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

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

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(30)
  eventDays?: number;
}

export class BrainSearchDto {
  @IsOptional()
  @IsString()
  @MaxLength(500, { message: "q must not exceed 500 characters" })
  q?: string;

  @IsOptional()
  @Type(() => Number)
  @IsInt({ message: "limit must be an integer" })
  @Min(1, { message: "limit must be at least 1" })
  @Max(100, { message: "limit must not exceed 100" })
  limit?: number;
}
