/**
 * Comparativo DTOs - Data Transfer Objects para Cuadros Comparativos de Cotizaciones
 *
 * Gestiona comparativos de cotizaciones para seleccion de proveedores.
 *
 * @module Purchase (MAI-004)
 */

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

/**
 * Estado del comparativo
 */
export enum ComparativoStatus {
  DRAFT = 'draft',
  IN_EVALUATION = 'in_evaluation',
  APPROVED = 'approved',
  CANCELLED = 'cancelled',
}

/**
 * DTO para producto en cotizacion de proveedor
 */
export class ComparativoProductoDto {
  @IsUUID()
  productId: string;

  @IsNumber()
  @Min(0)
  quantity: number;

  @IsNumber()
  @Min(0)
  unitPrice: number;

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

/**
 * DTO para proveedor en comparativo
 */
export class ComparativoProveedorDto {
  @IsUUID()
  supplierId: string;

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

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

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

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

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

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

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

/**
 * DTO para crear un nuevo comparativo de cotizaciones
 */
export class CreateComparativoDto {
  @IsOptional()
  @IsUUID()
  requisicionId?: string;

  @IsString()
  @MinLength(3)
  @MaxLength(30)
  code: string;

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

  @IsDateString()
  comparisonDate: string;

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

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

/**
 * DTO para actualizar un comparativo existente
 */
export class UpdateComparativoDto {
  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(30)
  code?: string;

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

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

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

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

/**
 * DTO para agregar un proveedor al comparativo
 */
export class AddProveedorToComparativoDto {
  @IsUUID()
  supplierId: string;

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

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

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

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

/**
 * DTO para actualizar un proveedor en el comparativo
 */
export class UpdateProveedorInComparativoDto {
  @IsOptional()
  @IsString()
  @MaxLength(50)
  quotationNumber?: string;

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

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

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

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

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

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

/**
 * DTO para agregar un producto a la cotizacion de un proveedor
 */
export class AddProductoToProveedorDto {
  @IsUUID()
  productId: string;

  @IsNumber()
  @Min(0)
  quantity: number;

  @IsNumber()
  @Min(0)
  unitPrice: number;

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

/**
 * DTO para aprobar un comparativo y seleccionar proveedor ganador
 */
export class ApproveComparativoDto {
  @IsUUID()
  winnerSupplierId: string;

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

/**
 * DTO para cancelar un comparativo
 */
export class CancelComparativoDto {
  @IsString()
  @MinLength(10)
  reason: string;
}

/**
 * DTO para filtrar comparativos en listados
 */
export class ComparativoFiltersDto {
  @IsOptional()
  @IsUUID()
  requisicionId?: string;

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

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

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

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

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

  @IsOptional()
  @IsDateString()
  dateTo?: 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 de respuesta para un producto en cotizacion
 */
export class ComparativoProductoResponseDto {
  id: string;
  tenantId: string;
  comparativoProveedorId: string;
  productId: string;
  product?: {
    id: string;
    code: string;
    name: string;
    unit: string;
  };
  quantity: number;
  unitPrice: number;
  totalPrice: number;
  notes?: string;
  createdAt: Date;
  createdById?: string;
}

/**
 * DTO de respuesta para un proveedor en comparativo
 */
export class ComparativoProveedorResponseDto {
  id: string;
  tenantId: string;
  comparativoId: string;
  supplierId: string;
  supplier?: {
    id: string;
    code: string;
    name: string;
    rfc?: string;
  };
  quotationNumber?: string;
  quotationDate?: Date;
  deliveryDays?: number;
  paymentConditions?: string;
  totalAmount?: number;
  isSelected: boolean;
  evaluationNotes?: string;
  productos?: ComparativoProductoResponseDto[];
  createdAt: Date;
  createdById?: string;
}

/**
 * DTO de respuesta para un comparativo de cotizaciones
 */
export class ComparativoResponseDto {
  id: string;
  tenantId: string;
  requisicionId?: string;
  requisicion?: {
    id: string;
    code: string;
  };
  code: string;
  name: string;
  comparisonDate: Date;
  status: ComparativoStatus;
  winnerSupplierId?: string;
  winnerSupplier?: {
    id: string;
    code: string;
    name: string;
  };
  approvedById?: string;
  approvedBy?: {
    id: string;
    firstName: string;
    lastName: string;
  };
  approvedAt?: Date;
  notes?: string;
  proveedores?: ComparativoProveedorResponseDto[];
  proveedoresCount?: number;
  createdAt: Date;
  createdById?: string;
  createdBy?: {
    id: string;
    firstName: string;
    lastName: string;
  };
  updatedAt: Date;
  updatedById?: string;
}
