{"repo": "alceujrab/laracrm", "files": {"app/Http/Controllers/AppSettingsController.php": {"bbd317c6685c4f2d667e455af28208fb249fe99d": {"t": 1785746161.2559805, "n": 17170, "h": "b5ae5f65059b2c48", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n\n public function getClickSendSettings()\n {\n return response()->json([\n 'clicksend_username' => (string) AppSetting::getSetting('clicksend_username', ''),\n 'clicksend_api_key' => (string) AppSetting::getSetting('clicksend_api_key', ''),\n 'clicksend_default_from' => (string) AppSetting::getSetting('clicksend_default_from', ''),\n ]);\n }\n\n public function updateClickSendSettings(Request $request)\n {\n $request->validate([\n 'clicksend_username' => 'nullable|string|max:500',\n 'clicksend_api_key' => 'nullable|string|max:500',\n 'clicksend_default_from' => 'nullable|string|max:50',\n ]);\n\n AppSetting::setSetting('clicksend_username', $request->input('clicksend_username', ''));\n AppSetting::setSetting('clicksend_api_key', $request->input('clicksend_api_key', ''));\n AppSetting::setSetting('clicksend_default_from', $request->input('clicksend_default_from', ''));\n\n return response()->json(['message' => 'Credenciais do ClickSend salvas com sucesso!']);\n }\n\n public function testClickSendConnection(Request $request)\n {\n $request->validate([\n 'username' => 'required|string',\n 'api_key' => 'required|string',\n ]);\n\n $ok = app(ClickSendService::class)\n ->testCredentials($request->username, $request->api_key);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com ClickSend estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique as credenciais.'], 422);\n }\n\n public function getSmsMaisSettings()\n {\n return response()->json([\n 'smsmais_token' => (string) AppSetting::getSetting('smsmais_token', ''),\n ]);\n }\n\n public function updateSmsMaisSettings(Request $request)\n {\n $request->validate([\n 'smsmais_token' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('smsmais_token', $request->input('smsmais_token', ''));\n\n return response()->json(['message' => 'Credenciais do SMS Mais salvas com sucesso!']);\n }\n\n public function testSmsMaisConnection(Request $request)\n {\n $request->validate([\n 'token' => 'required|string',\n ]);\n\n $ok = app(SmsMaisService::class)->testCredentials($request->token);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com SMS Mais estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Token inválido ou conta bloqueada.'], 422);\n }\n\n public function getAwsSettings()\n {\n return response()->json([\n 'aws_access_key_id' => (string) AppSetting::getSetting('aws_access_key_id', ''),\n 'aws_secret_access_key' => (string) AppSetting::getSetting('aws_secret_access_key', ''),\n 'aws_region' => (string) AppSetting::getSetting('aws_region', 'sa-east-1'),\n 'aws_account_id' => (string) AppSetting::getSetting('aws_account_id', '195202617322'),\n 'aws_sns_sms_sender_id' => (string) AppSetting::getSetting('aws_sns_sms_sender_id', 'EliteVeic'),\n 'aws_sns_sms_type' => (string) AppSetting::getSetting('aws_sns_sms_type', 'Transactional'),\n 'aws_sns_platform_app_arn_fcm' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_fcm', ''),\n 'aws_sns_platform_app_arn_apns' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_apns', ''),\n ]);\n }\n\n public function updateAwsSettings(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'nullable|string|max:500',\n 'aws_secret_access_key' => 'nullable|string|max:500',\n 'aws_region' => 'nullable|string|max:50',\n 'aws_account_id' => 'nullable|string|max:20',\n 'aws_sns_sms_sender_id' => 'nullable|string|max:11',\n 'aws_sns_sms_type' => 'nullable|string|in:Transactional,Promotional',\n 'aws_sns_platform_app_arn_fcm' => 'nullable|string|max:500',\n 'aws_sns_platform_app_arn_apns' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('aws_access_key_id', $request->input('aws_access_key_id', ''));\n AppSetting::setSetting('aws_secret_access_key', $request->input('aws_secret_access_key', ''));\n AppSetting::setSetting('aws_region', $request->input('aws_region', 'sa-east-1'));\n AppSetting::setSetting('aws_account_id', $request->input('aws_account_id', ''));\n AppSetting::setSetting('aws_sns_sms_sender_id', $request->input('aws_sns_sms_sender_id', ''));\n AppSetting::setSetting('aws_sns_sms_type', $request->input('aws_sns_sms_type', 'Transactional'));\n AppSetting::setSetting('aws_sns_platform_app_arn_fcm', $request->input('aws_sns_platform_app_arn_fcm', ''));\n AppSetting::setSetting('aws_sns_platform_app_arn_apns', $request->input('aws_sns_platform_app_arn_apns', ''));\n\n return response()->json(['message' => 'Credenciais AWS salvas com sucesso!']);\n }\n\n public function testAwsConnection(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'required|string',\n 'aws_secret_access_key' => 'required|string',\n 'aws_region' => 'nullable|string|max:50',\n ]);\n\n $ok = app(AwsSnsService::class)->testCredentials(\n $request->aws_access_key_id,\n $request->aws_secret_access_key,\n $request->input('aws_region', 'sa-east-1'),\n );\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com AWS SNS estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique Access Key, Secret Key e região (sa-east-1).'], 422);\n }\n\n public function getSmsProvider()\n {\n return response()->json([\n 'provider' => (string) AppSetting::getSetting('sms_primary_provider', 'aws'),\n ]);\n }\n\n public function setSmsProvider(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:aws,clicksend,smsmais',\n ]);\n\n AppSetting::setSetting('sms_primary_provider', $request->provider);\n\n $name = match ($request->provider) {\n 'clicksend' => 'ClickSend',\n 'smsmais' => 'SMS Mais',\n default => 'AWS SNS',\n };\n\n return response()->json(['message' => \"{$name} definido como provedor principal de SMS!\"]);\n }\n\n public function updateThemePresets(Request $request, ThemeSettingsService $themes): RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n 'tokens' => ['required', 'array'],\n ]);\n\n $themes->saveThemeTokens($validated['theme_id'], $validated['tokens']);\n\n return back()->with('success', 'Paleta do tema salva com sucesso!');\n }\n\n public function resetThemePreset(Request $request, ThemeSettingsService $themes): RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n ]);\n\n $themes->resetTheme($validated['theme_id']);\n\n return back()->with('success', 'Tema restaurado para os valores padrão de fábrica.');\n }\n}\n"}, "78c7b6b6502b44e7e365b1b2df684c3069a9db8d": {"t": 1785760282.17778, "n": 17170, "h": "b5ae5f65059b2c48", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n\n public function getClickSendSettings()\n {\n return response()->json([\n 'clicksend_username' => (string) AppSetting::getSetting('clicksend_username', ''),\n 'clicksend_api_key' => (string) AppSetting::getSetting('clicksend_api_key', ''),\n 'clicksend_default_from' => (string) AppSetting::getSetting('clicksend_default_from', ''),\n ]);\n }\n\n public function updateClickSendSettings(Request $request)\n {\n $request->validate([\n 'clicksend_username' => 'nullable|string|max:500',\n 'clicksend_api_key' => 'nullable|string|max:500',\n 'clicksend_default_from' => 'nullable|string|max:50',\n ]);\n\n AppSetting::setSetting('clicksend_username', $request->input('clicksend_username', ''));\n AppSetting::setSetting('clicksend_api_key', $request->input('clicksend_api_key', ''));\n AppSetting::setSetting('clicksend_default_from', $request->input('clicksend_default_from', ''));\n\n return response()->json(['message' => 'Credenciais do ClickSend salvas com sucesso!']);\n }\n\n public function testClickSendConnection(Request $request)\n {\n $request->validate([\n 'username' => 'required|string',\n 'api_key' => 'required|string',\n ]);\n\n $ok = app(ClickSendService::class)\n ->testCredentials($request->username, $request->api_key);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com ClickSend estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique as credenciais.'], 422);\n }\n\n public function getSmsMaisSettings()\n {\n return response()->json([\n 'smsmais_token' => (string) AppSetting::getSetting('smsmais_token', ''),\n ]);\n }\n\n public function updateSmsMaisSettings(Request $request)\n {\n $request->validate([\n 'smsmais_token' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('smsmais_token', $request->input('smsmais_token', ''));\n\n return response()->json(['message' => 'Credenciais do SMS Mais salvas com sucesso!']);\n }\n\n public function testSmsMaisConnection(Request $request)\n {\n $request->validate([\n 'token' => 'required|string',\n ]);\n\n $ok = app(SmsMaisService::class)->testCredentials($request->token);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com SMS Mais estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Token inválido ou conta bloqueada.'], 422);\n }\n\n public function getAwsSettings()\n {\n return response()->json([\n 'aws_access_key_id' => (string) AppSetting::getSetting('aws_access_key_id', ''),\n 'aws_secret_access_key' => (string) AppSetting::getSetting('aws_secret_access_key', ''),\n 'aws_region' => (string) AppSetting::getSetting('aws_region', 'sa-east-1'),\n 'aws_account_id' => (string) AppSetting::getSetting('aws_account_id', '195202617322'),\n 'aws_sns_sms_sender_id' => (string) AppSetting::getSetting('aws_sns_sms_sender_id', 'EliteVeic'),\n 'aws_sns_sms_type' => (string) AppSetting::getSetting('aws_sns_sms_type', 'Transactional'),\n 'aws_sns_platform_app_arn_fcm' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_fcm', ''),\n 'aws_sns_platform_app_arn_apns' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_apns', ''),\n ]);\n }\n\n public function updateAwsSettings(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'nullable|string|max:500',\n 'aws_secret_access_key' => 'nullable|string|max:500',\n 'aws_region' => 'nullable|string|max:50',\n 'aws_account_id' => 'nullable|string|max:20',\n 'aws_sns_sms_sender_id' => 'nullable|string|max:11',\n 'aws_sns_sms_type' => 'nullable|string|in:Transactional,Promotional',\n 'aws_sns_platform_app_arn_fcm' => 'nullable|string|max:500',\n 'aws_sns_platform_app_arn_apns' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('aws_access_key_id', $request->input('aws_access_key_id', ''));\n AppSetting::setSetting('aws_secret_access_key', $request->input('aws_secret_access_key', ''));\n AppSetting::setSetting('aws_region', $request->input('aws_region', 'sa-east-1'));\n AppSetting::setSetting('aws_account_id', $request->input('aws_account_id', ''));\n AppSetting::setSetting('aws_sns_sms_sender_id', $request->input('aws_sns_sms_sender_id', ''));\n AppSetting::setSetting('aws_sns_sms_type', $request->input('aws_sns_sms_type', 'Transactional'));\n AppSetting::setSetting('aws_sns_platform_app_arn_fcm', $request->input('aws_sns_platform_app_arn_fcm', ''));\n AppSetting::setSetting('aws_sns_platform_app_arn_apns', $request->input('aws_sns_platform_app_arn_apns', ''));\n\n return response()->json(['message' => 'Credenciais AWS salvas com sucesso!']);\n }\n\n public function testAwsConnection(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'required|string',\n 'aws_secret_access_key' => 'required|string',\n 'aws_region' => 'nullable|string|max:50',\n ]);\n\n $ok = app(AwsSnsService::class)->testCredentials(\n $request->aws_access_key_id,\n $request->aws_secret_access_key,\n $request->input('aws_region', 'sa-east-1'),\n );\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com AWS SNS estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique Access Key, Secret Key e região (sa-east-1).'], 422);\n }\n\n public function getSmsProvider()\n {\n return response()->json([\n 'provider' => (string) AppSetting::getSetting('sms_primary_provider', 'aws'),\n ]);\n }\n\n public function setSmsProvider(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:aws,clicksend,smsmais',\n ]);\n\n AppSetting::setSetting('sms_primary_provider', $request->provider);\n\n $name = match ($request->provider) {\n 'clicksend' => 'ClickSend',\n 'smsmais' => 'SMS Mais',\n default => 'AWS SNS',\n };\n\n return response()->json(['message' => \"{$name} definido como provedor principal de SMS!\"]);\n }\n\n public function updateThemePresets(Request $request, ThemeSettingsService $themes): RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n 'tokens' => ['required', 'array'],\n ]);\n\n $themes->saveThemeTokens($validated['theme_id'], $validated['tokens']);\n\n return back()->with('success', 'Paleta do tema salva com sucesso!');\n }\n\n public function resetThemePreset(Request $request, ThemeSettingsService $themes): RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n ]);\n\n $themes->resetTheme($validated['theme_id']);\n\n return back()->with('success', 'Tema restaurado para os valores padrão de fábrica.');\n }\n}\n"}, "d6960095eb18ce5bfdee09139197aa14cd73f9da": {"t": 1785760283.979137, "n": 17166, "h": "12c1612f7b0a433a", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n\n public function getClickSendSettings()\n {\n return response()->json([\n 'clicksend_username' => (string) AppSetting::getSetting('clicksend_username', ''),\n 'clicksend_api_key' => (string) AppSetting::getSetting('clicksend_api_key', ''),\n 'clicksend_default_from' => (string) AppSetting::getSetting('clicksend_default_from', ''),\n ]);\n }\n\n public function updateClickSendSettings(Request $request)\n {\n $request->validate([\n 'clicksend_username' => 'nullable|string|max:500',\n 'clicksend_api_key' => 'nullable|string|max:500',\n 'clicksend_default_from' => 'nullable|string|max:50',\n ]);\n\n AppSetting::setSetting('clicksend_username', $request->input('clicksend_username', ''));\n AppSetting::setSetting('clicksend_api_key', $request->input('clicksend_api_key', ''));\n AppSetting::setSetting('clicksend_default_from', $request->input('clicksend_default_from', ''));\n\n return response()->json(['message' => 'Credenciais do ClickSend salvas com sucesso!']);\n }\n\n public function testClickSendConnection(Request $request)\n {\n $request->validate([\n 'username' => 'required|string',\n 'api_key' => 'required|string',\n ]);\n\n $ok = app(ClickSendService::class)\n ->testCredentials($request->username, $request->api_key);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com ClickSend estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique as credenciais.'], 422);\n }\n\n public function getSmsMaisSettings()\n {\n return response()->json([\n 'smsmais_token' => (string) AppSetting::getSetting('smsmais_token', ''),\n ]);\n }\n\n public function updateSmsMaisSettings(Request $request)\n {\n $request->validate([\n 'smsmais_token' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('smsmais_token', $request->input('smsmais_token', ''));\n\n return response()->json(['message' => 'Credenciais do SMS Mais salvas com sucesso!']);\n }\n\n public function testSmsMaisConnection(Request $request)\n {\n $request->validate([\n 'token' => 'required|string',\n ]);\n\n $ok = app(SmsMaisService::class)->testCredentials($request->token);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com SMS Mais estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Token inválido ou conta bloqueada.'], 422);\n }\n\n public function getAwsSettings()\n {\n return response()->json([\n 'aws_access_key_id' => (string) AppSetting::getSetting('aws_access_key_id', ''),\n 'aws_secret_access_key' => (string) AppSetting::getSetting('aws_secret_access_key', ''),\n 'aws_region' => (string) AppSetting::getSetting('aws_region', 'sa-east-1'),\n 'aws_account_id' => (string) AppSetting::getSetting('aws_account_id', '195202617322'),\n 'aws_sns_sms_sender_id' => (string) AppSetting::getSetting('aws_sns_sms_sender_id', 'EliteVeic'),\n 'aws_sns_sms_type' => (string) AppSetting::getSetting('aws_sns_sms_type', 'Transactional'),\n 'aws_sns_platform_app_arn_fcm' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_fcm', ''),\n 'aws_sns_platform_app_arn_apns' => (string) AppSetting::getSetting('aws_sns_platform_app_arn_apns', ''),\n ]);\n }\n\n public function updateAwsSettings(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'nullable|string|max:500',\n 'aws_secret_access_key' => 'nullable|string|max:500',\n 'aws_region' => 'nullable|string|max:50',\n 'aws_account_id' => 'nullable|string|max:20',\n 'aws_sns_sms_sender_id' => 'nullable|string|max:11',\n 'aws_sns_sms_type' => 'nullable|string|in:Transactional,Promotional',\n 'aws_sns_platform_app_arn_fcm' => 'nullable|string|max:500',\n 'aws_sns_platform_app_arn_apns' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('aws_access_key_id', $request->input('aws_access_key_id', ''));\n AppSetting::setSetting('aws_secret_access_key', $request->input('aws_secret_access_key', ''));\n AppSetting::setSetting('aws_region', $request->input('aws_region', 'sa-east-1'));\n AppSetting::setSetting('aws_account_id', $request->input('aws_account_id', ''));\n AppSetting::setSetting('aws_sns_sms_sender_id', $request->input('aws_sns_sms_sender_id', ''));\n AppSetting::setSetting('aws_sns_sms_type', $request->input('aws_sns_sms_type', 'Transactional'));\n AppSetting::setSetting('aws_sns_platform_app_arn_fcm', $request->input('aws_sns_platform_app_arn_fcm', ''));\n AppSetting::setSetting('aws_sns_platform_app_arn_apns', $request->input('aws_sns_platform_app_arn_apns', ''));\n\n return response()->json(['message' => 'Credenciais AWS salvas com sucesso!']);\n }\n\n public function testAwsConnection(Request $request)\n {\n $request->validate([\n 'aws_access_key_id' => 'required|string',\n 'aws_secret_access_key' => 'required|string',\n 'aws_region' => 'nullable|string|max:50',\n ]);\n\n $ok = app(AwsSnsService::class)->testCredentials(\n $request->aws_access_key_id,\n $request->aws_secret_access_key,\n $request->input('aws_region', 'sa-east-1'),\n );\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com AWS SNS estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique Access Key, Secret Key e região (sa-east-1).'], 422);\n }\n\n public function getSmsProvider()\n {\n return response()->json([\n 'provider' => (string) AppSetting::getSetting('sms_primary_provider', 'aws'),\n ]);\n }\n\n public function setSmsProvider(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:aws,clicksend,smsmais',\n ]);\n\n AppSetting::setSetting('sms_primary_provider', $request->provider);\n\n $name = match ($request->provider) {\n 'clicksend' => 'ClickSend',\n 'smsmais' => 'SMS Mais',\n default => 'AWS SNS',\n };\n\n return response()->json(['message' => \"{$name} definido como provedor principal de SMS!\"]);\n }\n\n public function updateThemePresets(Request $request, ThemeSettingsService $themes): \\Illuminate\\Http\\RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n 'tokens' => ['required', 'array'],\n ]);\n\n $themes->saveThemeTokens($validated['theme_id'], $validated['tokens']);\n\n return back()->with('success', 'Paleta do tema salva com sucesso!');\n }\n\n public function resetThemePreset(Request $request, ThemeSettingsService $themes): \\Illuminate\\Http\\RedirectResponse\n {\n $validated = $request->validate([\n 'theme_id' => ['required', 'string', 'in:'.implode(',', ThemeSettingsService::THEME_IDS)],\n ]);\n\n $themes->resetTheme($validated['theme_id']);\n\n return back()->with('success', 'Tema restaurado para os valores padrão de fábrica.');\n }\n}\n"}, "8bc027be0174ca9df46b88b47688635303cae8b8": {"t": 1785760285.4850564, "n": 12843, "h": "a877dcfb86c72663", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n\n public function getClickSendSettings()\n {\n return response()->json([\n 'clicksend_username' => (string) AppSetting::getSetting('clicksend_username', ''),\n 'clicksend_api_key' => (string) AppSetting::getSetting('clicksend_api_key', ''),\n 'clicksend_default_from' => (string) AppSetting::getSetting('clicksend_default_from', ''),\n ]);\n }\n\n public function updateClickSendSettings(Request $request)\n {\n $request->validate([\n 'clicksend_username' => 'nullable|string|max:500',\n 'clicksend_api_key' => 'nullable|string|max:500',\n 'clicksend_default_from' => 'nullable|string|max:50',\n ]);\n\n AppSetting::setSetting('clicksend_username', $request->input('clicksend_username', ''));\n AppSetting::setSetting('clicksend_api_key', $request->input('clicksend_api_key', ''));\n AppSetting::setSetting('clicksend_default_from', $request->input('clicksend_default_from', ''));\n\n return response()->json(['message' => 'Credenciais do ClickSend salvas com sucesso!']);\n }\n\n public function testClickSendConnection(Request $request)\n {\n $request->validate([\n 'username' => 'required|string',\n 'api_key' => 'required|string',\n ]);\n\n $ok = app(ClickSendService::class)\n ->testCredentials($request->username, $request->api_key);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com ClickSend estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique as credenciais.'], 422);\n }\n\n public function getSmsMaisSettings()\n {\n return response()->json([\n 'smsmais_token' => (string) AppSetting::getSetting('smsmais_token', ''),\n ]);\n }\n\n public function updateSmsMaisSettings(Request $request)\n {\n $request->validate([\n 'smsmais_token' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('smsmais_token', $request->input('smsmais_token', ''));\n\n return response()->json(['message' => 'Credenciais do SMS Mais salvas com sucesso!']);\n }\n\n public function testSmsMaisConnection(Request $request)\n {\n $request->validate([\n 'token' => 'required|string',\n ]);\n\n $ok = app(SmsMaisService::class)->testCredentials($request->token);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com SMS Mais estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Token inválido ou conta bloqueada.'], 422);\n }\n\n public function getSmsProvider()\n {\n return response()->json([\n 'provider' => (string) AppSetting::getSetting('sms_primary_provider', 'clicksend'),\n ]);\n }\n\n public function setSmsProvider(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:clicksend,smsmais',\n ]);\n\n AppSetting::setSetting('sms_primary_provider', $request->provider);\n\n $name = $request->provider === 'smsmais' ? 'SMS Mais' : 'ClickSend';\n\n return response()->json(['message' => \"{$name} definido como provedor principal de SMS!\"]);\n }\n}\n"}, "4881c49fe26ae91685bf7693be68d81b58cdca87": {"t": 1785760286.717684, "n": 11191, "h": "850e32b94932ae9a", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n\n public function getClickSendSettings()\n {\n return response()->json([\n 'clicksend_username' => (string) AppSetting::getSetting('clicksend_username', ''),\n 'clicksend_api_key' => (string) AppSetting::getSetting('clicksend_api_key', ''),\n 'clicksend_default_from' => (string) AppSetting::getSetting('clicksend_default_from', ''),\n ]);\n }\n\n public function updateClickSendSettings(Request $request)\n {\n $request->validate([\n 'clicksend_username' => 'nullable|string|max:500',\n 'clicksend_api_key' => 'nullable|string|max:500',\n 'clicksend_default_from' => 'nullable|string|max:50',\n ]);\n\n AppSetting::setSetting('clicksend_username', $request->input('clicksend_username', ''));\n AppSetting::setSetting('clicksend_api_key', $request->input('clicksend_api_key', ''));\n AppSetting::setSetting('clicksend_default_from', $request->input('clicksend_default_from', ''));\n\n return response()->json(['message' => 'Credenciais do ClickSend salvas com sucesso!']);\n }\n\n public function testClickSendConnection(Request $request)\n {\n $request->validate([\n 'username' => 'required|string',\n 'api_key' => 'required|string',\n ]);\n\n $ok = app(ClickSendService::class)\n ->testCredentials($request->username, $request->api_key);\n\n if ($ok) {\n return response()->json(['message' => 'Conexão com ClickSend estabelecida com sucesso!']);\n }\n\n return response()->json(['message' => 'Falha na conexão. Verifique as credenciais.'], 422);\n }\n}\n"}, "623c06932bf95baee2e1e64b551f2b9113788380": {"t": 1785760288.2910323, "n": 9508, "h": "2cde3fcf3efcee2a", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (! is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (! is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: '.$response->body());\n }\n } elseif ($provider === 'openai') {\n $response = Http::withHeaders([\n 'Authorization' => 'Bearer '.$apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API OpenAI: '.$response->body());\n }\n } elseif ($provider === 'claude') {\n $response = Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Claude: '.$response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key='.$apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (! $response->successful()) {\n throw new \\Exception('Erro na API Gemini: '.$response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: '.$e->getMessage()], 400);\n }\n }\n\n public function getGoogleSettings()\n {\n return response()->json([\n 'google_client_id' => (string) AppSetting::getSetting('google_client_id', ''),\n 'google_client_secret' => (string) AppSetting::getSetting('google_client_secret', ''),\n 'google_redirect_uri' => url('/auth/google/callback'),\n ]);\n }\n\n public function updateGoogleSettings(Request $request)\n {\n $request->validate([\n 'google_client_id' => 'nullable|string|max:500',\n 'google_client_secret' => 'nullable|string|max:500',\n ]);\n\n AppSetting::setSetting('google_client_id', $request->input('google_client_id', ''));\n AppSetting::setSetting('google_client_secret', $request->input('google_client_secret', ''));\n\n return response()->json(['message' => 'Credenciais do Google salvas com sucesso!']);\n }\n}\n"}, "eb0f6aec29cbeedc3958b8a508d13bd7e5289ffe": {"t": 1785760289.9083607, "n": 8708, "h": "cb992ec21fa4c9b1", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (!is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (!is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n\n public function getAiSettings()\n {\n return response()->json([\n 'ai_market_provider' => AppSetting::getSetting('ai_market_provider', 'deepseek'),\n 'ai_api_key_deepseek' => AppSetting::getSetting('ai_api_key_deepseek', ''),\n 'ai_api_key_openai' => AppSetting::getSetting('ai_api_key_openai', ''),\n 'ai_api_key_claude' => AppSetting::getSetting('ai_api_key_claude', ''),\n 'ai_api_key_gemini' => AppSetting::getSetting('ai_api_key_gemini', ''),\n ]);\n }\n\n public function updateAiSettings(Request $request)\n {\n $request->validate([\n 'ai_market_provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'ai_api_key_deepseek' => 'nullable|string',\n 'ai_api_key_openai' => 'nullable|string',\n 'ai_api_key_claude' => 'nullable|string',\n 'ai_api_key_gemini' => 'nullable|string',\n ]);\n\n AppSetting::setSetting('ai_market_provider', $request->ai_market_provider);\n AppSetting::setSetting('ai_api_key_deepseek', $request->input('ai_api_key_deepseek') ?? '');\n AppSetting::setSetting('ai_api_key_openai', $request->input('ai_api_key_openai') ?? '');\n AppSetting::setSetting('ai_api_key_claude', $request->input('ai_api_key_claude') ?? '');\n AppSetting::setSetting('ai_api_key_gemini', $request->input('ai_api_key_gemini') ?? '');\n\n return response()->json(['message' => 'Configurações salvas com sucesso!']);\n }\n\n public function testAiConnection(Request $request)\n {\n $request->validate([\n 'provider' => 'required|string|in:deepseek,openai,claude,gemini',\n 'api_key' => 'required|string',\n ]);\n\n $provider = $request->provider;\n $apiKey = $request->api_key;\n\n try {\n $prompt = 'Responda apenas com a palavra OK.';\n $timeout = 10;\n\n if ($provider === 'deepseek') {\n $response = \\Illuminate\\Support\\Facades\\Http::withHeaders([\n 'Authorization' => 'Bearer ' . $apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.deepseek.com/v1/chat/completions', [\n 'model' => 'deepseek-chat',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (!$response->successful()) {\n throw new \\Exception('Erro na API DeepSeek: ' . $response->body());\n }\n } elseif ($provider === 'openai') {\n $response = \\Illuminate\\Support\\Facades\\Http::withHeaders([\n 'Authorization' => 'Bearer ' . $apiKey,\n 'Content-Type' => 'application/json',\n ])->timeout($timeout)->post('https://api.openai.com/v1/chat/completions', [\n 'model' => 'gpt-4o-mini',\n 'messages' => [\n ['role' => 'user', 'content' => $prompt],\n ],\n 'max_tokens' => 5,\n ]);\n\n if (!$response->successful()) {\n throw new \\Exception('Erro na API OpenAI: ' . $response->body());\n }\n } elseif ($provider === 'claude') {\n $response = \\Illuminate\\Support\\Facades\\Http::withHeaders([\n 'x-api-key' => $apiKey,\n 'Content-Type' => 'application/json',\n 'anthropic-version' => '2023-06-01',\n ])->timeout($timeout)->post('https://api.anthropic.com/v1/messages', [\n 'model' => 'claude-3-haiku-20240307',\n 'max_tokens' => 5,\n 'messages' => [['role' => 'user', 'content' => $prompt]],\n ]);\n\n if (!$response->successful()) {\n throw new \\Exception('Erro na API Claude: ' . $response->body());\n }\n } elseif ($provider === 'gemini') {\n $response = \\Illuminate\\Support\\Facades\\Http::timeout($timeout)->post(\n 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=' . $apiKey,\n ['contents' => [['parts' => [['text' => $prompt]]]]]\n );\n\n if (!$response->successful()) {\n throw new \\Exception('Erro na API Gemini: ' . $response->body());\n }\n } else {\n throw new \\Exception('Provedor não suportado.');\n }\n\n return response()->json(['message' => 'Conexão testada com sucesso! O provedor respondeu corretamente.']);\n } catch (\\Throwable $e) {\n return response()->json(['error' => 'Falha na conexão: ' . $e->getMessage()], 400);\n }\n }\n}\n"}, "7171a3c67b73924a2e004efd94ee6ad381f4e9f6": {"t": 1785760291.355466, "n": 3769, "h": "59f003a1a426f3fd", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|file|mimes:jpeg,png,jpg,svg,webp,gif|max:4096',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n $file = $request->file('app_logo');\n $oldLogo = AppSetting::getSetting('app_logo');\n\n $destDir = storage_path('app/public/app_logos');\n if (!is_dir($destDir)) {\n @mkdir($destDir, 0775, true);\n }\n\n $ext = strtolower($file->getClientOriginalExtension() ?: $file->extension() ?: 'png');\n $filename = Str::random(40).'.'.$ext;\n $absolute = $destDir.DIRECTORY_SEPARATOR.$filename;\n\n try {\n $file->move($destDir, $filename);\n } catch (\\Throwable $e) {\n Log::error('AppSettings logo move failed', ['error' => $e->getMessage()]);\n return back()->withErrors(['app_logo' => 'Falha ao salvar a logomarca: '.$e->getMessage()])->withInput();\n }\n\n if (!is_file($absolute) || filesize($absolute) === 0) {\n Log::error('AppSettings logo not persisted', ['path' => $absolute]);\n return back()->withErrors(['app_logo' => 'A logomarca não foi gravada no servidor. Verifique permissões de storage/app/public/app_logos.'])->withInput();\n }\n\n if ($oldLogo && $oldLogo !== 'app_logos/'.$filename) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n AppSetting::setSetting('app_logo', 'app_logos/'.$filename);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n}\n"}, "ddb46ae97d985ef2ed3992097b60d1cc11cd4574": {"t": 1785760292.6869047, "n": 2671, "h": "5a26d3b164fb4d59", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|image|mimes:jpeg,png,jpg,svg|max:2048',\n 'company_cnpj' => 'nullable|string|max:32',\n 'company_address' => 'nullable|string|max:255',\n 'company_email' => 'nullable|email|max:255',\n 'company_whatsapp' => 'nullable|string|max:32',\n 'company_site' => 'nullable|string|max:255',\n 'company_instagram' => 'nullable|string|max:255',\n 'company_facebook' => 'nullable|string|max:255',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('company_cnpj', (string) $request->input('company_cnpj', ''));\n AppSetting::setSetting('company_address', (string) $request->input('company_address', ''));\n AppSetting::setSetting('company_email', (string) $request->input('company_email', ''));\n AppSetting::setSetting('company_whatsapp', (string) $request->input('company_whatsapp', ''));\n AppSetting::setSetting('company_site', (string) $request->input('company_site', ''));\n AppSetting::setSetting('company_instagram', (string) $request->input('company_instagram', ''));\n AppSetting::setSetting('company_facebook', (string) $request->input('company_facebook', ''));\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n // Deletar logo antiga se existir\n $oldLogo = AppSetting::getSetting('app_logo');\n if ($oldLogo) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n $path = $request->file('app_logo')->store('app_logos', 'public');\n AppSetting::setSetting('app_logo', $path);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n}\n"}, "034c4a08f45985734723d590ab04bd00b87eace2": {"t": 1785760294.263483, "n": 1566, "h": "904892fc5a9251f8", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|image|mimes:jpeg,png,jpg,svg|max:2048',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_critical_auto_task_minutes' => 'nullable|integer|min:0|max:1440',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n AppSetting::setSetting('sla_critical_auto_task_minutes', (string) ($request->input('sla_critical_auto_task_minutes', 20)));\n\n if ($request->hasFile('app_logo')) {\n // Deletar logo antiga se existir\n $oldLogo = AppSetting::getSetting('app_logo');\n if ($oldLogo) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n $path = $request->file('app_logo')->store('app_logos', 'public');\n AppSetting::setSetting('app_logo', $path);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n}\n"}, "425e9fbc6b6524129eb59f151c26206cdcf442ef": {"t": 1785760295.8376424, "n": 1351, "h": "1359b242ea404ce5", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|image|mimes:jpeg,png,jpg,svg|max:2048',\n 'sla_first_response_minutes' => 'nullable|integer|min:1|max:720',\n 'sla_queue_wait_minutes' => 'nullable|integer|min:1|max:720',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n AppSetting::setSetting('sla_first_response_minutes', (string) ($request->input('sla_first_response_minutes', 5)));\n AppSetting::setSetting('sla_queue_wait_minutes', (string) ($request->input('sla_queue_wait_minutes', 10)));\n\n if ($request->hasFile('app_logo')) {\n // Deletar logo antiga se existir\n $oldLogo = AppSetting::getSetting('app_logo');\n if ($oldLogo) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n $path = $request->file('app_logo')->store('app_logos', 'public');\n AppSetting::setSetting('app_logo', $path);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n}\n"}, "e81c70864b638c3995d654989e9892505e602e24": {"t": 1785760297.3827035, "n": 960, "h": "1394d53c8c8ac36b", "c": "validate([\n 'app_name' => 'required|string|max:255',\n 'app_logo' => 'nullable|image|mimes:jpeg,png,jpg,svg|max:2048',\n ]);\n\n AppSetting::setSetting('app_name', $request->app_name);\n\n if ($request->hasFile('app_logo')) {\n // Deletar logo antiga se existir\n $oldLogo = AppSetting::getSetting('app_logo');\n if ($oldLogo) {\n Storage::disk('public')->delete($oldLogo);\n }\n\n $path = $request->file('app_logo')->store('app_logos', 'public');\n AppSetting::setSetting('app_logo', $path);\n }\n\n return back()->with('success', 'Configurações atualizadas com sucesso!');\n }\n}\n"}}}}