import {
  IsString,
  IsNotEmpty,
  IsOptional,
  IsEnum,
  IsUUID,
  IsArray,
  IsInt,
  Min,
  Max,
  MaxLength,
  MinLength,
  IsBoolean,
  IsObject,
  ValidateNested,
} from 'class-validator';
import { Type, Transform } from 'class-transformer';

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

export enum TicketStatus {
  OPEN = 'OPEN',
  ASSIGNED = 'ASSIGNED',
  IN_PROGRESS = 'IN_PROGRESS',
  PENDING = 'PENDING',
  RESOLVED = 'RESOLVED',
  CLOSED = 'CLOSED',
  CANCELLED = 'CANCELLED',
}

export enum TicketPriority {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
  URGENT = 'URGENT',
}

export enum TicketSource {
  WEB = 'WEB',
  MOBILE = 'MOBILE',
  EMAIL = 'EMAIL',
  API = 'API',
  CHAT = 'CHAT',
  PHONE = 'PHONE',
  WALK_IN = 'WALK_IN',
}

export enum CommentType {
  COMMENT = 'COMMENT',
  STATUS_CHANGE = 'STATUS_CHANGE',
  ASSIGNMENT = 'ASSIGNMENT',
  SYSTEM = 'SYSTEM',
  AI_CONTEXT = 'AI_CONTEXT',
}

export enum VisibilityScope {
  ALL = 'ALL',
  AGENT_ONLY = 'AGENT_ONLY',
  GROUP_ONLY = 'GROUP_ONLY',
  INTERNAL = 'INTERNAL',
}

// ==================== 附件 DTO ====================

export class AttachmentDto {
  @IsString()
  @IsNotEmpty()
  fileName: string;

  @IsString()
  @IsNotEmpty()
  fileUrl: string;

  @IsInt()
  @Min(0)
  fileSize: number;

  @IsString()
  @IsNotEmpty()
  mimeType: string;
}

// ==================== 创建工单 DTO ====================

export class CreateTicketDto {
  @IsString()
  @IsNotEmpty()
  @MinLength(5, { message: '标题至少 5 个字符' })
  @MaxLength(200, { message: '标题最多 200 个字符' })
  title: string;

  @IsString()
  @IsNotEmpty()
  @MinLength(10, { message: '描述至少 10 个字符' })
  @MaxLength(10000, { message: '描述最多 10000 个字符' })
  description: string;

  @IsUUID()
  @IsNotEmpty()
  categoryId: string;

  @IsEnum(TicketPriority)
  @IsOptional()
  priority?: TicketPriority;

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

  @IsEnum(TicketSource)
  @IsOptional()
  source?: TicketSource;

  @IsObject()
  @IsOptional()
  channelMetadata?: Record<string, any>;

  @IsString()
  @IsOptional()
  @MaxLength(10)
  language?: string;

  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => AttachmentDto)
  @IsOptional()
  attachments?: AttachmentDto[];
}

// ==================== 更新工单 DTO ====================

export class UpdateTicketDto {
  @IsString()
  @IsOptional()
  @MinLength(5, { message: '标题至少 5 个字符' })
  @MaxLength(200, { message: '标题最多 200 个字符' })
  title?: string;

  @IsString()
  @IsOptional()
  @MaxLength(10000, { message: '描述最多 10000 个字符' })
  description?: string;

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

  @IsEnum(TicketPriority)
  @IsOptional()
  priority?: TicketPriority;

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

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

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

// ==================== 更新工单状态 DTO ====================

export class UpdateTicketStatusDto {
  @IsEnum(TicketStatus)
  @IsNotEmpty()
  status: TicketStatus;

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

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

// ==================== 分配工单 DTO ====================

export class AssignTicketDto {
  @IsUUID()
  @IsOptional()
  assigneeId?: string;

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

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

// ==================== 查询工单 DTO ====================

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

  @IsInt()
  @Min(1)
  @Max(100)
  @IsOptional()
  @Type(() => Number)
  limit?: number = 20;

  @IsEnum(TicketStatus)
  @IsOptional()
  status?: TicketStatus;

  @IsArray()
  @IsEnum(TicketStatus, { each: true })
  @IsOptional()
  @Transform(({ value }) => (typeof value === 'string' ? value.split(',') : value))
  statuses?: TicketStatus[];

  @IsEnum(TicketPriority)
  @IsOptional()
  priority?: TicketPriority;

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

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

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

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

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

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

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

  @IsString()
  @IsOptional()
  view?: 'my_created' | 'my_assigned' | 'my_group' | 'all';

  @IsString()
  @IsOptional()
  sortBy?: 'createdAt' | 'updatedAt' | 'priority' | 'dueAt';

  @IsString()
  @IsOptional()
  sortOrder?: 'asc' | 'desc';
}

// ==================== 评论 DTO ====================

export class CreateCommentDto {
  @IsString()
  @IsNotEmpty()
  @MinLength(1, { message: '评论内容不能为空' })
  @MaxLength(5000, { message: '评论内容最多 5000 个字符' })
  content: string;

  @IsEnum(CommentType)
  @IsOptional()
  type?: CommentType;

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

  @IsEnum(VisibilityScope)
  @IsOptional()
  visibilityScope?: VisibilityScope;

  @IsArray()
  @IsUUID('4', { each: true })
  @IsOptional()
  mentionedUserIds?: string[];

  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => AttachmentDto)
  @IsOptional()
  attachments?: AttachmentDto[];
}

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

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

// ==================== 满意度评价 DTO ====================

export class CreateSatisfactionDto {
  @IsInt()
  @Min(1)
  @Max(5)
  rating: number;

  @IsString()
  @IsOptional()
  @MaxLength(1000)
  comment?: string;
}

// ==================== 关注者 DTO ====================

export class UpdateWatchersDto {
  @IsArray()
  @IsUUID('4', { each: true })
  watcherIds: string[];
}

// ==================== 活动日志查询 DTO ====================

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

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