import { createEmptyPieceModelStructure, createEmptyProductModelStructure, type PieceModelCustomField, type PieceModelProduct, type PieceModelStructure, type PieceModelStructureEditorField, type PieceModelStructureForEditor, type ProductModelStructure, } from '../types/inventory' import { isPlainObject, sanitizeProducts, hydrateProducts } from './componentStructure' export const defaultPieceStructure = (): PieceModelStructure => ({ ...createEmptyPieceModelStructure(), }) export const defaultProductStructure = (): ProductModelStructure => ({ ...createEmptyProductModelStructure(), }) const ensurePieceStructureShape = (input: any): PieceModelStructure => { const base = createEmptyPieceModelStructure() if (!isPlainObject(input)) { return base } const clone: PieceModelStructure = { ...base, customFields: Array.isArray((input as any).customFields) ? (input as any).customFields : [], products: Array.isArray((input as any).products) ? (input as any).products : [], } for (const [key, value] of Object.entries(input as Record)) { if (key === 'customFields' || key === 'products') { continue } clone[key] = value } return clone } export const clonePieceStructure = (input: any): PieceModelStructure => { try { const cloned = JSON.parse(JSON.stringify(input ?? defaultPieceStructure())) return ensurePieceStructureShape(cloned) } catch (_error) { return defaultPieceStructure() } } export const cloneProductStructure = (input: any): ProductModelStructure => { return clonePieceStructure(input) } const sanitizePieceCustomFields = (fields: any[]): PieceModelCustomField[] => { if (!Array.isArray(fields)) { return [] } return fields .map((field, index) => { const name = typeof field?.name === 'string' ? field.name.trim() : '' if (!name) { return null } const type = typeof field?.type === 'string' && field.type ? field.type : 'text' const required = !!field?.required let options: string[] | undefined if (type === 'select') { const rawOptions = typeof field?.optionsText === 'string' ? field.optionsText : Array.isArray(field?.options) ? field.options.join('\n') : '' const parsed = rawOptions .split(/\r?\n/) .map((option: string) => option.trim()) .filter((option: string) => option.length > 0) options = parsed.length > 0 ? parsed : undefined } const result: PieceModelCustomField = { name, type, required } if (options) { result.options = options } const defaultValue = field?.defaultValue !== undefined && field?.defaultValue !== null && field?.defaultValue !== '' ? String(field.defaultValue) : null if (defaultValue !== null) { result.defaultValue = defaultValue } if (typeof field?.id === 'string' && field.id) { result.id = field.id } if (typeof field?.customFieldId === 'string' && field.customFieldId) { result.customFieldId = field.customFieldId } const orderIndex = typeof field?.orderIndex === 'number' ? field.orderIndex : index result.orderIndex = orderIndex return result }) .filter((field): field is PieceModelCustomField => !!field) } const sanitizePieceProducts = (products: any[]): PieceModelProduct[] => { return sanitizeProducts(products) as PieceModelProduct[] } export const normalizePieceStructureForSave = (input: any): PieceModelStructure => { const source = clonePieceStructure(input) const restEntries = Object.entries(source).filter( ([key]) => key !== 'customFields' && key !== 'products', ) return { ...Object.fromEntries(restEntries), products: sanitizePieceProducts(source.products || []), customFields: sanitizePieceCustomFields(source.customFields), } } const hydratePieceCustomFields = (fields: any[]): PieceModelStructureEditorField[] => { if (!Array.isArray(fields)) { return [] } return fields.map((field, index) => ({ name: field?.name ?? '', type: field?.type ?? 'text', required: !!field?.required, options: Array.isArray(field?.options) ? field.options : undefined, optionsText: typeof field?.optionsText === 'string' ? field.optionsText : Array.isArray(field?.options) ? field.options.join('\n') : '', orderIndex: typeof field?.orderIndex === 'number' ? field.orderIndex : index, ...(field?.id ? { id: field.id } : {}), ...(field?.customFieldId ? { customFieldId: field.customFieldId } : {}), })) } export const hydratePieceStructureForEditor = (input: any): PieceModelStructureForEditor => { const source = clonePieceStructure(input) const payload: PieceModelStructureForEditor = { ...Object.fromEntries( Object.entries(source).filter(([key]) => key !== 'customFields' && key !== 'products'), ), products: hydrateProducts(source.products || []) as PieceModelProduct[], customFields: hydratePieceCustomFields(source.customFields), } return payload } export const formatPieceStructurePreview = (structure: any) => { if (!structure || typeof structure !== 'object') { return 'Aucun champ personnalisé' } const customFields = Array.isArray((structure as any).customFields) ? (structure as any).customFields.length : 0 const products = Array.isArray((structure as any).products) ? (structure as any).products.length : 0 if (!customFields && !products) { return 'Aucun produit ni champ personnalisé' } const segments: string[] = [] if (products) { segments.push(`${products} produit(s)`) } if (customFields) { segments.push(`${customFields} champ(s) personnalisé(s)`) } return segments.join(' · ') } export const normalizeProductStructureForSave = (input: any): ProductModelStructure => normalizePieceStructureForSave(input) export const hydrateProductStructureForEditor = (input: any) => hydratePieceStructureForEditor(input) export const formatProductStructurePreview = (structure: any) => formatPieceStructurePreview(structure)