<?php
/**
 * Class responsible for communitacting with Boostsite API.
 */

namespace BoostsiteAIContentGenerator;

use BoostsiteAIContentGenerator\Api\SettingController;

if ( ! class_exists( 'Boostsite' ) ) {

	/**
	 * Boostsite class
	 */
	class Boostsite {
		/**
		 * API endpoint.
		 *
		 * @var string
		 */
		public $endpoint;

		/**
		 * Array of HTTP Headers.
		 *
		 * @var array
		 */
		public $header;

		/**
		 * Request data type.
		 *
		 * @var string
		 */
		public $data_type;

		/**
		 * Type of API call.
		 *
		 * @var string
		 */
		public $call_type;

		/**
		 * Call payload.
		 *
		 * @var string
		 */
		public $payload;

		/**
		 * API host.
		 *
		 * @var string
		 */
		public $api_host;

		/**
		 * Settings.
		 *
		 * @var SettingController
		 */
		private $settings;

		/**
		 * API key for Boostsite API.
		 *
		 * @var string
		 */
		private $api_key;

		/**
		 * Define the properties inside a instance
		 */
		public function __construct() {
			$this->api_host  = 'https://api.boostsite.com';
			$this->endpoint  = '';
			$this->header    = array();
			$this->data_type = 'json';
			$this->call_type = '';
			$this->payload   = array();
			$this->settings  = new SettingController();
			$this->api_key   = $this->settings->get_single_setting( 'api_key' );
		}

		/**
		 * Define the variables for db table creation
		 *
		 * @return Array
		 */
		public function call() {
			$args = array(
				'headers' => array_merge(
					array(
						'Content-Type'  => 'application/json',
						'Authorization' => 'Bearer ' . $this->api_key,
					),
					$this->header // Include any additional headers set in the object.
				),
				'method'  => $this->call_type,
				'timeout' => 30,
			);

			// Only include body for non-GET requests
			if ( 'GET' !== $this->call_type ) {
				$args['body'] = json_encode( $this->payload );
			}

			// Log the request details.
			$this->log_debug( "API Request: {$this->call_type} {$this->endpoint}" );
			$this->log_debug( 'Request Headers: ' . json_encode( $args['headers'] ) );
			$this->log_debug( 'Request Body: ' . ( isset( $args['body'] ) ? $args['body'] : 'No body (GET request)' ) );

			$result = wp_remote_request( $this->endpoint, $args );

			// Handle request error.
			if ( is_wp_error( $result ) ) {
				$error_message = $result->get_error_message();
				$this->log_debug( 'API Error: ' . $error_message );
				return array(
					'error'   => true,
					'message' => $error_message,
				);
			}

			$response_code = wp_remote_retrieve_response_code( $result );
			$response_body = wp_remote_retrieve_body( $result );

			// Log response details.
			$this->log_debug( 'Response Code: ' . $response_code );
			$this->log_debug( 'Response Body: ' . $response_body );

			$data = json_decode( $response_body, true );

			// Handle JSON parsing errors.
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				return array(
					'error'   => true,
					'message' => 'Error parsing response: ' . json_last_error_msg(),
				);
			}

			// Check for non-successful HTTP status codes.
			if ( ! in_array( $response_code, array( 200, 201 ) ) ) {
				// If we have structured error data, return it.
				if ( isset( $data['statusCode'] ) && isset( $data['message'] ) ) {
					return $data; // Return the structured error response.
				}

				// Fallback to generic error if no structured data.
				return array(
					'error'   => true,
					'message' => 'Unexpected response code: ' . $response_code,
				);
			}

			// Check for API-specific error messages.
			if ( isset( $data['error'] ) ) {
				return array(
					'error'   => true,
					'message' => $data['error'],
				);
			}

			return $data;
		}

		/**
		 * Get the current user from the API
		 *
		 * @return Object
		 */
		public function get_user() {
			$this->endpoint = $this->api_host . '/external-plugin-new/get_user';

			$this->call_type = 'POST';
			$this->payload   = array(
				'user_id' => $this->settings->get_single_setting( 'user_id' ),
			);

			$data_response = $this->call();

			// Handle errors from the call method.
			if ( isset( $data_response['error'] ) && true === $data_response['error'] ) {
				$this->log_debug( 'Error: ' . $data_response['error'] . ' when getting the user from API.' );
				return null;
			}

			// Handle incomplete data.
			if ( ! isset( $data_response['account_type'] ) || isset( $data_response['error'] ) ) {
				$this->log_debug( 'Error: ' . $data_response['error'] . ' when getting the user from API.' );
				return null;
			}

			return $data_response;
		}

		/**
		 * Save current user data
		 *
		 * @param  string $user_id User id.
		 * @param  array  $new_settings Array of new settings.
		 * @return void
		 * @throws \Exception Error if fails to save settings.
		 */
		public function save_user( $user_id, $new_settings ) {
			$user_id = esc_attr( $user_id );

			// Get settings and replace user id.
			$settings            = $this->settings->get_settings_raw();
			$settings['user_id'] = $user_id;

			// Update the settings.
			// Overrite the settings with new ones.
			$settings = array_merge(
				$settings,
				array(
					'email'                       => isset( $new_settings['email'] ) && is_email( $new_settings['email'] )
														? sanitize_email( $new_settings['email'] )
														: $settings['email'],
					'account_type'                => isset( $new_settings['account_type'] )
														? sanitize_text_field( $new_settings['account_type'] )
														: $settings['account_type'],
					'api_key'                     => isset( $new_settings['api_key'] )
														? sanitize_text_field( $new_settings['api_key'] )
														: $settings['api_key'],
					'available_tokens'            => isset( $new_settings['available_tokens'] )
														? sanitize_text_field( $new_settings['available_tokens'] )
														: $settings['available_tokens'],
					'used_tokens'                 => isset( $new_settings['used_tokens'] )
														? sanitize_text_field( $new_settings['used_tokens'] )
														: $settings['used_tokens'],
					'trial_end_time'              => isset( $new_settings['trial_end_time'] )
														? sanitize_text_field( $new_settings['trial_end_time'] )
														: $settings['trial_end_time'],
					'available_tokens_additional' => isset( $new_settings['available_tokens_additional'] )
														? sanitize_text_field( $new_settings['available_tokens_additional'] )
														: null,
					'has_plugin'                  => isset( $new_settings['has_plugin'] )
														? sanitize_text_field( $new_settings['has_plugin'] )
														: $settings['has_plugin'],
					'rest_url'                    => isset( $new_settings['rest_url'] )
														? sanitize_text_field( $new_settings['rest_url'] )
														: $settings['rest_url'],
					'account_expired'             => isset( $new_settings['account_expired'] )
														? sanitize_text_field( $new_settings['account_expired'] )
														: $settings['account_expired'],
					'enable_category_creation'    => isset( $new_settings['enable_category_creation'] )
														? sanitize_text_field( $new_settings['enable_category_creation'] )
														: $settings['enable_category_creation'],
					'category_creation_limit'     => isset( $new_settings['category_creation_limit'] )
														? sanitize_text_field( $new_settings['category_creation_limit'] )
														: $settings['category_creation_limit'],
				)
			);

			$saved_settings = $this->settings->set_settings( $settings );

			// Handle save error.
			if ( is_null( $saved_settings ) ) {
				throw new \Exception( 'Failed to save user settings.' );
			}
		}

		/**
		 * Checks if user is logged in.
		 *
		 * @return boolean
		 */
		public function update_user() {
			// Check if options are set.
			$settings = $this->settings->get_settings_raw();
			if ( empty( $settings['user_id'] ) || empty( $settings['email'] ) ) {
				return false;
			}

			// Check if user exists in the API.
			$user = $this->get_user();
			if ( null === $user ) {
				return false;
			}

			// Store the settings to update.
			$settings = array();

			// Get the data from API.
			$settings['available_tokens'] = 'FREE' === $user['account_type'] ? 1 : 35;
			$settings['used_tokens']      = $user['used_tokens_this_week'];
			$settings['trial_end_time']   = '';

			// Set trial end date.
			if ( isset( $user['trial_remainging_days'] ) && ! empty( $user['trial_remainging_days'] ) ) {
				// Add remaining days to today.
				$days_untill_end = intval( $user['trial_remainging_days'] );
				$today           = new \DateTime();
				$today->modify( "+$days_untill_end days" );

				// Save the date in correct format.
				$settings['trial_end_time'] = $today->format( 'Y-m-d' );
			}

			// Additional tokens.
			$settings['available_tokens_additional'] = $user['additional_tokens'] ?? null;

			// Rest of the settings.
			$settings['account_type']             = $user['account_type'];
			$settings['has_plugin']               = $user['has_plugin'];
			$settings['rest_url']                 = $user['rest_url'];
			$settings['account_expired']          = $user['account_expired'] ?? '';
			$settings['enable_category_creation'] = $user['enable_category_creation'] ?? '1';
			$settings['category_creation_limit']  = $user['category_creation_limit'] ?? '15';

			// Update user data.
			$this->save_user( $user['userID'], $settings );

			return true;
		}

		/**
		 * Checks if user is has schedule.
		 *
		 * @return boolean
		 */
		public function check_schedule() {
			// First get schedules from the API.
			$schedules_response = $this->get_schedules();

			if ( ! isset( $schedules_response['schedule'] ) ) {
				return false;
			}

			// Save new schedules.
			$settings              = $this->settings->get_settings_raw();
			$settings['schedules'] = $schedules_response['schedule'];

			$data = $this->settings->set_settings( $settings );

			return ! empty( $data['schedules'] );
		}

		/**
		 * Update settings in the API with schedules
		 *
		 * @param  mixed $settings All of the plugin settings from SettingController.
		 * @return Object
		 */
		public function update_settings( $settings ) {
			// Set endpoint and call type.
			$this->endpoint  = $this->api_host . '/external-plugin-new/update';
			$this->call_type = 'PUT';

			// Get posts titles.
			$posts       = get_posts(
				array(
					'post_status' => array( 'future', 'publish', 'draft' ),
					'numberposts' => 50,
				)
			);
			$post_titles = wp_list_pluck( $posts, 'post_title' );

			// Get categories names.
			$categories     = get_categories(
				array(
					'hide_empty' => false,
				)
			);
			$category_names = wp_list_pluck( $categories, 'name' );

			// Prepare the call body.
			$schedules = $settings['schedules'];

			// Prepare the payload.
			$this->payload = array(
				'user_id'    => $settings['user_id'],
				'email'      => $settings['email'],
				'titles'     => $post_titles,
				'categories' => $category_names,
				'version'    => 2,
				'schedule'   => array(),
				'config'     => array(
					'rest_url' => get_rest_url(),
				),
			);

			// Add the schedules.
			foreach ( $schedules as $schedule ) {
				// Add the schedule.
				$this->payload['schedule'][] = $this->generate_schedule_body( $schedule );
			}

			$response = $this->call();

			$error = $this->handle_api_errors( $response );
			if ( $error ) {
				return $error;
			}

			return $response;
		}

			/**
			 * Update plugin settings in the API.
			 *
			 * @param  mixed $settings Settings: rest_url.
			 * @return Object
			 */
		public function update_plugin( $settings ) {
			// Prepare the payload.
			$payload = array(
				'user_id' => esc_html( $this->settings->get_single_setting( 'user_id' ) ),
			);

			if ( ! empty( $settings['rest_url'] ) ) {
				$payload['rest_url'] = esc_url( $settings['rest_url'] );
			}

			if ( array_key_exists( 'enable_category_creation', $settings ) ) {
				$payload['enable_category_creation'] = boolval( esc_html( $settings['enable_category_creation'] ) );
			}

			if ( ! empty( $settings['category_creation_limit'] ) ) {
				$payload['category_creation_limit'] = (int) esc_html( $settings['category_creation_limit'] );
			}

			$this->endpoint = $this->api_host . '/external-plugin-new/update_plugin';

			$this->call_type = 'PUT';
			$this->payload   = $payload;

			$response = $this->call();

			$error = $this->handle_api_errors( $response );
			if ( $error ) {
				return $error;
			}

			return $response;
		}

			/**
			 * Generate topic for the website based on the website tagline.
			 *
			 * @return Object
			 */
		public function generate_topic() {
			// Check if the tagline is set.
			$tagline = get_bloginfo( 'description' );

			if ( empty( $tagline ) ) {
				return array(
					'info' => 'error_exist',
					'data' => 'Please set the tagline of your website.',
				);
			}

			$payload = array(
				'meta_description' => esc_html( get_bloginfo( 'description' ) ),
			);

			return $this->make_api_call_with_error_handling( '/external-plugin-new/generate_topic', 'POST', $payload, false );
		}

			/**
			 * Regenerate post with given ID.
			 *
			 * @param  number $id ID of the post to regenerate.
			 * @return boolean
			 */
		public function regenerate_post( $id ) {
			$payload = array(
				'post_id' => esc_html( strval( $id ) ),
			);

			$response = $this->make_api_call( '/external-plugin-new/regenerate_article', 'POST', $payload );

			// Return false if any errors exist.
			return ! $this->handle_api_errors( $response );
		}

		/**
		 * Get all the schedules.
		 *
		 * @return Object
		 */
		public function get_schedules() {
			$response = $this->make_api_call_with_error_handling( '/external-plugin-new/get_schedule' );

			// Return early if error.
			if ( isset( $response['info'] ) && 'error_exist' === $response['info'] ) {
				return $response;
			}

			// Process schedules to convert UTC times back to their original timezones.
			$schedules_with_timezone = array();
			foreach ( $response['schedule'] as $schedule ) {
				$schedules_with_timezone[] = $this->process_schedule( $schedule );
			}
			$response['schedule'] = $schedules_with_timezone;

			return $response;
		}

		/**
		 * Remove schedule with given id.
		 *
		 * @param  number $id ID of the schedule to delete.
		 * @return Object
		 */
		public function remove_schedule( $id ) {
			return $this->make_api_call_with_error_handling( '/external-plugin-new/schedule/' . $id, 'DELETE' );
		}

		/**
		 * Edit schedule with given id.
		 *
		 * @param  number $id ID of the schedule to edit.
		 * @param  mixed  $schedule new schedule to replace the old one.
		 * @return Object
		 */
		public function edit_schedule( $id, $schedule ) {
			$payload = array(
				'schedule' => $this->generate_schedule_body( $schedule ),
			);

			return $this->make_api_call_with_error_handling( '/external-plugin-new/schedule/' . $id, 'PUT', $payload );
		}

		/**
		 * Add new schedule.
		 *
		 * @param  mixed $schedule new schedule to replace the old one.
		 * @return Object
		 */
		public function add_schedule( $schedule ) {
			$payload = array(
				'schedule' => $this->generate_schedule_body( $schedule ),
			);

			return $this->make_api_call_with_error_handling( '/external-plugin-new/schedule', 'POST', $payload );
		}

		/**
		 * Get the subscription details.
		 *
		 * @return Object
		 */
		public function subscription_details() {
			$response = $this->make_api_call( '/operator/customer-plugin-plan' );

			// Handle errors from the call method.
			if ( isset( $response['error'] ) && true === $response['error'] ) {
				$this->log_debug( 'Error: ' . $response['error'] . ' when getting the user from API.' );
			}

			return $response;
		}

		/**
		 * Cancel the subscription.
		 *
		 * @return Object
		 */
		public function cancel_subscription() {
			$response = $this->make_api_call( '/operator/remove-customer-plan', 'PATCH' );

			// Handle errors from the call method.
			if ( isset( $response['error'] ) && true === $response['error'] ) {
				$this->log_debug( 'Error: ' . $response['error'] . ' when getting the user from API.' );
			}

			return $response;
		}

		/**
		 * Generate Stripe URL.
		 *
		 * @return Object
		 */
		public function generate_stripe_url() {
			$payload = array(
				'url' => esc_url( home_url() . '/wp-admin/admin.php?page=boostsite-menu' ),
			);

			$response = $this->make_api_call( '/external-plugin-new/generate_stripe_url', 'POST', $payload );

			// Handle only call method errors, not statusCode errors.
			if ( isset( $response['error'] ) && true === $response['error'] ) {
				return array(
					'info' => 'error_exist',
					'data' => $response['message'],
				);
			}

			return $response;
		}

		/**
		 * Plan the first batch of articles.
		 *
		 * @return Object
		 */
		public function plan_first_batch_articles() {
			return $this->make_api_call_with_error_handling( '/external-plugin-new/plan_first_batch_articles' );
		}

		/**
		 * Check API connection.
		 *
		 * @return Object
		 */
		public function check_connection() {
			return $this->make_api_call_with_error_handling( '/external-plugin-new/check_connection' );
		}

		/**
		 * Reset API token.
		 *
		 * @return Object
		 */
		public function request_api_key_reset() {
			$payload = array(
				'email' => esc_html( $this->settings->get_single_setting( 'email' ) ),
			);

			return $this->make_api_call_with_error_handling( '/external-plugin-new/request_api_key_reset', 'POST', $payload );
		}

		/**
		 * Confirm API key reset with token.
		 *
		 * @param string $token Reset token.
		 * @return Object
		 */
		public function api_key_reset( $token ) {
			$token = esc_html( $token );

			return $this->make_api_call_with_error_handling( "/external-plugin-new/reset_api_key/{$token}", 'GET', array(), false );
		}

		/**
		 * Helper function to format the schedule.
		 *
		 * @param  mixed $schedule Schedule object.
		 * @return array
		 */
		public function generate_schedule_body( $schedule ) {
			$schedule = (object) $schedule;

			// Prepare basic schedule.
			$new_schedule = array(
				'topic'                 => $schedule->topic,
				'days'                  => array_map( 'intval', $schedule->days ),
				'time'                  => $this->convert_time_to_utc( $schedule->time, $schedule->time_zone ),
				'time_zone'             => $schedule->time_zone,
				'lang'                  => $schedule->lang,
				'author'                => $schedule->author,
				'advSchedule'           => null,
				'articles_keywords'     => array(),
				'activity_date_enabled' => $schedule->activity_date_enabled,
				'activity_date'         => $schedule->activity_date,
			);

			// Populate keywords.
			if ( $schedule->articles_keywords ) {
				foreach ( $schedule->articles_keywords as $keywords ) {
					if ( is_array( $keywords ) && isset( $keywords['keywords'] ) && is_array( $keywords['keywords'] ) ) {
						// Already in the correct format.
						$new_schedule['articles_keywords'][] = $keywords;
					} elseif ( is_array( $keywords ) ) {
						// Normal array.
						$new_schedule['articles_keywords'][] = array(
							'keywords' => $keywords,
						);
					}
				}
			}

			// Advanced schedule.
			if ( $schedule->advSchedule ) {
				// Convert to an associative array if it's an object.
				$adv_schedule_array = (array) $schedule->advSchedule;

				// Ensure the correct format for advSchedule.
				$formatted_adv_schedule = array();

				foreach ( $adv_schedule_array as $day => $times ) {
					if ( is_array( $times ) ) {
						// Convert each time to UTC.
						$utc_times = array_map(
							function ( $time ) use ( $schedule ) {
								return $this->convert_time_to_utc( $time, $schedule->time_zone );
							},
							$times
						);

						$formatted_adv_schedule[ strval( $day ) ] = array_map( 'sanitize_text_field', $utc_times );
					}
				}

				// Add the properly formatted advanced schedule.
				$new_schedule['advSchedule'] = $formatted_adv_schedule;
			}

			// return the schedule.
			return $new_schedule;
		}

		/**
		 * Process a schedule from the API, converting UTC times to the specified timezone.
		 *
		 * @param array $schedule Schedule from API.
		 * @return array Processed schedule with converted times.
		 */
		private function process_schedule( $schedule ) {
			// Convert to object for consistency with generate_schedule_body.
			$schedule = (object) $schedule;

			// Convert the main time from UTC to the specified timezone.
			if ( isset( $schedule->time ) && isset( $schedule->time_zone ) ) {
				$schedule->time = $this->convert_time_from_utc( $schedule->time, $schedule->time_zone );
			}

			// Process advanced schedule if it exists.
			if ( isset( $schedule->advSchedule ) && ! empty( $schedule->advSchedule ) ) {
				$adv_schedule           = (array) $schedule->advSchedule;
				$processed_adv_schedule = array();

				foreach ( $adv_schedule as $day => $times ) {
					if ( is_array( $times ) ) {
						// Convert each time from UTC to the specified timezone.
						$local_times = array_map(
							function ( $time ) use ( $schedule ) {
								return $this->convert_time_from_utc( $time, $schedule->time_zone );
							},
							$times
						);

						$processed_adv_schedule[ strval( $day ) ] = $local_times;
					}
				}

				$schedule->advSchedule = $processed_adv_schedule;
			}

			// Convert the keywords to the correct format.
			if ( isset( $schedule->articles_keywords ) && is_array( $schedule->articles_keywords ) ) {
				foreach ( $schedule->articles_keywords as &$keywords ) {
					// Remove 'keywords' key if it exists.
					if ( is_array( $keywords ) && isset( $keywords['keywords'] ) ) {
						$keywords = $keywords['keywords'];
					}
				}
			}

			// Convert back to array for storage.
			return (array) $schedule;
		}

		/**
		 * Convert a time from UTC to a specific timezone.
		 *
		 * @param string $time The UTC time to convert (format: H:i).
		 * @param string $timezone The timezone identifier to convert to.
		 * @return string The time in specified timezone (format: H:i).
		 */
		private function convert_time_from_utc( $time, $timezone ) {
			// Create a DateTime object with today's date and the specified time in UTC.
			$datetime = new \DateTime( "today {$time}", new \DateTimeZone( 'UTC' ) );

			// Convert to the specified timezone.
			$datetime->setTimezone( new \DateTimeZone( $timezone ) );

			// Return the time in H:i format.
			return $datetime->format( 'H:i' );
		}

		/**
		 * Convert a time from a specific timezone to UTC.
		 *
		 * @param string $time The time to convert (format: H:i).
		 * @param string $timezone The timezone identifier.
		 * @return string The time in UTC (format: H:i).
		 */
		private function convert_time_to_utc( $time, $timezone ) {
			// Create a DateTime object with today's date and the specified time in the given timezone.
			$datetime = new \DateTime( "today {$time}", new \DateTimeZone( $timezone ) );

			// Convert to UTC.
			$datetime->setTimezone( new \DateTimeZone( 'UTC' ) );

			// Return the time in H:i format.
			return $datetime->format( 'H:i' );
		}

		/**
		 * Log debug messages.
		 *
		 * @param string $message Log message.
		 */
		private function log_debug( $message ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG && defined( 'BOOSTSITE_DEBUG' ) && BOOSTSITE_DEBUG ) {
				error_log( '[API Debug] ' . $message );
			}
		}

		/**
		 * Handle standardized error responses from API calls.
		 *
		 * @param array $response API response data.
		 * @return array|null Returns error array if error exists, null if no error.
		 */
		private function handle_api_errors( $response ) {
			// Handle errors from the call method.
			if ( isset( $response['error'] ) && true === $response['error'] ) {
				return array(
					'info'       => 'error_exist',
					'data'       => $response['message'],
					'statusCode' => isset( $response['statusCode'] ) ? $response['statusCode'] : 500,
				);
			}

			// Handle structured error responses (new format)
			if ( isset( $response['statusCode'] ) && $response['statusCode'] >= 400 ) {
				return array(
					'info'       => 'error_exist',
					'data'       => isset( $response['message'] ) ? $response['message'] : 'Unknown error',
					'statusCode' => $response['statusCode'],
				);
			}

			return null;
		}

		/**
		 * Make a standardized API call with common payload.
		 *
		 * @param string $endpoint_path The API endpoint path (without host).
		 * @param string $method HTTP method (GET, POST, PUT, DELETE).
		 * @param array  $additional_payload Additional payload data to merge with base payload.
		 * @param bool   $include_user_id Whether to include user_id in payload.
		 * @return array API response.
		 */
		private function make_api_call( $endpoint_path, $method = 'POST', $additional_payload = array(), $include_user_id = true ) {
			$this->endpoint  = $this->api_host . $endpoint_path;
			$this->call_type = $method;

			$base_payload = array();
			if ( $include_user_id ) {
				$base_payload['user_id'] = esc_html( $this->settings->get_single_setting( 'user_id' ) );
			}

			$this->payload = array_merge( $base_payload, $additional_payload );

			return $this->call();
		}

		/**
		 * Make API call and handle standard error responses.
		 *
		 * @param string $endpoint_path The API endpoint path.
		 * @param string $method HTTP method.
		 * @param array  $additional_payload Additional payload data.
		 * @param bool   $include_user_id Whether to include user_id in payload.
		 * @return array API response or standardized error.
		 */
		private function make_api_call_with_error_handling( $endpoint_path, $method = 'POST', $additional_payload = array(), $include_user_id = true ) {
			$response = $this->make_api_call( $endpoint_path, $method, $additional_payload, $include_user_id );

			$error = $this->handle_api_errors( $response );
			if ( $error ) {
				return $error;
			}

			return $response;
		}
	}
}
