import {
  IsBoolean,
  IsArray,
  IsDateString,
  IsEnum,
  IsIn,
  IsNotEmpty,
  IsObject,
  IsOptional,
  IsString,
  ValidateNested,
  MinLength,
} from 'class-validator';
import { Type } from 'class-transformer';
import type { MonitorTargetType } from './monitor-target.entity';

const monitorTargetTypeEnum = {
  http: 'http',
  tcp: 'tcp',
  redis: 'redis',
  rabbitmq: 'rabbitmq',
  elasticsearch: 'elasticsearch',
  'java-app': 'java-app',
} as const;

const targetStatusEnum = {
  enabled: 'enabled',
  disabled: 'disabled',
} as const;

const agentPlatformEnum = {
  linux: 'linux',
  windows: 'windows',
} as const;

const packageArchEnum = {
  amd64: 'amd64',
  arm64: 'arm64',
  loong64: 'loong64',
} as const;

export class CreateMonitorTargetDto {
  @IsString()
  @MinLength(2)
  name!: string;

  @IsEnum(monitorTargetTypeEnum)
  type!: MonitorTargetType;

  @IsString()
  @IsNotEmpty()
  serviceKey!: string;

  @IsString()
  @IsNotEmpty()
  cronExpr!: string;

  @IsString()
  @IsNotEmpty()
  endpoint!: string;

  @IsString()
  @IsNotEmpty()
  configJson!: string;

  @IsOptional()
  @IsString()
  secretJson?: string;
}

export class UpdateMonitorTargetDto extends CreateMonitorTargetDto {}

export class UpdateMonitorTargetStatusDto {
  @IsEnum(targetStatusEnum)
  status!: 'enabled' | 'disabled';
}

export class CreateMonitorAgentDto {
  @IsString()
  @MinLength(2)
  name!: string;

  @IsString()
  @IsNotEmpty()
  agentKey!: string;

  @IsOptional()
  @IsString()
  host?: string;

  @IsEnum(agentPlatformEnum)
  platform!: 'linux' | 'windows';
}

export class UpdateMonitorAgentDto extends CreateMonitorAgentDto {}

export class BuildMonitorAgentPackageDto {
  @IsOptional()
  @IsEnum(agentPlatformEnum)
  targetOs?: 'linux' | 'windows';

  @IsOptional()
  @IsEnum(packageArchEnum)
  targetArch?: 'amd64' | 'arm64' | 'loong64';
}

export class ExecuteMonitorTargetDto {
  @IsOptional()
  @IsBoolean()
  replaceQueued?: boolean;
}

export class ClearQueuedMonitorRunsDto {
  @IsOptional()
  @IsString()
  targetId?: string;

  @IsOptional()
  @Type(() => Number)
  olderThanMinutes?: number;
}

export class RequeueStaleMonitorRunsDto {
  @IsOptional()
  @IsString()
  targetId?: string;

  @IsOptional()
  @Type(() => Number)
  staleMinutes?: number;
}

export class UpdateMonitorAlertStatusDto {
  @IsIn(['open', 'acknowledged', 'resolved'])
  status!: 'open' | 'acknowledged' | 'resolved';
}

export class DeleteMonitorRunsDto {
  @IsArray()
  @IsString({ each: true })
  runIds!: string[];
}

export class UpdateMonitorAgentStatusDto {
  @IsEnum(targetStatusEnum)
  status!: 'enabled' | 'disabled';
}

export class UpdateMonitorAgentFeaturesDto {
  @IsBoolean()
  monitoringEnabled!: boolean;

  @IsBoolean()
  logIngestEnabled!: boolean;

  @IsBoolean()
  proactivePushEnabled!: boolean;
}

export class IngestMonitorLogEventDto {
  @IsString()
  @IsNotEmpty()
  serviceKey!: string;

  @IsOptional()
  @IsString()
  sourceType?: 'vector' | 'fluent-bit' | 'manual';

  @IsOptional()
  @IsString()
  sourceName?: string;

  @IsOptional()
  @IsString()
  level?: string;

  @IsString()
  @IsNotEmpty()
  message!: string;

  @IsDateString()
  timestamp!: string;

  @IsOptional()
  @IsObject()
  meta?: Record<string, unknown>;
}

export class IngestMonitorLogsDto {
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => IngestMonitorLogEventDto)
  logs!: IngestMonitorLogEventDto[];
}
