import { normalizeProductText } from './productParsing.ts'; export type ProductTypeKey = | 'finished_apparel' | 'finished_accessory' | 'raw_material' | 'packaging' | 'dtf_input' | 'dtf_service' | 'kit_bundle' | 'service' | 'machine_part' | 'equipment' | 'ignore_from_planning' | 'unknown'; export type ProductPlanningMode = 'cutting' | 'unit_replenishment' | 'material' | 'service' | 'ignore' | 'review'; export type ProductTypeConfig = { key: ProductTypeKey; label: string; description: string; planningMode: ProductPlanningMode; badgeClassName: string; }; export const productTypeConfigs: Record = { finished_apparel: { key: 'finished_apparel', label: 'Vestuário', description: 'Produto acabado que pode entrar em corte/reposição por SKU.', planningMode: 'cutting', badgeClassName: 'border-sky-400/30 bg-sky-400/10 text-sky-300' }, finished_accessory: { key: 'finished_accessory', label: 'Acessório', description: 'Produto acabado sem regra de malha principal.', planningMode: 'unit_replenishment', badgeClassName: 'border-cyan-400/30 bg-cyan-400/10 text-cyan-300' }, raw_material: { key: 'raw_material', label: 'Matéria-prima', description: 'Entrada de produção, como malha, ribana, tecido, fio ou resíduo.', planningMode: 'material', badgeClassName: 'border-emerald-400/30 bg-emerald-400/10 text-emerald-300' }, packaging: { key: 'packaging', label: 'Embalagem', description: 'Insumo de embalagem controlado por unidade/milheiro.', planningMode: 'unit_replenishment', badgeClassName: 'border-amber-400/30 bg-amber-400/10 text-amber-300' }, dtf_input: { key: 'dtf_input', label: 'Insumo DTF', description: 'Insumo para DTF, como tinta, filme, poliamida ou fluido.', planningMode: 'material', badgeClassName: 'border-fuchsia-400/30 bg-fuchsia-400/10 text-fuchsia-300' }, dtf_service: { key: 'dtf_service', label: 'Serviço DTF', description: 'Impressão, estampa ou personalização vendida como serviço/produto customizado.', planningMode: 'service', badgeClassName: 'border-purple-400/30 bg-purple-400/10 text-purple-300' }, kit_bundle: { key: 'kit_bundle', label: 'Kit', description: 'Bundle marketplace composto por outros SKUs.', planningMode: 'review', badgeClassName: 'border-indigo-400/30 bg-indigo-400/10 text-indigo-300' }, service: { key: 'service', label: 'Serviço', description: 'Frete, transporte, tecelagem, tinturaria ou serviço técnico.', planningMode: 'service', badgeClassName: 'border-zinc-400/30 bg-zinc-400/10 text-zinc-300' }, machine_part: { key: 'machine_part', label: 'Peça máquina', description: 'Peça, limpeza ou manutenção de máquina.', planningMode: 'unit_replenishment', badgeClassName: 'border-orange-400/30 bg-orange-400/10 text-orange-300' }, equipment: { key: 'equipment', label: 'Equipamento', description: 'Máquina ou equipamento permanente.', planningMode: 'ignore', badgeClassName: 'border-slate-400/30 bg-slate-400/10 text-slate-300' }, ignore_from_planning: { key: 'ignore_from_planning', label: 'Ignorar', description: 'Item que não deve dirigir corte, compra ou reposição.', planningMode: 'ignore', badgeClassName: 'border-dark-border bg-dark-input text-dark-muted' }, unknown: { key: 'unknown', label: 'Revisar', description: 'Tipo não identificado automaticamente.', planningMode: 'review', badgeClassName: 'border-red-400/30 bg-red-400/10 text-red-300' } }; const has = (value: string, pattern: RegExp) => pattern.test(value); export const classifyProductType = (name: string): ProductTypeKey => { const normalizedName = normalizeProductText(name) .normalize('NFD') .replace(/\p{Diacritic}/gu, '') .toUpperCase(); if (!normalizedName) return 'unknown'; if (has(normalizedName, /\bSALDO ESTOQUE\b/)) return 'ignore_from_planning'; if (has(normalizedName, /^(?:\d+\s+)?(?:MALHA|RIBANA)\b/)) return 'raw_material'; if (has(normalizedName, /\b(?:RETALHO|RESIDUO)\s+(?:DE\s+)?(?:MALHA|MOLETOM)\b/)) return 'raw_material'; if (has(normalizedName, /\bFIO\b.*\bMALHARIA\b/)) return 'raw_material'; if (has(normalizedName, /\b(?:LINHA|FIO) PARA COSTURA\b/)) return 'raw_material'; if (has(normalizedName, /\bATACADOR\b/)) return 'raw_material'; if (has(normalizedName, /\bILHOS\b/)) return 'raw_material'; if (has(normalizedName, /ETIQUETA|TAG|FITA/)) return 'raw_material'; if (has(normalizedName, /\bCREDITO\b/)) return 'ignore_from_planning'; if (has(normalizedName, /\bKIT\b/)) return 'kit_bundle'; if (has(normalizedName, /TRANSPARENTE PP|SACO DE SEGURANCA|MILHEIRO|SACOLA|EMBALAGEM/)) return 'packaging'; if (has(normalizedName, /PRENSA|MAQUINA|OVERLOCK|OVERLOK|GALONEIRA|PRATELEIRA/)) return 'equipment'; if (has(normalizedName, /FRETE|SERVICO|TRANSPORTE|MOTOTAXI|TECELAGEM|TINTURARIA|MAO DE OBRA/)) return 'service'; if (has(normalizedName, /DUMPER|CABO FLAT|WIPPER|PRIMER|FLUIDO DE LIMPEZA|MISTURADOR|CABECA I3200|CABECA DE IMPRESSAO|SENSOR INFRAVERMELHO|CAPSULA FILTRO|PECA DE MAQUINA/)) return 'machine_part'; if (has(normalizedName, /TINTA DTF|FILME DTF|POLIAMIDA.*DTF|DTF ROLO|PO PARA DTF|BOMBA DE TINTA/)) return 'dtf_input'; if (has(normalizedName, /IMPRESSAO DTF|IMPRESSAO UV|CORRECAO IMPRESSAO|ESTAMPA|PERSONALIZACAO/)) return 'dtf_service'; if (has(normalizedName, /MALHA|RIBANA|FIO|TECIDO|RESIDUO|RETALHO|PIMA|ALGODAO/)) { if (!has(normalizedName, /CAMISETA|MOLETOM|REGATA|BONE|CHINELO|OVERSIZE|OVER SIZE/)) { return 'raw_material'; } } if (has(normalizedName, /BONE|TRUCKER|\bCAP\b|CHINELO/)) return 'finished_accessory'; if (has(normalizedName, /CAMISETA|MOLETOM|CANGURU|REGATA|INFANTIL|OVER SIZE|OVERSIZE|PROMOCIONAL|VESTUARIO/)) return 'finished_apparel'; if (has(normalizedName, /ETIQUETA|TAG|FITA|LINHA PARA COSTURA|COSTURA/)) return 'raw_material'; return 'unknown'; }; export const getProductTypeConfig = (type: ProductTypeKey) => productTypeConfigs[type] || productTypeConfigs.unknown; export const productTypeOptions = Object.values(productTypeConfigs) .filter(config => config.key !== 'ignore_from_planning') .map(config => ({ value: config.key, label: config.label })); export const editableProductTypeOptions = Object.values(productTypeConfigs) .map(config => ({ value: config.key, label: config.label, description: config.description })); export const resolveProductType = ( name: string, override?: { productType?: ProductTypeKey | '' } | null ): ProductTypeKey => { return override?.productType || classifyProductType(name); }; export const getDominantProductType = (rows: T[]) => { if (!rows.length) return 'unknown'; const totals = rows.reduce>((acc, row) => { acc[row.productType] = (acc[row.productType] || 0) + Math.max(row.quantitySold, 1); return acc; }, {}); return (Object.entries(totals).sort((a, b) => b[1] - a[1])[0]?.[0] || 'unknown') as ProductTypeKey; };