/**
 * 日志系统 DTO
 * 定义日志查询、配置、告警等接口的数据传输对象
 */

import {
  IsOptional,
  IsString,
  IsEnum,
  IsBoolean,
  IsInt,
  Min,
  Max,
  IsDateString,
  IsIn,
  IsNumber,
  IsArray,
  ValidateNested,
  IsObject,
} from 'class-validator';
import { Type, Transform } from 'class-transformer';

// ==================== 枚举定义 ====================

export enum LogLevel {
  ERROR = 'ERROR',
  WARN = 'WARN',
  INFO = 'INFO',
  DEBUG = 'DEBUG',
}

export enum AlertType {
  SLOW_REQUEST = 'SLOW_REQUEST',
  HIGH_ERROR_RATE = 'HIGH_ERROR_RATE',
  DISK_SPACE = 'DISK_SPACE',
  IP_ANOMALY = 'IP_ANOMALY',
}

export enum AlertStatus {
  SENT = 'SENT',
  FAILED = 'FAILED',
  ACKNOWLEDGED = 'ACKNOWLEDGED',
}

export enum AlertSeverity {
  CRITICAL = 'CRITICAL',
  WARNING = 'WARNING',
  INFO = 'INFO',
}

// ==================== 通用查询参数 ====================

export class CommonLogQueryDto {
  @IsOptional()
  @IsDateString()
  startTime?: string;

  @IsOptional()
  @IsDateString()
  endTime?: string;

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

  @IsOptional()
  @IsIn(['CN', 'US', 'UAE'])
  region?: string;

  @IsOptional()
  @IsIn(['@timestamp', 'level', 'duration', 'service'])
  sortBy?: '@timestamp' | 'level' | 'duration' | 'service' = '@timestamp';

  @IsOptional()
  @IsIn(['asc', 'desc'])
  sortOrder?: 'asc' | 'desc' = 'desc';

  @IsOptional()
  @IsInt()
  @Min(1)
  @Type(() => Number)
  page?: number = 1;

  @IsOptional()
  @IsInt()
  @Min(1)
  @Max(200)
  @Type(() => Number)
  limit?: number = 50;
}

// ==================== 日志查询 DTO ====================

/**
 * 查询日志 DTO
 * GET /api/v1/logs/query
 */
export class QueryLogDto extends CommonLogQueryDto {
  @IsOptional()
  @IsEnum(LogLevel)
  level?: LogLevel;

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

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

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

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

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

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

  @IsOptional()
  @IsInt()
  @Min(0)
  @Type(() => Number)
  minDuration?: number;

  @IsOptional()
  @IsInt()
  @Min(0)
  @Type(() => Number)
  maxDuration?: number;

  @IsOptional()
  @IsInt()
  @Type(() => Number)
  statusCode?: number;

  @IsOptional()
  @IsBoolean()
  @Transform(({ value }) => value === 'true' || value === true)
  hasError?: boolean;
}

/**
 * 查询错误日志 DTO
 * GET /api/v1/logs/errors
 */
export class QueryErrorLogDto extends CommonLogQueryDto {
  @IsOptional()
  @IsString()
  errorType?: string;

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

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

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

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

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

/**
 * 查询慢请求 DTO
 * GET /api/v1/logs/slow-requests
 */
export class QuerySlowRequestDto extends CommonLogQueryDto {
  @IsOptional()
  @IsInt()
  @Min(100)
  @Type(() => Number)
  thresholdMs?: number = 2000;

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

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

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

/**
 * 查询日志统计 DTO
 * GET /api/v1/logs/stats
 */
export class QueryLogStatsDto {
  @IsOptional()
  @IsDateString()
  startTime?: string;

  @IsOptional()
  @IsDateString()
  endTime?: string;

  @IsOptional()
  @IsIn(['hour', 'day', 'service', 'level', 'region'])
  groupBy?: 'hour' | 'day' | 'service' | 'level' | 'region';
}

/**
 * 查询告警历史 DTO
 * GET /api/v1/logs/alerts
 */
export class QueryAlertHistoryDto extends CommonLogQueryDto {
  @IsOptional()
  @IsEnum(AlertType)
  type?: AlertType;

  @IsOptional()
  @IsEnum(AlertStatus)
  status?: AlertStatus;
}

// ==================== 配置更新 DTO ====================

class DynamicSamplingRulesDto {
  @IsOptional()
  @IsInt()
  @Min(1)
  qpsThreshold?: number;

  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  minSampleRate?: number;

  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  maxSampleRate?: number;
}

class SamplingRulesDto {
  @IsOptional()
  @ValidateNested()
  @Type(() => DynamicSamplingRulesDto)
  dynamic?: DynamicSamplingRulesDto;
}

class SamplingConfigDto {
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @ValidateNested()
  @Type(() => SamplingRulesDto)
  rules?: SamplingRulesDto;
}

class SlowRequestAlertDto {
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsInt()
  @Min(100)
  thresholdMs?: number;

  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  excludePaths?: string[];
}

class ErrorRateAlertDto {
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(100)
  thresholdPercent?: number;

  @IsOptional()
  @IsInt()
  @Min(1)
  windowMinutes?: number;
}

class DiskSpaceAlertDto {
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsInt()
  @Min(0)
  @Max(100)
  warningPercent?: number;

  @IsOptional()
  @IsInt()
  @Min(0)
  @Max(100)
  criticalPercent?: number;
}

class AlertsConfigDto {
  @IsOptional()
  @ValidateNested()
  @Type(() => SlowRequestAlertDto)
  slowRequest?: SlowRequestAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => ErrorRateAlertDto)
  errorRate?: ErrorRateAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => DiskSpaceAlertDto)
  diskSpace?: DiskSpaceAlertDto;
}

/**
 * 更新日志配置 DTO
 * PUT /api/v1/logs/config
 */
export class UpdateLogConfigDto {
  @IsOptional()
  @IsEnum(LogLevel)
  level?: LogLevel;

  @IsOptional()
  @ValidateNested()
  @Type(() => SamplingConfigDto)
  sampling?: SamplingConfigDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => AlertsConfigDto)
  alerts?: AlertsConfigDto;
}

// ==================== 日志清理 DTO ====================

/**
 * 清理日志 DTO
 * POST /api/v1/logs/cleanup
 */
export class CleanupLogDto {
  @IsOptional()
  @IsIn(['http', 'application', 'error', 'all'])
  type?: 'http' | 'application' | 'error' | 'all' = 'all';

  @IsOptional()
  @IsInt()
  @Min(1)
  @Type(() => Number)
  olderThanDays?: number;

  @IsOptional()
  @IsBoolean()
  @Transform(({ value }) => value === 'true' || value === true)
  dryRun?: boolean = false;
}

// ==================== 告警配置 DTO ====================

class IpAnomalyAlertDto {
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsInt()
  @Min(1)
  maxRequestsPerMinute?: number;

  @IsOptional()
  @IsInt()
  @Min(1)
  blockDurationMinutes?: number;
}

class SlackNotificationDto {
  @IsOptional()
  @IsString()
  webhookUrl?: string;

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

class FeishuNotificationDto {
  @IsOptional()
  @IsString()
  webhookUrl?: string;

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

class EmailNotificationDto {
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  recipients?: string[];

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

class NotificationsConfigDto {
  @IsOptional()
  @ValidateNested()
  @Type(() => SlackNotificationDto)
  slack?: SlackNotificationDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => FeishuNotificationDto)
  feishu?: FeishuNotificationDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => EmailNotificationDto)
  email?: EmailNotificationDto;
}

/**
 * 更新告警配置 DTO
 * PUT /api/v1/logs/alerts/config
 */
export class UpdateAlertConfigDto {
  @IsOptional()
  @ValidateNested()
  @Type(() => SlowRequestAlertDto)
  slowRequest?: SlowRequestAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => ErrorRateAlertDto)
  errorRate?: ErrorRateAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => IpAnomalyAlertDto)
  ipAnomaly?: IpAnomalyAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => DiskSpaceAlertDto)
  diskSpace?: DiskSpaceAlertDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => NotificationsConfigDto)
  notifications?: NotificationsConfigDto;
}

/**
 * 测试告警 DTO
 * POST /api/v1/logs/alerts/test
 */
export class TestAlertDto {
  @IsIn(['slack', 'feishu', 'email'])
  channel: 'slack' | 'feishu' | 'email';

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

