validate([ 'q' => ['required', 'string', 'max:100'], ]); $searchQuery = $request->string('q'); $user = $request->user(); $lguSuffix = ''; if ($user && $user->tenant_id) { $tenant = $user->tenant ?: Tenant::find($user->tenant_id); if ($tenant && $tenant->cityMunicipality) { $lguSuffix = ', ' . $tenant->cityMunicipality->name; } } $fullQuery = $searchQuery . $lguSuffix . ', Philippines'; // Cache lookup results to protect Nominatim API rate limits $cacheKey = 'geo_boundary_' . md5(strtolower($fullQuery)); $results = Cache::remember($cacheKey, now()->addDays(7), function () use ($fullQuery) { try { $response = Http::withHeaders([ 'User-Agent' => 'Verde Waste Management App (admin@verde.local)', ])->get('https://nominatim.openstreetmap.org/search', [ 'q' => $fullQuery, 'format' => 'json', 'polygon_geojson' => 1, 'limit' => 5, ]); if ($response->successful()) { $data = $response->json() ?? []; return collect($data) ->filter(fn ($item) => isset($item['geojson'])) ->map(fn ($item) => [ 'display_name' => $item['display_name'] ?? 'Unknown Location', 'geojson' => $item['geojson'], ]) ->values() ->all(); } } catch (\Exception $e) { Log::error('Nominatim boundary fetch failed: ' . $e->getMessage()); } return []; }); return $this->ok($results); } }