*/ public function __invoke( string $range, ?string $metric = null, ?string $from = null, ?string $to = null, ?int $limit = null ): array { // NeuronAI passes an explicit null for a property the model omitted, so the // defaults have to live here rather than in the signature. $metric = $metric ?? 'points_earned'; $limit = $limit ?? 5; $requested_limit = $limit; $check = $this->guard( 'manage_pointics', 'manage_options' ); if ( $check ) { return $check; } $check = $this->pointics_tables_ready(); if ( $check ) { return $check; } try { $request = new \WP_REST_Request( 'GET', '/pointics/v1/analytics/top-customers' ); $request->set_param( 'range', $range ); $request->set_param( 'metric', $metric ); $request->set_param( 'limit', max( 1, min( 50, $limit ) ) ); if ( null !== $from ) { $request->set_param( 'from', $from ); } if ( null !== $to ) { $request->set_param( 'to', $to ); } $controller = pointics_container()->make( \Pointics\Api\Controllers\Analytics_Controller::class ); $data = $this->extract_response( $controller->top_customers( $request ), __( 'Failed to retrieve Pointics top customers.', 'aisentic' ), $this->getName() ); if ( $this->is_error( $data ) ) { return $this->steer_analytics_error( $data ); } $result = [ 'range' => $this->pluck( is_array( $data['range'] ?? null ) ? $data['range'] : [], [ 'preset', 'from', 'to', 'previous_from', 'previous_to', 'timezone' ] ), 'metric' => $data['metric'] ?? $metric, 'items' => $this->shape_rows( is_array( $data['items'] ?? null ) ? $data['items'] : [], function ( array $item ): array { $shaped = $this->pluck( $item, [ 'user_id', 'name', 'email', 'avatar_url', 'points' ] ); if ( array_key_exists( 'tier', $item ) ) { $shaped['tier'] = is_array( $item['tier'] ) ? $this->pluck( $item['tier'], [ 'id', 'name', 'slug' ] ) : null; } return $shaped; } ), ]; if ( $requested_limit > 50 ) { /* translators: %d: maximum number of analytics records. */ $result['note'] = sprintf( __( 'The requested limit was clamped to %d to keep the analytics result bounded.', 'aisentic' ), 50 ); } return $result; } catch ( \Throwable $e ) { Log::error( 'Pointics_Get_Top_Customers_Tool error', [ 'error' => $e->getMessage() ] ); return $this->steer( [ 'error' => __( 'Failed to retrieve Pointics top customers.', 'aisentic' ), 'code' => 'internal', 'status' => 500, ] ); } } }