false]; try { $data = readJsonBody(); if (empty($data)) throw new Exception('No request body provided'); $categories = $data['categories'] ?? []; $detectedTemplates = []; $analyzedCategories = []; foreach ($categories as $cat) { $catName = $cat['name'] ?? ''; $catNote = $cat['categoryNote'] ?? ''; $items = $cat['items'] ?? []; // Check for category-wide patterns in the note $categoryTemplates = []; // "Add to any salad/item" pattern if (preg_match('/add\s+(?:the\s+following\s+)?to\s+any\s+(salad|item)/i', $catNote)) { if (preg_match('/add[^:]+:\s*(.+)/i', $catNote, $addOnMatch)) { $addOnText = $addOnMatch[1]; $addOnItems = array_map('trim', explode(',', $addOnText)); $templateID = 'cat_' . strtolower(preg_replace('/\W+/', '_', $catName)) . '_addons'; if (!isset($detectedTemplates[$templateID])) { $options = [['name' => 'None', 'price' => 0, 'isDefault' => true]]; foreach ($addOnItems as $addon) { $addon = trim($addon); if (!empty($addon)) { $options[] = ['name' => $addon, 'price' => 0, 'isDefault' => false]; } } $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Add Protein', 'options' => $options, 'required' => false, 'maxSelections' => 1, 'detectedFrom' => "Category note: $catName", 'appliesTo' => [], ]; } $categoryTemplates[] = $templateID; } } // Analyze each item $analyzedItems = []; foreach ($items as $item) { $itemName = $item['name'] ?? ''; $itemDesc = $item['description'] ?? ''; $itemMods = []; // Apply category-wide templates foreach ($categoryTemplates as $catTmpl) { $itemMods[] = $catTmpl; $detectedTemplates[$catTmpl]['appliesTo'][] = $itemName; } // Size patterns (small available) if (preg_match('/\bsmall\s*(available|option)?\b/i', $itemDesc) || preg_match('/\bsmall\b/i', $itemName)) { $templateID = 'size_regular_small'; if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Size', 'options' => [ ['name' => 'Regular', 'price' => 0, 'isDefault' => true], ['name' => 'Small', 'price' => 0, 'isDefault' => false], ], 'required' => true, 'maxSelections' => 1, 'detectedFrom' => "Pattern: 'Small available'", 'appliesTo' => [], ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } // Half order pattern if (preg_match('/\b(1\/2|half)\s*(order)?\s*(available)?\b/i', $itemDesc)) { $templateID = 'size_full_half'; if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Size', 'options' => [ ['name' => 'Full Order', 'price' => 0, 'isDefault' => true], ['name' => 'Half Order', 'price' => 0, 'isDefault' => false], ], 'required' => true, 'maxSelections' => 1, 'detectedFrom' => "Pattern: '1/2 order available'", 'appliesTo' => [], ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } // Boneless or bone in if (preg_match('/\bboneless\s+(or|\/)\s*bone\s*-?\s*in\b/i', $itemDesc)) { $templateID = 'wing_style'; if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Style', 'options' => [ ['name' => 'Bone-In', 'price' => 0, 'isDefault' => true], ['name' => 'Boneless', 'price' => 0, 'isDefault' => false], ], 'required' => true, 'maxSelections' => 1, 'detectedFrom' => "Pattern: 'Boneless or bone in'", 'appliesTo' => [], ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } // Protein add-on (With Chicken / With Steak or Shrimp) if (preg_match('/with\s+chicken.*(?:steak|shrimp)/i', $itemDesc)) { $templateID = 'protein_addon'; if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Add Protein', 'options' => [ ['name' => 'Plain', 'price' => 0, 'isDefault' => true], ['name' => 'With Chicken', 'price' => 0, 'isDefault' => false], ['name' => 'With Steak or Shrimp', 'price' => 0, 'isDefault' => false], ], 'required' => false, 'maxSelections' => 1, 'detectedFrom' => "Pattern: 'With Chicken / With Steak or Shrimp'", 'appliesTo' => [], ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } // "add X +$Y" pattern if (preg_match_all('/add\s+(\w+(?:\s+(?:and\s+)?\w+)?)\s*[.\+]?\s*(\d+(?:\.\d{2})?)/i', $itemDesc, $priceMatches)) { $templateID = 'addon_' . strtolower(preg_replace('/\W+/', '_', $itemName)); if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Add-ons', 'options' => [], 'required' => false, 'maxSelections' => 0, 'detectedFrom' => "Pattern: 'Add X +\$Y' in $itemName", 'appliesTo' => [], 'needsPricing' => true, ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } // "with guacamole" pattern if (preg_match('/\bwith\s+guacamole\b/i', $itemDesc)) { $templateID = 'addon_guacamole'; if (!isset($detectedTemplates[$templateID])) { $detectedTemplates[$templateID] = [ 'id' => $templateID, 'name' => 'Add Guacamole', 'options' => [ ['name' => 'No Guacamole', 'price' => 0, 'isDefault' => true], ['name' => 'Add Guacamole', 'price' => 0, 'isDefault' => false], ], 'required' => false, 'maxSelections' => 1, 'detectedFrom' => "Pattern: 'With guacamole'", 'appliesTo' => [], 'needsPricing' => true, ]; } $itemMods[] = $templateID; $detectedTemplates[$templateID]['appliesTo'][] = $itemName; } $analyzedItems[] = [ 'name' => $itemName, 'description' => $itemDesc, 'price' => $item['price'] ?? 0, 'detectedModifiers' => $itemMods, 'originalDescription' => $itemDesc, ]; } $analyzedCategories[] = [ 'name' => $catName, 'categoryNote' => $catNote, 'items' => $analyzedItems, 'categoryWideTemplates' => $categoryTemplates, ]; } // Build template array sorted by usage count $templateArray = array_values($detectedTemplates); foreach ($templateArray as &$tmpl) { $tmpl['usageCount'] = count($tmpl['appliesTo']); } unset($tmpl); usort($templateArray, fn($a, $b) => $b['usageCount'] - $a['usageCount']); // Generate questions $questions = []; if (!empty($templateArray)) { $questions[] = [ 'type' => 'confirm_templates', 'question' => 'I detected these modifier groups. Are they correct?', 'templates' => $templateArray, ]; } $itemsNeedingPrices = []; foreach ($analyzedCategories as $cat) { foreach ($cat['items'] as $item) { if (($item['price'] ?? 0) == 0) { $itemsNeedingPrices[] = ['category' => $cat['name'], 'item' => $item['name']]; } } } if (!empty($itemsNeedingPrices)) { $questions[] = ['type' => 'pricing_needed', 'question' => 'These items need prices:', 'items' => $itemsNeedingPrices]; } $templatesNeedingPrices = []; foreach ($templateArray as $tmpl) { if (!empty($tmpl['needsPricing'])) { $templatesNeedingPrices[] = [ 'templateId' => $tmpl['id'], 'templateName' => $tmpl['name'], 'appliesTo' => $tmpl['appliesTo'], ]; } } if (!empty($templatesNeedingPrices)) { $questions[] = ['type' => 'modifier_pricing_needed', 'question' => 'These add-on options need prices:', 'templates' => $templatesNeedingPrices]; } // Count totals $totalItems = 0; $totalLinks = 0; foreach ($analyzedCategories as $cat) { $totalItems += count($cat['items']); foreach ($cat['items'] as $item) { $totalLinks += count($item['detectedModifiers']); } } $response['OK'] = true; $response['analyzedMenu'] = [ 'categories' => $analyzedCategories, 'detectedTemplates' => $templateArray, 'totalItems' => $totalItems, 'totalTemplates' => count($templateArray), 'totalModifierLinks' => $totalLinks, ]; $response['questions'] = $questions; $response['summary'] = "Analyzed $totalItems items, detected " . count($templateArray) . " modifier templates with $totalLinks links"; } catch (Exception $e) { $response['error'] = $e->getMessage(); } jsonResponse($response);