false, 'error' => 'phone/user_id and text are required']); exit; } // Normalize encoding - try to ensure UTF-8 if (!function_exists('normalize_text')) { function normalize_text($s) { if (empty($s)) return $s; // If valid UTF-8, attempt to repair common mojibake (Ã, Â) before returning if (mb_check_encoding($s, 'UTF-8')) { if (preg_match('/Ã|Â/', $s)) { $step = @iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s); if ($step) { $step2 = @iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $step); if ($step2 && mb_check_encoding($step2, 'UTF-8')) return $step2; } } return $s; } // Try latin1 -> utf8 $try = @iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $s); if ($try && mb_check_encoding($try, 'UTF-8')) return $try; // Try CP1252 $try2 = @iconv('CP1252', 'UTF-8//TRANSLIT', $s); if ($try2 && mb_check_encoding($try2, 'UTF-8')) return $try2; // Fallback: utf8_decode then re-encode $auto = mb_convert_encoding($s, 'UTF-8', 'auto'); // Try to repair common double-encoding mojibake (look for sequences like à or Â) if (preg_match('/[\xC2\xC3][\x80-\xBF]/', $s) || preg_match('/Ã|Â/', $s)) { $step = @iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s); if ($step) { $step2 = @iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $step); if ($step2 && mb_check_encoding($step2, 'UTF-8')) return $step2; } } return $auto; } } $rawClean = normalize_text($raw); // Parse key: value lines $lines = preg_split('/\r?\n/', $rawClean); $parsed = []; foreach ($lines as $line) { $line = trim($line); if ($line === '') continue; // Try separator ':' or '-' if (strpos($line, ':') !== false) { list($k,$v) = explode(':', $line, 2); } elseif (strpos($line, '?') !== false && preg_match('/^\s*([^\?]+\?)\s*(.+)$/', $line, $m)) { $k = $m[1]; $v = $m[2]; } else { // last resort split by whitespace before last token $parts = preg_split('/\s{2,}/', $line); if (count($parts) === 2) { $k = $parts[0]; $v = $parts[1]; } else { continue; } } $k = trim($k); $v = trim($v); // normalize key and value encoding $k = normalize_text($k); $v = normalize_text($v); $parsed[$k] = $v; } // Map expected questions (in Spanish) to fields if (!function_exists('yesno_to_bool')) { function yesno_to_bool($s) { $s = mb_strtolower($s); // Normalize common utf8 artifacts $s = str_replace(['\u00a0','\xa0'], ' ', $s); $s = trim($s); if (in_array($s, ['si','sí','s','yes','y','true','1'])) return 1; if (in_array($s, ['no','n','false','0'])) return 0; return null; } } $qeasy = null; $qhuman = null; $rating = null; $comment = null; // try keys in parsed foreach ($parsed as $k => $v) { $kl = mb_strtolower($k); if (strpos($kl, 'fue') !== false && strpos($kl, 'facil') !== false) { $qeasy = yesno_to_bool($v); } elseif (strpos($kl, 'asesor') !== false || strpos($kl, 'humano') !== false) { $qhuman = yesno_to_bool($v); } elseif (strpos($kl, 'calificaci') !== false || strpos($kl, 'calificacion') !== false || strpos($kl, 'calificaci') !== false) { $rating = intval(preg_replace('/[^0-9]/','',$v)); } elseif (strpos($kl, 'coment') !== false) { $comment = $v; } } // fallback: try regex in raw if ($qeasy === null) { if (preg_match('/fue\s+([^,:\?]+)\s+interact/i', $rawClean, $m)) { $qeasy = yesno_to_bool($m[1]); } } if ($qhuman === null) { if (preg_match('/asesor.*:\s*([^,\n]+)/i', $rawClean, $m)) { $qhuman = yesno_to_bool($m[1]); } } if ($rating === null) { if (preg_match('/calificaci[oó]n[:\s]*([0-9]+)/i', $rawClean, $m)) { $rating = intval($m[1]); } } if ($comment === null) { if (preg_match('/comentario[:\s]*(.+)$/i', $rawClean, $m)) { $comment = trim($m[1]); } } // Insert into DB try { $db = Database::getInstance(); $phoneNormalized = $phone ? preg_replace('/[^0-9+]/','',$phone) : null; $now = date('Y-m-d H:i:s'); $data = [ 'user_id' => $user_id, 'phone_number' => $phoneNormalized, 'q_easy_interact' => $qeasy, 'q_human_resolved' => $qhuman, 'rating' => $rating, 'comment' => $comment, 'raw_text' => $rawClean, 'created_at' => $now ]; $id = $db->insert('survey_responses', $data); if (function_exists('writeLog')) writeLog('INFO', 'Survey response saved', ['id'=>$id, 'phone'=>$phoneNormalized, 'parsed'=>$parsed]); echo json_encode(['success'=>true,'id'=>$id,'parsed'=>$parsed]); } catch (Exception $e) { http_response_code(500); echo json_encode(['success'=>false,'error'=>$e->getMessage()]); }