validate([ 'message' => ['required', 'string', 'max:1000'], 'thread_id' => ['nullable', 'string', 'uuid'], ]); $message = $request->string('message')->trim()->toString(); if (session('admin_logged_in')) { return $this->handleAdmin($message, $request->input('thread_id')); } return $this->handlePublic($request, $message); } private function handleAdmin(string $message, ?string $threadId): JsonResponse { $adminId = (int) session('admin_id'); $isSuperadmin = (int) session('admin_role') === 1; $thread = AgentThread::findOrCreateForAdmin($threadId, $adminId); $reply = $this->service->chatAdmin($message, $thread, $isSuperadmin); return response()->json([ 'reply' => $reply, 'thread_id' => $thread->thread_id, ]); } private function handlePublic(Request $request, string $message): JsonResponse { $maxMessages = (int) config('services.genius.max_messages_per_session', 20); $windowMin = (int) config('services.genius.session_window_minutes', 60); $session = $request->session(); $startedAt = $session->get('agent_window_started_at'); $count = (int) $session->get('agent_window_count', 0); if ($startedAt === null || (time() - (int) $startedAt) > $windowMin * 60) { $startedAt = time(); $count = 0; } if ($maxMessages > 0 && $count >= $maxMessages) { $remaining = max(1, (int) ceil(($windowMin * 60 - (time() - (int) $startedAt)) / 60)); return response()->json([ 'reply' => "Llegaste al límite de {$maxMessages} consultas por sesión. " . "Volvé a intentar en {$remaining} minuto(s) o contactá directamente a OnAPB.", 'limit_reached' => true, ]); } $history = $session->get('agent_messages', []); $reply = $this->service->chatPublic($message, $history); $history[] = ['role' => 'user', 'content' => $message]; $history[] = ['role' => 'assistant', 'content' => $reply]; $session->put('agent_messages', $history); $session->put('agent_window_started_at', $startedAt); $session->put('agent_window_count', $count + 1); return response()->json(['reply' => $reply]); } }