/**
 * WorkOrder DTOs - Data Transfer Objects para Ordenes de Trabajo de Mantenimiento
 *
 * Registro de mantenimientos preventivos y correctivos.
 *
 * @module Assets (MAE-015)
 */

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

/**
 * Tipo de mantenimiento
 */
export enum MaintenanceType {
  PREVENTIVE = 'preventive',
  CORRECTIVE = 'corrective',
  PREDICTIVE = 'predictive',
  EMERGENCY = 'emergency',
}

/**
 * Estado de la orden de trabajo
 */
export enum WorkOrderStatus {
  DRAFT = 'draft',
  SCHEDULED = 'scheduled',
  IN_PROGRESS = 'in_progress',
  ON_HOLD = 'on_hold',
  COMPLETED = 'completed',
  CANCELLED = 'cancelled',
}

/**
 * Prioridad de la orden de trabajo
 */
export enum WorkOrderPriority {
  LOW = 'low',
  MEDIUM = 'medium',
  HIGH = 'high',
  CRITICAL = 'critical',
}

/**
 * DTO para crear una nueva orden de trabajo
 */
export class CreateWorkOrderDto {
  @IsUUID()
  assetId: string;

  @IsEnum(MaintenanceType)
  type: MaintenanceType;

  @IsEnum(WorkOrderPriority)
  priority: WorkOrderPriority;

  @IsString()
  @MinLength(3)
  @MaxLength(255)
  title: string;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/**
 * DTO para actualizar una orden de trabajo
 */
export class UpdateWorkOrderDto {
  @IsOptional()
  @IsEnum(MaintenanceType)
  type?: MaintenanceType;

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

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

  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(255)
  title?: string;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/**
 * DTO para filtrar ordenes de trabajo
 */
export class WorkOrderFiltersDto {
  @IsOptional()
  @IsUUID()
  assetId?: string;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/**
 * DTO para crear una parte/refaccion en orden de trabajo
 */
export class CreateWorkOrderPartDto {
  @IsUUID()
  workOrderId: string;

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

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

  @IsString()
  @MinLength(1)
  @MaxLength(255)
  partName: string;

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

  @IsNumber()
  @IsPositive()
  quantity: number;

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

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

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

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

/**
 * DTO para actualizar una parte/refaccion en orden de trabajo
 */
export class UpdateWorkOrderPartDto {
  @IsOptional()
  @IsString()
  @MaxLength(50)
  partCode?: string;

  @IsOptional()
  @IsString()
  @MinLength(1)
  @MaxLength(255)
  partName?: string;

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

  @IsOptional()
  @IsNumber()
  @IsPositive()
  quantityRequired?: number;

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

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

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

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

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

/**
 * DTO para completar una orden de trabajo
 */
export class CompleteWorkOrderDto {
  @IsString()
  @MinLength(10)
  workPerformed: string;

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

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

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

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

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

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

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

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

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

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

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

/**
 * DTO para cancelar una orden de trabajo
 */
export class CancelWorkOrderDto {
  @IsString()
  @MinLength(10)
  reason: string;
}

/**
 * DTO de respuesta para una orden de trabajo
 */
export class WorkOrderResponseDto {
  id: string;
  tenantId: string;
  workOrderNumber: string;
  assetId: string;
  asset?: {
    id: string;
    assetCode: string;
    name: string;
    assetType: string;
  };
  maintenanceType: MaintenanceType;
  status: WorkOrderStatus;
  priority: WorkOrderPriority;
  title: string;
  description?: string;
  problemReported?: string;
  diagnosis?: string;
  projectId?: string;
  projectName?: string;
  locationDescription?: string;
  requestedDate: Date;
  scheduledStartDate?: Date;
  scheduledEndDate?: Date;
  actualStartDate?: Date;
  actualEndDate?: Date;
  assignedToId?: string;
  assignedToName?: string;
  teamIds?: string[];
  estimatedHours?: number;
  actualHours?: number;
  laborCost: number;
  partsCost: number;
  externalServiceCost: number;
  otherCosts: number;
  totalCost: number;
  partsUsedCount: number;
  partsUsed?: WorkOrderPartResponseDto[];
  workPerformed?: string;
  findings?: string;
  recommendations?: string;
  requiresFollowup: boolean;
  followupNotes?: string;
  createdAt: Date;
  updatedAt: Date;
  createdBy?: string;
  completedById?: string;
  completedByName?: string;
}

/**
 * DTO de respuesta para una parte/refaccion
 */
export class WorkOrderPartResponseDto {
  id: string;
  tenantId: string;
  workOrderId: string;
  partId?: string;
  partCode?: string;
  partName: string;
  partDescription?: string;
  quantityRequired: number;
  quantityUsed?: number;
  unitCost?: number;
  totalCost?: number;
  fromInventory: boolean;
  purchaseOrderId?: string;
  notes?: string;
  createdAt: Date;
  updatedAt: Date;
}

/**
 * DTO para reporte de ordenes de trabajo
 */
export class WorkOrderReportFiltersDto {
  @IsOptional()
  @IsUUID()
  assetId?: string;

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

  @IsDateString()
  dateFrom: string;

  @IsDateString()
  dateTo: string;

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

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

/**
 * DTO de respuesta para resumen de ordenes de trabajo
 */
export class WorkOrderSummaryDto {
  totalWorkOrders: number;
  byStatus: Record<WorkOrderStatus, number>;
  byType: Record<MaintenanceType, number>;
  byPriority: Record<WorkOrderPriority, number>;
  totalLaborCost: number;
  totalPartsCost: number;
  totalExternalCost: number;
  totalCost: number;
  averageCompletionTime?: number;
  periodStart: Date;
  periodEnd: Date;
}
