isLoggedIn()) { throw new Exception('Unauthorized'); } $db = Database::getInstance(); // Get input data $input = json_decode(file_get_contents('php://input'), true); $action = $input['action'] ?? ''; switch ($action) { case 'start': $result = startAnalysis($db, $input); break; case 'pause': $result = pauseAnalysis($db); break; case 'stop': $result = stopAnalysis($db); break; case 'reset': $result = resetAnalysis($db); break; default: throw new Exception('Invalid action'); } echo json_encode($result); } catch (Exception $e) { http_response_code(500); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); } function startAnalysis($db, $input) { try { // Check if analysis is already running $stateQuery = $db->query("SELECT * FROM optimization_analysis_state ORDER BY id DESC LIMIT 1"); $state = $stateQuery ? $stateQuery->fetch_assoc() : null; if ($state && $state['is_running']) { return [ 'success' => false, 'message' => 'Analysis is already running' ]; } // Get total combinations $totalResult = $db->query("SELECT COUNT(*) as count FROM panel_directives"); $totalCombinations = $totalResult ? $totalResult->fetch_assoc()['count'] : 0; if ($totalCombinations == 0) { return [ 'success' => false, 'message' => 'No combinations found. Generate combinations first in the Base section.' ]; } // **PRESERVE EXISTING PROGRESS** - Count what's already been processed $processedResult = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE llm_checked = 1"); $currentProcessed = $processedResult ? $processedResult->fetch_assoc()['count'] : 0; // Use the progress sent from frontend if available, otherwise use database count $preserveProgress = $input['preserve_progress'] ?? true; $frontendProgress = $input['current_progress'] ?? 0; // Use the higher of the two to ensure we never go backwards $actualProgress = max($currentProcessed, $frontendProgress); // Update or create analysis state WITHOUT resetting progress if ($state) { // Update existing state, preserving progress $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 1, should_pause = 0, started_at = NOW(), completed_at = NULL, total_combinations = ?, processed_combinations = GREATEST(processed_combinations, ?, ?) WHERE id = ?"); $stmt->bind_param('iiii', $totalCombinations, $actualProgress, $currentProcessed, $state['id']); } else { // Create new state with current progress $stmt = $db->prepare("INSERT INTO optimization_analysis_state (total_combinations, processed_combinations, is_running, started_at, should_pause) VALUES (?, ?, 1, NOW(), 0)"); $stmt->bind_param('ii', $totalCombinations, $actualProgress); } if (!$stmt->execute()) { throw new Exception("Failed to update analysis state: " . $db->getLastError()); } // Start background process $processFile = file_exists('enhanced_process_optimization.php') ? 'enhanced_process_optimization.php' : 'process_optimization_analysis.php'; if (function_exists('exec')) { $command = "php " . __DIR__ . "/$processFile > /dev/null 2>&1 &"; exec($command, $output, $returnCode); if ($returnCode !== 0) { error_log("Warning: Background process may not have started properly. Return code: $returnCode"); } } else { error_log("Warning: exec() function not available. Background processing may not work."); } $remaining = $totalCombinations - $actualProgress; return [ 'success' => true, 'message' => 'Analysis started successfully', 'total_combinations' => $totalCombinations, 'current_progress' => $actualProgress, 'remaining' => $remaining, 'resumed_from' => $actualProgress > 0, 'process_file' => $processFile ]; } catch (Exception $e) { error_log("Error starting analysis: " . $e->getMessage()); return [ 'success' => false, 'message' => 'Failed to start analysis: ' . $e->getMessage() ]; } } function pauseAnalysis($db) { try { $stmt = $db->prepare("UPDATE optimization_analysis_state SET should_pause = 1 WHERE is_running = 1"); if ($stmt->execute()) { return [ 'success' => true, 'message' => 'Analysis paused successfully' ]; } else { throw new Exception("Failed to pause analysis"); } } catch (Exception $e) { return [ 'success' => false, 'message' => 'Failed to pause analysis: ' . $e->getMessage() ]; } } function stopAnalysis($db) { try { $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 0, should_pause = 0, completed_at = NOW() WHERE is_running = 1"); if ($stmt->execute()) { return [ 'success' => true, 'message' => 'Analysis stopped successfully' ]; } else { throw new Exception("Failed to stop analysis"); } } catch (Exception $e) { return [ 'success' => false, 'message' => 'Failed to stop analysis: ' . $e->getMessage() ]; } } function resetAnalysis($db) { try { // First stop any running analysis $db->query("UPDATE optimization_analysis_state SET is_running = 0, should_pause = 0"); // Reset all progress (only if user explicitly wants to reset) $db->query("UPDATE panel_directives SET llm_checked = 0, is_impossible = 0, llm_reasoning = NULL, status = 'pending'"); // Reset analysis state $db->query("UPDATE optimization_analysis_state SET processed_combinations = 0, completed_at = NULL, started_at = NULL"); return [ 'success' => true, 'message' => 'Analysis reset successfully. All progress cleared.' ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Failed to reset analysis: ' . $e->getMessage() ]; } } ?>