false, 'ERROR' => 'missing_params', 'MESSAGE' => 'BusinessID is required']); } try { // If servicePointID not provided but orderID is, look it up if ($servicePointID <= 0 && $orderID > 0) { $qOrderSP = queryOne("SELECT ServicePointID FROM Orders WHERE ID = ?", [$orderID]); if ($qOrderSP && (int) $qOrderSP['ServicePointID'] > 0) { $servicePointID = (int) $qOrderSP['ServicePointID']; } } // Look up "Chat" task type for this business $ttQuery = queryOne(" SELECT ID FROM tt_TaskTypes WHERE BusinessID = ? AND Name LIKE '%Chat%' LIMIT 1 ", [$businessID]); $chatTaskTypeID = $ttQuery ? (int) $ttQuery['ID'] : 0; // Check for existing open chat $forceNew = !empty($data['ForceNew']) && $data['ForceNew'] === true; if (!$forceNew) { $existingChat = queryOne(" SELECT t.ID, t.CreatedOn, (SELECT MAX(cm.CreatedOn) FROM ChatMessages cm WHERE cm.TaskID = t.ID) as LastMessageTime FROM Tasks t LEFT JOIN ChatMessages cm2 ON cm2.TaskID = t.ID AND cm2.SenderUserID = ? WHERE t.BusinessID = ? AND (t.TaskTypeID = ? OR t.Title LIKE 'Chat%') AND t.CompletedOn IS NULL AND ( (t.OrderID = ? AND ? > 0) OR (t.SourceType = 'servicepoint' AND t.SourceID = ? AND ? > 0) OR (t.SourceType = 'user' AND t.SourceID = ? AND ? > 0) OR (cm2.SenderUserID = ? AND ? > 0) ) ORDER BY t.CreatedOn DESC LIMIT 1 ", [ $userID, $businessID, $chatTaskTypeID, $orderID, $orderID, $servicePointID, $servicePointID, $userID, $userID, $userID, $userID, ]); if ($existingChat) { $lastActivity = $existingChat['LastMessageTime']; if (empty($lastActivity)) { $lastActivity = $existingChat['CreatedOn']; } $chatAge = (int) ((time() - strtotime($lastActivity)) / 60); if ($chatAge > 30) { // Auto-close stale chat queryTimed("UPDATE Tasks SET CompletedOn = NOW() WHERE ID = ?", [$existingChat['ID']]); } else { jsonResponse([ 'OK' => true, 'TaskID' => (int) $existingChat['ID'], 'MESSAGE' => 'Rejoined existing chat', 'EXISTING' => true, ]); } } } // Get service point info $tableName = ''; if ($servicePointID > 0) { $spQuery = queryOne("SELECT Name FROM ServicePoints WHERE ID = ?", [$servicePointID]); $tableName = $spQuery ? $spQuery['Name'] : "Table #$servicePointID"; } // Get user name $userName = ''; if ($userID > 0) { $userQuery = queryOne("SELECT FirstName FROM Users WHERE ID = ?", [$userID]); if ($userQuery && !empty(trim($userQuery['FirstName']))) { $userName = $userQuery['FirstName']; } } // Create task title if ($servicePointID > 0) { $taskTitle = !empty($userName) ? "Chat - $userName ($tableName)" : "Chat - $tableName"; } else { $taskTitle = !empty($userName) ? "Chat - $userName (Remote)" : "Remote Chat"; } $taskDetails = !empty($initialMessage) ? $initialMessage : 'Customer initiated chat'; // Look up or create a "Chat" category $catQuery = queryOne(" SELECT ID FROM TaskCategories WHERE BusinessID = ? AND Name = 'Chat' LIMIT 1 ", [$businessID]); if (!$catQuery) { queryTimed(" INSERT INTO TaskCategories (BusinessID, Name, Color) VALUES (?, 'Chat', '#2196F3') ", [$businessID]); $categoryID = (int) lastInsertId(); } else { $categoryID = (int) $catQuery['ID']; } // Determine source type and ID $sourceType = $servicePointID > 0 ? 'servicepoint' : 'user'; $sourceID = $servicePointID > 0 ? $servicePointID : $userID; // Insert task queryTimed(" INSERT INTO Tasks ( BusinessID, CategoryID, OrderID, TaskTypeID, Title, Details, ClaimedByUserID, SourceType, SourceID, CreatedOn ) VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, NOW()) ", [ $businessID, $categoryID, $orderID > 0 ? $orderID : null, $chatTaskTypeID > 0 ? $chatTaskTypeID : null, $taskTitle, $taskDetails, $sourceType, $sourceID, ]); $taskID = (int) lastInsertId(); // If there's an initial message, save it if (!empty($initialMessage) && $userID > 0) { queryTimed(" INSERT INTO ChatMessages (TaskID, SenderUserID, SenderType, MessageBody) VALUES (?, ?, 'customer', ?) ", [$taskID, $userID, $initialMessage]); } jsonResponse([ 'OK' => true, 'TaskID' => $taskID, 'MESSAGE' => 'Chat started', ]); } catch (Exception $e) { jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]); }