/**
 * Document DTOs - Data Transfer Objects para Documentos
 *
 * Gestiona la creacion, actualizacion y filtrado de documentos.
 *
 * @module Documents (MAE-016)
 */

import {
  IsString,
  IsUUID,
  IsOptional,
  IsEnum,
  IsNumber,
  IsArray,
  IsUrl,
  IsDateString,
  IsBoolean,
  MinLength,
  MaxLength,
  Min,
} from 'class-validator';

/**
 * Tipo de documento
 */
export enum DocumentTypeEnum {
  PLAN = 'plan',
  SPECIFICATION = 'specification',
  CONTRACT = 'contract',
  PERMIT = 'permit',
  REPORT = 'report',
  PHOTOGRAPH = 'photograph',
  DRAWING = 'drawing',
  MANUAL = 'manual',
  PROCEDURE = 'procedure',
  FORM = 'form',
  CORRESPONDENCE = 'correspondence',
  INVOICE = 'invoice',
  ESTIMATE = 'estimate',
  OTHER = 'other',
}

/**
 * Estado del documento
 */
export enum DocumentStatusEnum {
  DRAFT = 'draft',
  PENDING_REVIEW = 'pending_review',
  IN_REVIEW = 'in_review',
  APPROVED = 'approved',
  REJECTED = 'rejected',
  OBSOLETE = 'obsolete',
  ARCHIVED = 'archived',
}

/**
 * Nivel de acceso del documento
 */
export enum AccessLevelEnum {
  PUBLIC = 'public',
  INTERNAL = 'internal',
  CONFIDENTIAL = 'confidential',
  RESTRICTED = 'restricted',
}

/**
 * DTO para crear un nuevo documento
 */
export class CreateDocumentDto {
  @IsString()
  @MinLength(3)
  @MaxLength(500)
  title!: string;

  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(100)
  documentCode?: string;

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

  @IsOptional()
  @IsString()
  @MaxLength(2000)
  description?: string;

  @IsEnum(DocumentTypeEnum)
  documentType!: DocumentTypeEnum;

  @IsOptional()
  @IsEnum(AccessLevelEnum)
  accessLevel?: AccessLevelEnum;

  @IsOptional()
  @IsUrl()
  fileUrl?: string;

  @IsOptional()
  @IsNumber()
  @Min(0)
  fileSize?: number;

  @IsOptional()
  @IsString()
  @MaxLength(100)
  mimeType?: string;

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

  @IsOptional()
  @IsString()
  @MaxLength(50)
  projectCode?: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  projectName?: string;

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

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

  @IsOptional()
  @IsString()
  @MaxLength(255)
  author?: string;

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

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

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

  @IsOptional()
  @IsString()
  @MaxLength(100)
  source?: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  externalReference?: string;

  @IsOptional()
  @IsString()
  @MaxLength(500)
  originalFilename?: string;

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

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

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

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

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

/**
 * DTO para actualizar un documento existente
 */
export class UpdateDocumentDto {
  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(500)
  title?: string;

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

  @IsOptional()
  @IsString()
  @MaxLength(2000)
  description?: string;

  @IsOptional()
  @IsEnum(DocumentTypeEnum)
  documentType?: DocumentTypeEnum;

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

  @IsOptional()
  @IsEnum(AccessLevelEnum)
  accessLevel?: AccessLevelEnum;

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

  @IsOptional()
  @IsString()
  @MaxLength(50)
  projectCode?: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  projectName?: string;

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

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

  @IsOptional()
  @IsString()
  @MaxLength(255)
  author?: string;

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

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

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

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

  @IsOptional()
  @IsString()
  @MaxLength(100)
  source?: string;

  @IsOptional()
  @IsString()
  @MaxLength(255)
  externalReference?: string;

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

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

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

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

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

/**
 * DTO para filtrar documentos en listados
 */
export class DocumentFiltersDto {
  @IsOptional()
  @IsUUID()
  categoryId?: string;

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

  @IsOptional()
  @IsString()
  @MaxLength(255)
  search?: string;

  @IsOptional()
  @IsEnum(DocumentTypeEnum)
  documentType?: DocumentTypeEnum;

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

  @IsOptional()
  @IsEnum(AccessLevelEnum)
  accessLevel?: AccessLevelEnum;

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

  @IsOptional()
  @IsString()
  @MaxLength(255)
  author?: string;

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

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

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

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

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

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

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

  @IsOptional()
  @IsNumber()
  @Min(1)
  page?: number;

  @IsOptional()
  @IsNumber()
  @Min(1)
  limit?: number;

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

  @IsOptional()
  @IsEnum(['ASC', 'DESC'])
  sortOrder?: 'ASC' | 'DESC';
}

/**
 * DTO de respuesta para un documento
 */
export class DocumentResponseDto {
  id!: string;
  tenantId!: string;
  documentCode!: string;
  title!: string;
  description?: string;
  categoryId?: string;
  category?: {
    id: string;
    name: string;
    code: string;
  };
  documentType!: DocumentTypeEnum;
  status!: DocumentStatusEnum;
  accessLevel!: AccessLevelEnum;
  currentVersionId?: string;
  currentVersionNumber!: string;
  projectId?: string;
  projectCode?: string;
  projectName?: string;
  author?: string;
  keywords?: string[];
  tags?: string[];
  documentDate?: Date;
  effectiveDate?: Date;
  expiryDate?: Date;
  reviewDate?: Date;
  source?: string;
  externalReference?: string;
  originalFilename?: string;
  parentDocumentId?: string;
  relatedDocuments?: string[];
  requiresApproval!: boolean;
  currentWorkflowId?: string;
  approvedById?: string;
  approvedAt?: Date;
  viewCount!: number;
  downloadCount!: number;
  lastAccessedAt?: Date;
  isTemplate!: boolean;
  isLocked!: boolean;
  lockedById?: string;
  lockedAt?: Date;
  notes?: string;
  versionsCount?: number;
  annotationsCount?: number;
  createdBy?: string;
  createdAt!: Date;
  updatedBy?: string;
  updatedAt!: Date;
}

/**
 * DTO para bloquear/desbloquear un documento
 */
export class LockDocumentDto {
  @IsOptional()
  @IsString()
  @MaxLength(500)
  reason?: string;
}
