/**
 * Approval DTOs - Data Transfer Objects para Flujos de Aprobacion
 *
 * Gestiona workflows de aprobacion para documentos.
 *
 * @module Documents (MAE-016)
 */

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

/**
 * Tipo de paso de aprobacion
 */
export enum ApprovalStepTypeEnum {
  REVIEW = 'review',
  APPROVAL = 'approval',
  SIGNATURE = 'signature',
  COMMENT = 'comment',
}

/**
 * Estado del workflow
 */
export enum WorkflowStatusEnum {
  DRAFT = 'draft',
  PENDING = 'pending',
  IN_PROGRESS = 'in_progress',
  APPROVED = 'approved',
  REJECTED = 'rejected',
  CANCELLED = 'cancelled',
}

/**
 * Accion de aprobacion
 */
export enum ApprovalActionEnum {
  APPROVE = 'approve',
  REJECT = 'reject',
  REQUEST_CHANGES = 'request_changes',
}

/**
 * DTO para definir un paso de aprobacion dentro de un workflow
 */
export class CreateApprovalStepDto {
  @IsNumber()
  @Min(1)
  stepNumber!: number;

  @IsString()
  @MinLength(2)
  @MaxLength(255)
  name!: string;

  @IsEnum(ApprovalStepTypeEnum)
  type!: ApprovalStepTypeEnum;

  @IsArray()
  @IsUUID('4', { each: true })
  approvers!: string[];

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

  @IsOptional()
  @IsString()
  @MaxLength(100)
  role?: string;
}

/**
 * DTO para crear un nuevo workflow de aprobacion
 */
export class CreateApprovalWorkflowDto {
  @IsString()
  @MinLength(3)
  @MaxLength(50)
  workflowCode!: string;

  @IsString()
  @MinLength(3)
  @MaxLength(255)
  name!: string;

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

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

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

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

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

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

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

/**
 * DTO para actualizar un workflow de aprobacion existente
 */
export class UpdateApprovalWorkflowDto {
  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(255)
  name?: string;

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

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

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

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

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

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

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

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

/**
 * DTO para enviar un documento a aprobacion
 */
export class SubmitForApprovalDto {
  @IsUUID()
  documentId!: string;

  @IsUUID()
  workflowId!: string;

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

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

  @IsOptional()
  @IsDateString()
  dueDate?: string;
}

/**
 * DTO para aprobar o rechazar un documento
 */
export class ApproveRejectDto {
  @IsEnum(ApprovalActionEnum)
  action!: ApprovalActionEnum;

  @IsOptional()
  @IsString()
  @MaxLength(2000)
  comments?: string;
}

/**
 * DTO para cancelar una instancia de aprobacion
 */
export class CancelApprovalDto {
  @IsString()
  @MinLength(5)
  @MaxLength(2000)
  reason!: string;
}

/**
 * DTO para filtrar workflows de aprobacion
 */
export class WorkflowFiltersDto {
  @IsOptional()
  @IsString()
  @MaxLength(255)
  search?: string;

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

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

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

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

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

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

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

/**
 * DTO para filtrar instancias de aprobacion
 */
export class ApprovalInstanceFiltersDto {
  @IsOptional()
  @IsUUID()
  documentId?: string;

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

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

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

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

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

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

  @IsOptional()
  @IsDateString()
  dueTo?: 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 workflow de aprobacion
 */
export class ApprovalWorkflowResponseDto {
  id!: string;
  tenantId!: string;
  workflowCode!: string;
  name!: string;
  description?: string;
  categoryId?: string;
  category?: {
    id: string;
    name: string;
    code: string;
  };
  documentType?: string;
  steps!: Array<{
    stepNumber: number;
    name: string;
    type: ApprovalStepTypeEnum;
    approvers: string[];
    requiredCount: number;
  }>;
  allowParallel!: boolean;
  allowSkip!: boolean;
  autoArchiveOnApproval!: boolean;
  isActive!: boolean;
  createdBy?: string;
  createdAt!: Date;
  updatedBy?: string;
  updatedAt!: Date;
}

/**
 * DTO de respuesta para una instancia de aprobacion
 */
export class ApprovalInstanceResponseDto {
  id!: string;
  tenantId!: string;
  workflowId!: string;
  workflow?: {
    id: string;
    name: string;
    workflowCode: string;
  };
  documentId!: string;
  document?: {
    id: string;
    documentCode: string;
    title: string;
  };
  versionId?: string;
  status!: WorkflowStatusEnum;
  currentStep!: number;
  totalSteps!: number;
  startedAt?: Date;
  completedAt?: Date;
  dueDate?: Date;
  initiatedById?: string;
  initiatedByName?: string;
  finalAction?: ApprovalActionEnum;
  finalComments?: string;
  finalApproverId?: string;
  notes?: string;
  steps?: Array<{
    id: string;
    stepNumber: number;
    stepName: string;
    stepType: ApprovalStepTypeEnum;
    status: WorkflowStatusEnum;
    startedAt?: Date;
    completedAt?: Date;
    actionTaken?: ApprovalActionEnum;
  }>;
  createdAt!: Date;
  updatedAt!: Date;
}
