// =====================================================
// WAREHOUSE MODULE - TYPESCRIPT TYPES
// =====================================================

// ===============================================
// ENUMS
// ===============================================

export enum WarehouseType {
  Physical = 0,
  Logical = 1,
  Transit = 2,
  Returns = 3,
  Defective = 4,
  Subcontract = 5,
}

export enum StockManagementType {
  Standard = 0,
  NotManaged = 1,
  VariableWeight = 2,
  Kit = 3,
}

export enum ValuationMethod {
  WeightedAverage = 0,
  FIFO = 1,
  LIFO = 2,
  StandardCost = 3,
  SpecificCost = 4,
}

export enum BatchStatus {
  Available = 0,
  Quarantine = 1,
  Blocked = 2,
  Expired = 3,
  Depleted = 4,
}

export enum QualityStatus {
  NotChecked = 0,
  Approved = 1,
  Rejected = 2,
  ConditionallyApproved = 3,
}

export enum SerialStatus {
  Available = 0,
  Reserved = 1,
  Sold = 2,
  InRepair = 3,
  Defective = 4,
  Returned = 5,
  Disposed = 6,
}

export enum MovementType {
  Inbound = 0,
  Outbound = 1,
  Transfer = 2,
  Adjustment = 3,
  Production = 4,
  Consumption = 5,
  SupplierReturn = 6,
  CustomerReturn = 7,
}

export enum MovementStatus {
  Draft = 0,
  Confirmed = 1,
  Cancelled = 2,
}

export enum ExternalDocumentType {
  PurchaseOrder = 0,
  InboundDeliveryNote = 1,
  PurchaseInvoice = 2,
  SalesOrder = 3,
  OutboundDeliveryNote = 4,
  SalesInvoice = 5,
  ProductionOrder = 6,
  InventoryDocument = 7,
}

export enum BarcodeType {
  EAN13 = 0,
  EAN8 = 1,
  UPCA = 2,
  UPCE = 3,
  Code128 = 4,
  Code39 = 5,
  QRCode = 6,
  DataMatrix = 7,
  Internal = 8,
}

export enum InventoryType {
  Full = 0,
  Partial = 1,
  Cyclic = 2,
  Sample = 3,
}

export enum InventoryStatus {
  Draft = 0,
  InProgress = 1,
  Completed = 2,
  Confirmed = 3,
  Cancelled = 4,
}

// ===============================================
// WAREHOUSE LOCATION
// ===============================================

export interface WarehouseLocationDto {
  id: number;
  code: string;
  alternativeCode?: string;
  name: string;
  description?: string;
  address?: string;
  city?: string;
  province?: string;
  postalCode?: string;
  country?: string;
  type: WarehouseType;
  isDefault: boolean;
  isActive: boolean;
  sortOrder: number;
  notes?: string;
  createdAt?: string;
  updatedAt?: string;
}

export interface CreateWarehouseDto {
  // code è generato automaticamente dal backend
  alternativeCode?: string;
  name: string;
  description?: string;
  address?: string;
  city?: string;
  province?: string;
  postalCode?: string;
  country?: string;
  type: WarehouseType;
  isDefault: boolean;
  sortOrder: number;
  notes?: string;
}

export interface UpdateWarehouseDto {
  // code non è modificabile
  alternativeCode?: string;
  name: string;
  description?: string;
  address?: string;
  city?: string;
  province?: string;
  postalCode?: string;
  country?: string;
  type: WarehouseType;
  isDefault: boolean;
  sortOrder: number;
  notes?: string;
  isActive: boolean;
}

// ===============================================
// ARTICLE CATEGORY
// ===============================================

export interface CategoryDto {
  id: number;
  code: string;
  alternativeCode?: string;
  name: string;
  description?: string;
  parentCategoryId?: number;
  parentCategoryName?: string;
  level: number;
  fullPath?: string;
  icon?: string;
  color?: string;
  defaultValuationMethod?: ValuationMethod;
  sortOrder: number;
  isActive: boolean;
  notes?: string;
  createdAt?: string;
  updatedAt?: string;
}

export interface CategoryTreeDto {
  id: number;
  code: string;
  name: string;
  description?: string;
  level: number;
  fullPath?: string;
  icon?: string;
  color?: string;
  isActive: boolean;
  children: CategoryTreeDto[];
}

export interface CreateCategoryDto {
  // code è generato automaticamente dal backend
  alternativeCode?: string;
  name: string;
  description?: string;
  parentCategoryId?: number;
  icon?: string;
  color?: string;
  defaultValuationMethod?: ValuationMethod;
  sortOrder: number;
  notes?: string;
}

export interface UpdateCategoryDto {
  // code non è modificabile
  alternativeCode?: string;
  name: string;
  description?: string;
  icon?: string;
  color?: string;
  defaultValuationMethod?: ValuationMethod;
  sortOrder: number;
  isActive: boolean;
  notes?: string;
}

// ===============================================
// ARTICLE
// ===============================================

export interface ArticleDto {
  id: number;
  code: string;
  alternativeCode?: string;
  description: string;
  shortDescription?: string;
  barcode?: string;
  manufacturerCode?: string;
  categoryId?: number;
  categoryName?: string;
  unitOfMeasure: string;
  secondaryUnitOfMeasure?: string;
  unitConversionFactor?: number;
  stockManagement: StockManagementType;
  isBatchManaged: boolean;
  isSerialManaged: boolean;
  hasExpiry: boolean;
  expiryWarningDays?: number;
  minimumStock?: number;
  maximumStock?: number;
  reorderPoint?: number;
  reorderQuantity?: number;
  leadTimeDays?: number;
  valuationMethod?: ValuationMethod;
  standardCost?: number;
  lastPurchaseCost?: number;
  weightedAverageCost?: number;
  baseSellingPrice?: number;
  weight?: number;
  volume?: number;
  isActive: boolean;
  notes?: string;
  hasImage: boolean;
  createdAt?: string;
  updatedAt?: string;
}

export interface CreateArticleDto {
  // code è generato automaticamente dal backend
  description: string;
  shortDescription?: string;
  alternativeCode?: string;
  barcode?: string;
  manufacturerCode?: string;
  categoryId?: number;
  unitOfMeasure: string;
  secondaryUnitOfMeasure?: string;
  unitConversionFactor?: number;
  stockManagement: StockManagementType;
  isBatchManaged: boolean;
  isSerialManaged: boolean;
  hasExpiry: boolean;
  expiryWarningDays?: number;
  minimumStock?: number;
  maximumStock?: number;
  reorderPoint?: number;
  reorderQuantity?: number;
  leadTimeDays?: number;
  valuationMethod?: ValuationMethod;
  standardCost?: number;
  baseSellingPrice?: number;
  weight?: number;
  volume?: number;
  notes?: string;
}

export interface UpdateArticleDto {
  // code non è modificabile
  description: string;
  shortDescription?: string;
  alternativeCode?: string;
  barcode?: string;
  manufacturerCode?: string;
  categoryId?: number;
  unitOfMeasure: string;
  secondaryUnitOfMeasure?: string;
  unitConversionFactor?: number;
  stockManagement: StockManagementType;
  isBatchManaged: boolean;
  isSerialManaged: boolean;
  hasExpiry: boolean;
  expiryWarningDays?: number;
  minimumStock?: number;
  maximumStock?: number;
  reorderPoint?: number;
  reorderQuantity?: number;
  leadTimeDays?: number;
  valuationMethod?: ValuationMethod;
  standardCost?: number;
  baseSellingPrice?: number;
  weight?: number;
  volume?: number;
  notes?: string;
  isActive: boolean;
}

export interface ArticleFilterDto {
  search?: string;
  categoryId?: number;
  isActive?: boolean;
  isBatchManaged?: boolean;
  isSerialManaged?: boolean;
  skip?: number;
  take?: number;
  orderBy?: string;
  orderDescending?: boolean;
}

export interface ArticleStockDto {
  articleId: number;
  articleCode: string;
  articleDescription: string;
  totalStock: number;
  availableStock: number;
  unitOfMeasure: string;
  minimumStock?: number;
  maximumStock?: number;
  reorderPoint?: number;
  isLowStock: boolean;
  stockByWarehouse: WarehouseStockDto[];
}

export interface WarehouseStockDto {
  warehouseId: number;
  warehouseCode: string;
  warehouseName: string;
  quantity: number;
  reservedQuantity: number;
  availableQuantity: number;
  unitCost?: number;
  stockValue?: number;
  batchId?: number;
  batchNumber?: string;
}

// ===============================================
// BATCH
// ===============================================

export interface BatchDto {
  id: number;
  articleId: number;
  articleCode?: string;
  articleDescription?: string;
  batchNumber: string;
  productionDate?: string;
  expiryDate?: string;
  supplierBatch?: string;
  supplierId?: number;
  unitCost?: number;
  initialQuantity: number;
  currentQuantity: number;
  reservedQuantity: number;
  availableQuantity: number;
  status: BatchStatus;
  qualityStatus?: QualityStatus;
  lastQualityCheckDate?: string;
  certifications?: string;
  notes?: string;
  isExpired: boolean;
  daysToExpiry?: number;
  createdAt?: string;
  updatedAt?: string;
}

export interface CreateBatchDto {
  articleId: number;
  batchNumber: string;
  productionDate?: string;
  expiryDate?: string;
  supplierBatch?: string;
  supplierId?: number;
  unitCost?: number;
  initialQuantity: number;
  certifications?: string;
  notes?: string;
}

export interface UpdateBatchDto {
  productionDate?: string;
  expiryDate?: string;
  supplierBatch?: string;
  unitCost?: number;
  certifications?: string;
  notes?: string;
}

// ===============================================
// SERIAL
// ===============================================

export interface SerialDto {
  id: number;
  articleId: number;
  articleCode?: string;
  articleDescription?: string;
  batchId?: number;
  batchNumber?: string;
  serialNumber: string;
  manufacturerSerial?: string;
  productionDate?: string;
  warrantyExpiryDate?: string;
  currentWarehouseId?: number;
  currentWarehouseCode?: string;
  currentWarehouseName?: string;
  status: SerialStatus;
  unitCost?: number;
  supplierId?: number;
  customerId?: number;
  soldDate?: string;
  salesReference?: string;
  attributes?: string;
  notes?: string;
  isWarrantyValid: boolean;
  daysToWarrantyExpiry?: number;
  createdAt?: string;
  updatedAt?: string;
}

export interface CreateSerialDto {
  articleId: number;
  batchId?: number;
  serialNumber: string;
  manufacturerSerial?: string;
  productionDate?: string;
  warrantyExpiryDate?: string;
  warehouseId?: number;
  unitCost?: number;
  supplierId?: number;
  attributes?: string;
  notes?: string;
}

export interface CreateSerialsBulkDto {
  articleId: number;
  batchId?: number;
  serialNumbers: string[];
  productionDate?: string;
  warrantyExpiryDate?: string;
  warehouseId?: number;
  unitCost?: number;
  supplierId?: number;
}

// ===============================================
// STOCK LEVEL
// ===============================================

export interface StockLevelDto {
  id: number;
  articleId: number;
  articleCode: string;
  articleDescription: string;
  categoryName?: string;
  warehouseId: number;
  warehouseCode: string;
  warehouseName: string;
  batchId?: number;
  batchNumber?: string;
  batchExpiryDate?: string;
  quantity: number;
  reservedQuantity: number;
  availableQuantity: number;
  onOrderQuantity: number;
  unitCost?: number;
  stockValue?: number;
  locationCode?: string;
  lastMovementDate?: string;
  lastInventoryDate?: string;
  minimumStock?: number;
  isLowStock: boolean;
}

export interface StockLevelFilterDto {
  articleId?: number;
  warehouseId?: number;
  batchId?: number;
  categoryId?: number;
  onlyWithStock?: boolean;
  onlyLowStock?: boolean;
  skip?: number;
  take?: number;
}

export interface StockSummaryDto {
  articleId: number;
  articleCode: string;
  articleDescription: string;
  unitOfMeasure: string;
  totalStock: number;
  availableStock: number;
  minimumStock?: number;
  maximumStock?: number;
  reorderPoint?: number;
  isLowStock: boolean;
  totalValue: number;
  warehouseCount: number;
  stockByWarehouse: StockLevelDto[];
}

// ===============================================
// MOVEMENT
// ===============================================

export interface MovementDto {
  id: number;
  documentNumber: string;
  movementDate: string;
  type: MovementType;
  status: MovementStatus;
  sourceWarehouseId?: number;
  sourceWarehouseCode?: string;
  sourceWarehouseName?: string;
  destinationWarehouseId?: number;
  destinationWarehouseCode?: string;
  destinationWarehouseName?: string;
  reasonId?: number;
  reasonDescription?: string;
  externalReference?: string;
  totalValue?: number;
  lineCount: number;
  confirmedDate?: string;
  notes?: string;
  createdAt?: string;
}

export interface MovementDetailDto extends MovementDto {
  externalDocumentType?: ExternalDocumentType;
  supplierId?: number;
  customerId?: number;
  confirmedBy?: string;
  updatedAt?: string;
  lines: MovementLineDto[];
}

export interface MovementLineDto {
  id: number;
  lineNumber: number;
  articleId: number;
  articleCode: string;
  articleDescription: string;
  batchId?: number;
  batchNumber?: string;
  serialId?: number;
  serialNumber?: string;
  quantity: number;
  unitOfMeasure: string;
  unitCost?: number;
  lineValue?: number;
  sourceLocationCode?: string;
  destinationLocationCode?: string;
  notes?: string;
}

export interface CreateMovementDto {
  documentNumber?: string;
  movementDate?: string;
  reasonId?: number;
  warehouseId: number;
  externalReference?: string;
  externalDocumentType?: ExternalDocumentType;
  supplierId?: number;
  customerId?: number;
  notes?: string;
  lines: CreateMovementLineDto[];
}

export interface CreateTransferDto {
  documentNumber?: string;
  movementDate?: string;
  reasonId?: number;
  sourceWarehouseId: number;
  destinationWarehouseId: number;
  externalReference?: string;
  notes?: string;
  lines: CreateMovementLineDto[];
}

export interface CreateAdjustmentDto {
  documentNumber?: string;
  movementDate?: string;
  reasonId?: number;
  warehouseId: number;
  externalReference?: string;
  notes?: string;
  lines: CreateMovementLineDto[];
}

export interface CreateMovementLineDto {
  articleId: number;
  batchId?: number;
  serialId?: number;
  quantity: number;
  unitOfMeasure?: string;
  unitCost?: number;
  sourceLocationCode?: string;
  destinationLocationCode?: string;
  externalLineReference?: string;
  notes?: string;
}

export interface MovementFilterDto {
  dateFrom?: string;
  dateTo?: string;
  type?: MovementType;
  status?: MovementStatus;
  warehouseId?: number;
  articleId?: number;
  reasonId?: number;
  externalReference?: string;
  skip?: number;
  take?: number;
  orderBy?: string;
  orderDescending?: boolean;
}

export interface MovementReasonDto {
  id: number;
  code: string;
  description: string;
  movementType: MovementType;
  stockSign: number;
  requiresExternalReference: boolean;
  requiresValuation: boolean;
  updatesAverageCost: boolean;
  isSystem: boolean;
  isActive: boolean;
}

// ===============================================
// VALUATION
// ===============================================

export interface ArticleValuationDto {
  articleId: number;
  articleCode: string;
  articleDescription: string;
  method: ValuationMethod;
  totalQuantity: number;
  unitOfMeasure: string;
  weightedAverageCost: number;
  standardCost?: number;
  lastPurchaseCost?: number;
  totalValue: number;
}

export interface PeriodValuationDto {
  id: number;
  period: number;
  valuationDate: string;
  articleId: number;
  articleCode: string;
  articleDescription: string;
  warehouseId?: number;
  warehouseCode?: string;
  warehouseName?: string;
  quantity: number;
  method: ValuationMethod;
  unitCost: number;
  totalValue: number;
  inboundQuantity: number;
  inboundValue: number;
  outboundQuantity: number;
  outboundValue: number;
  isClosed: boolean;
}

// ===============================================
// INVENTORY
// ===============================================

export interface InventoryCountDto {
  id: number;
  code: string;
  description: string;
  inventoryDate: string;
  warehouseId?: number;
  warehouseCode?: string;
  warehouseName?: string;
  categoryId?: number;
  categoryName?: string;
  type: InventoryType;
  status: InventoryStatus;
  startDate?: string;
  endDate?: string;
  confirmedDate?: string;
  adjustmentMovementId?: number;
  positiveDifferenceValue?: number;
  negativeDifferenceValue?: number;
  lineCount: number;
  countedLineCount: number;
  notes?: string;
  createdAt?: string;
}

export interface InventoryCountDetailDto extends InventoryCountDto {
  confirmedBy?: string;
  updatedAt?: string;
  lines: InventoryCountLineDto[];
}

export interface InventoryCountLineDto {
  id: number;
  articleId: number;
  articleCode: string;
  articleDescription: string;
  warehouseId: number;
  warehouseCode: string;
  batchId?: number;
  batchNumber?: string;
  locationCode?: string;
  theoreticalQuantity: number;
  countedQuantity?: number;
  difference?: number;
  unitCost?: number;
  differenceValue?: number;
  countedAt?: string;
  countedBy?: string;
  secondCountQuantity?: number;
  secondCountBy?: string;
  notes?: string;
}

export interface CreateInventoryCountDto {
  code?: string;
  description: string;
  inventoryDate?: string;
  warehouseId?: number;
  categoryId?: number;
  type: InventoryType;
  notes?: string;
}

// ===============================================
// HELPER FUNCTIONS
// ===============================================

export const warehouseTypeLabels: Record<WarehouseType, string> = {
  [WarehouseType.Physical]: "Fisico",
  [WarehouseType.Logical]: "Logico",
  [WarehouseType.Transit]: "Transito",
  [WarehouseType.Returns]: "Resi",
  [WarehouseType.Defective]: "Difettosi",
  [WarehouseType.Subcontract]: "Conto Lavoro",
};

export const stockManagementTypeLabels: Record<StockManagementType, string> = {
  [StockManagementType.Standard]: "Standard",
  [StockManagementType.NotManaged]: "Non Gestito",
  [StockManagementType.VariableWeight]: "Peso Variabile",
  [StockManagementType.Kit]: "Kit",
};

export const valuationMethodLabels: Record<ValuationMethod, string> = {
  [ValuationMethod.WeightedAverage]: "Costo Medio Ponderato",
  [ValuationMethod.FIFO]: "FIFO",
  [ValuationMethod.LIFO]: "LIFO",
  [ValuationMethod.StandardCost]: "Costo Standard",
  [ValuationMethod.SpecificCost]: "Costo Specifico",
};

export const batchStatusLabels: Record<BatchStatus, string> = {
  [BatchStatus.Available]: "Disponibile",
  [BatchStatus.Quarantine]: "Quarantena",
  [BatchStatus.Blocked]: "Bloccato",
  [BatchStatus.Expired]: "Scaduto",
  [BatchStatus.Depleted]: "Esaurito",
};

export const qualityStatusLabels: Record<QualityStatus, string> = {
  [QualityStatus.NotChecked]: "Non Controllato",
  [QualityStatus.Approved]: "Approvato",
  [QualityStatus.Rejected]: "Respinto",
  [QualityStatus.ConditionallyApproved]: "Approvato con Riserva",
};

export const serialStatusLabels: Record<SerialStatus, string> = {
  [SerialStatus.Available]: "Disponibile",
  [SerialStatus.Reserved]: "Riservato",
  [SerialStatus.Sold]: "Venduto",
  [SerialStatus.InRepair]: "In Riparazione",
  [SerialStatus.Defective]: "Difettoso",
  [SerialStatus.Returned]: "Reso",
  [SerialStatus.Disposed]: "Dismesso",
};

export const movementTypeLabels: Record<MovementType, string> = {
  [MovementType.Inbound]: "Carico",
  [MovementType.Outbound]: "Scarico",
  [MovementType.Transfer]: "Trasferimento",
  [MovementType.Adjustment]: "Rettifica",
  [MovementType.Production]: "Produzione",
  [MovementType.Consumption]: "Consumo",
  [MovementType.SupplierReturn]: "Reso a Fornitore",
  [MovementType.CustomerReturn]: "Reso da Cliente",
};

export const movementStatusLabels: Record<MovementStatus, string> = {
  [MovementStatus.Draft]: "Bozza",
  [MovementStatus.Confirmed]: "Confermato",
  [MovementStatus.Cancelled]: "Annullato",
};

export const inventoryTypeLabels: Record<InventoryType, string> = {
  [InventoryType.Full]: "Completo",
  [InventoryType.Partial]: "Parziale",
  [InventoryType.Cyclic]: "Ciclico",
  [InventoryType.Sample]: "A Campione",
};

export const inventoryStatusLabels: Record<InventoryStatus, string> = {
  [InventoryStatus.Draft]: "Bozza",
  [InventoryStatus.InProgress]: "In Corso",
  [InventoryStatus.Completed]: "Completato",
  [InventoryStatus.Confirmed]: "Confermato",
  [InventoryStatus.Cancelled]: "Annullato",
};

export function formatCurrency(value: number | undefined | null): string {
  if (value === undefined || value === null) return "-";
  return new Intl.NumberFormat("it-IT", {
    style: "currency",
    currency: "EUR",
  }).format(value);
}

export function formatQuantity(
  value: number | undefined | null,
  decimals: number = 2,
): string {
  if (value === undefined || value === null) return "-";
  return new Intl.NumberFormat("it-IT", {
    minimumFractionDigits: 0,
    maximumFractionDigits: decimals,
  }).format(value);
}

export function formatDate(dateString: string | undefined | null): string {
  if (!dateString) return "-";
  return new Date(dateString).toLocaleDateString("it-IT");
}

export function formatDateTime(dateString: string | undefined | null): string {
  if (!dateString) return "-";
  return new Date(dateString).toLocaleString("it-IT");
}

export function getMovementTypeColor(type: MovementType): string {
  switch (type) {
    case MovementType.Inbound:
    case MovementType.Production:
    case MovementType.CustomerReturn:
      return "success";
    case MovementType.Outbound:
    case MovementType.Consumption:
    case MovementType.SupplierReturn:
      return "error";
    case MovementType.Transfer:
      return "info";
    case MovementType.Adjustment:
      return "warning";
    default:
      return "default";
  }
}

export function getMovementStatusColor(status: MovementStatus): string {
  switch (status) {
    case MovementStatus.Draft:
      return "warning";
    case MovementStatus.Confirmed:
      return "success";
    case MovementStatus.Cancelled:
      return "error";
    default:
      return "default";
  }
}

export function getBatchStatusColor(status: BatchStatus): string {
  switch (status) {
    case BatchStatus.Available:
      return "success";
    case BatchStatus.Quarantine:
      return "warning";
    case BatchStatus.Blocked:
    case BatchStatus.Expired:
      return "error";
    case BatchStatus.Depleted:
      return "default";
    default:
      return "default";
  }
}

export function getSerialStatusColor(status: SerialStatus): string {
  switch (status) {
    case SerialStatus.Available:
      return "success";
    case SerialStatus.Reserved:
      return "info";
    case SerialStatus.Sold:
      return "primary";
    case SerialStatus.Returned:
      return "warning";
    case SerialStatus.InRepair:
    case SerialStatus.Defective:
      return "error";
    case SerialStatus.Disposed:
      return "default";
    default:
      return "default";
  }
}

export function getInventoryStatusColor(status: InventoryStatus): string {
  switch (status) {
    case InventoryStatus.Draft:
      return "default";
    case InventoryStatus.InProgress:
      return "info";
    case InventoryStatus.Completed:
      return "warning";
    case InventoryStatus.Confirmed:
      return "success";
    case InventoryStatus.Cancelled:
      return "error";
    default:
      return "default";
  }
}
