<?php
/**
 * This file is part of the Wisewand WordPress plugin.
 *
 * @package Wisewand
 * @since 1.0.0
 * @license GPL-2.0-or-later
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
namespace Wisewand\Utils;

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use WP_Error;

// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- error_log() and print_r() are only used within WP_DEBUG conditionals for debugging; direct database calls required for bulk transient cleanup operations

class Wisewand_API_Client {

	private $api_key;
	private $base_url;
	private $logger;
	private $rate_limiter;

	public function __construct( $api_key, $logger = null, $base_url = 'https://api.wisewand.ai' ) {
		$this->api_key  = $api_key;
		$this->base_url = rtrim( $base_url, '/' );
		$this->logger   = $logger;

		// Initialize rate limiter
		if ( ! class_exists( 'Wisewand\\Utils\\Rate_Limiter' ) ) {
			require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Rate_Limiter.php';
		}
		$this->rate_limiter = new Rate_Limiter( $logger );
	}

	/**
	 * List articles with pagination and filtering
	 */
	public function list_articles( $params = array() ) {
		$default_params = array(
			'skip'      => 0,
			'take'      => 20,
			'search'    => '',
			'status'    => '',
			'projectId' => '',
			'published' => '',
		);

		$params = array_merge( $default_params, $params );

		return $this->request( 'GET', '/v1/articles/', $params );
	}

	/**
	 * List category pages with pagination and filtering
	 */
	public function list_categorypages( $params = array() ) {
		$default_params = array(
			'skip'      => 0,
			'take'      => 20,
			'search'    => '',
			'status'    => '',
			'projectId' => '',
			'published' => '',
		);

		$params = array_merge( $default_params, $params );

		return $this->request( 'GET', '/v1/categorypages/', $params );
	}

	/**
	 * List product pages with pagination and filtering
	 */
	public function list_productpages( $params = array() ) {
		$default_params = array(
			'skip'      => 0,
			'take'      => 20,
			'search'    => '',
			'status'    => '',
			'projectId' => '',
			'published' => '',
		);

		$params = array_merge( $default_params, $params );

		return $this->request( 'GET', '/v1/productpages/', $params );
	}

	/**
	 * Generic method to list any content type
	 */
	public function list_content( $content_type = 'articles', $params = array() ) {
		switch ( $content_type ) {
			case 'categorypages':
				return $this->list_categorypages( $params );
			case 'productpages':
				return $this->list_productpages( $params );
			case 'discoverarticles':
				return $this->list_discoverarticles( $params );
			case 'articles':
			default:
				return $this->list_articles( $params );
		}
	}

	/**
	 * List discover articles (Google Discover) with pagination and filtering
	 */
	public function list_discoverarticles( $params = array() ) {
		$default_params = array(
			'skip'      => 0,
			'take'      => 20,
			'search'    => '',
			'status'    => '',
			'projectId' => '',
			'published' => '',
		);

		$params = array_merge( $default_params, $params );

		return $this->request( 'GET', '/v1/discoverarticles/', $params );
	}

	/**
	 * Get specific article by ID
	 */
	public function get_article( $article_id ) {
		return $this->request( 'GET', "/v1/articles/{$article_id}" );
	}

	/**
	 * Get article output (generated content)
	 */
	public function get_article_output( $article_id ) {
		return $this->request( 'GET', "/v1/articles/{$article_id}/output" );
	}

	/**
	 * Get category page output
	 */
	public function get_categorypage_output( $page_id ) {
		return $this->request( 'GET', "/v1/categorypages/{$page_id}/output" );
	}

	/**
	 * Get product page output
	 */
	public function get_productpage_output( $page_id ) {
		return $this->request( 'GET', "/v1/productpages/{$page_id}/output" );
	}

	/**
	 * Get discover article output (generated content)
	 *
	 * Uses two-step workflow:
	 * 1. GET /v1/discoverarticles/{id}/ to get last_output_id
	 * 2. GET /v1/discoverarticles/{id}/output?output={last_output_id} to get content
	 *
	 * @param string $article_id Discoverarticle ID
	 * @return array|WP_Error Output data or error
	 */
	public function get_discoverarticle_output( $article_id ) {
		// Sanitize article_id - assuming it's alphanumeric with hyphens/underscores
		$article_id = sanitize_key( $article_id );

		if ( empty( $article_id ) ) {
			return new \WP_Error(
				'invalid_article_id',
				__( 'Invalid article ID provided', 'wisewand-ai-content-writer-seo-content-generator' ),
				array( 'article_id' => $article_id )
			);
		}

		if ( $this->logger ) {
			$this->logger->debug(
				'Fetching discoverarticle output (two-step workflow)',
				array(
					'article_id' => $article_id,
				)
			);
		}

		// Step 1: Get the discoverarticle metadata to extract last_output_id
		$discoverarticle = $this->get_discoverarticle( $article_id );

		if ( is_wp_error( $discoverarticle ) ) {
			if ( $this->logger ) {
				$this->logger->error(
					'Failed to fetch discoverarticle metadata',
					array(
						'article_id' => $article_id,
						'error'      => $discoverarticle->get_error_message(),
					)
				);
			}
			return $discoverarticle;
		}

		// Extract last_output_id
		$last_output_id = $discoverarticle['last_output_id'] ?? null;

		// Handle missing last_output_id
		if ( empty( $last_output_id ) ) {
			$error_message = __( 'Discoverarticle has no generated output yet (last_output_id is missing)', 'wisewand-ai-content-writer-seo-content-generator' );

			if ( $this->logger ) {
				$this->logger->warning(
					$error_message,
					array(
						'article_id'       => $article_id,
						'status'           => $discoverarticle['status'] ?? 'unknown',
						'available_fields' => array_keys( $discoverarticle ),
					)
				);
			}

			return new \WP_Error(
				'no_output_generated',
				$error_message,
				array(
					'article_id' => sanitize_text_field( $article_id ),
					'status'     => sanitize_text_field( $discoverarticle['status'] ?? 'unknown' ),
					'suggestion' => __( 'The article may need to be generated first using run_discoverarticle_generation()', 'wisewand-ai-content-writer-seo-content-generator' ),
				)
			);
		}

		// Validate last_output_id format (assuming it's alphanumeric with hyphens)
		if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $last_output_id ) ) {
			if ( $this->logger ) {
				$this->logger->error(
					'Invalid last_output_id format',
					array(
						'article_id'     => $article_id,
						'last_output_id' => $last_output_id,
					)
				);
			}

			return new \WP_Error(
				'invalid_output_id',
				__( 'Invalid output ID format received from API', 'wisewand-ai-content-writer-seo-content-generator' ),
				array(
					'article_id'     => sanitize_text_field( $article_id ),
					'last_output_id' => sanitize_text_field( $last_output_id ),
				)
			);
		}

		if ( $this->logger ) {
			$this->logger->debug(
				'Found last_output_id, fetching output',
				array(
					'article_id'     => $article_id,
					'last_output_id' => $last_output_id,
				)
			);
		}

		// Step 2: Fetch the actual output using the last_output_id
		$output = $this->request(
			'GET',
			"/v1/discoverarticles/{$article_id}/output",
			array( 'output' => $last_output_id )
		);

		if ( is_wp_error( $output ) ) {
			if ( $this->logger ) {
				$this->logger->error(
					'Failed to fetch discoverarticle output content',
					array(
						'article_id'     => $article_id,
						'last_output_id' => $last_output_id,
						'error'          => $output->get_error_message(),
					)
				);
			}
			return $output;
		}

		if ( $this->logger ) {
			$this->logger->debug(
				'Successfully fetched discoverarticle output',
				array(
					'article_id'     => $article_id,
					'last_output_id' => $last_output_id,
					'output_keys'    => array_keys( $output ),
				)
			);
		}

		return $output;
	}

	/**
	 * Check if a discoverarticle has generated output available
	 *
	 * @param string $article_id Discoverarticle ID
	 * @return bool|WP_Error True if output exists, false if not, WP_Error on API failure
	 */
	public function discoverarticle_has_output( $article_id ) {
		// Sanitize article_id - assuming it's alphanumeric with hyphens/underscores
		$article_id = sanitize_key( $article_id );

		if ( empty( $article_id ) ) {
			return new \WP_Error(
				'invalid_article_id',
				__( 'Invalid article ID provided', 'wisewand-ai-content-writer-seo-content-generator' ),
				array( 'article_id' => $article_id )
			);
		}

		$discoverarticle = $this->get_discoverarticle( $article_id );

		if ( is_wp_error( $discoverarticle ) ) {
			return $discoverarticle;
		}

		return ! empty( $discoverarticle['last_output_id'] );
	}

	/**
	 * Generic method to get content output by type
	 */
	public function get_content_output( $content_id, $content_type = 'articles' ) {
		switch ( $content_type ) {
			case 'categorypages':
				return $this->get_categorypage_output( $content_id );
			case 'productpages':
				return $this->get_productpage_output( $content_id );
			case 'discoverarticles':
				return $this->get_discoverarticle_output( $content_id );
			case 'articles':
			default:
				return $this->get_article_output( $content_id );
		}
	}

	/**
	 * Run article generation
	 */
	public function run_article_generation( $article_id ) {
		return $this->request( 'POST', "/v1/articles/{$article_id}/run", array(), array() );
	}

	/**
	 * Create new article
	 */
	public function create_article( $article_data ) {
		return $this->request( 'POST', '/v1/articles/', array(), $article_data );
	}

	/**
	 * Update existing article
	 */
	public function update_article( $article_id, $updates ) {
		return $this->request( 'PATCH', "/v1/articles/{$article_id}", array(), $updates );
	}

	/**
	 * Bulk create articles
	 */
	public function bulk_create_articles( $articles_data ) {
		return $this->request( 'POST', '/v1/articles/bulk', array(), $articles_data );
	}

	/**
	 * Calculate article generation cost
	 */
	public function calculate_cost( $article_data ) {
		return $this->request( 'POST', '/v1/articles/cost', array(), $article_data );
	}

	/**
	 * Get the current WiseWand credit balance.
	 *
	 * Uses the cost estimation endpoint which returns the account balance
	 * alongside the estimated cost. Cached for 5 minutes.
	 *
	 * @since 2.9.6
	 *
	 * @return array|WP_Error Array with 'credits' (float) key, or WP_Error on failure.
	 */
	public function get_credit_balance() {
		$cached = get_transient( 'wisewand_credit_balance' );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->calculate_cost( array( 'subject' => 'balance_check' ) );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$balance = array(
			'credits' => (float) ( $result['credits'] ?? 0 ),
		);

		set_transient( 'wisewand_credit_balance', $balance, 5 * MINUTE_IN_SECONDS );
		return $balance;
	}

	/**
	 * List RSS feeds
	 *
	 * @param int   $skip Pagination offset
	 * @param int   $take Items per page (max 50)
	 * @param array $filters Optional filters (search, status, projectId)
	 * @return array|WP_Error Feed list with items and count
	 */
	public function list_feeds( $skip = 0, $take = 20, $filters = array() ) {
		$params = array(
			'skip' => $skip,
			'take' => min( 50, $take ), // API max is 50
		);

		if ( ! empty( $filters['search'] ) ) {
			$params['search'] = $filters['search'];
		}
		if ( ! empty( $filters['status'] ) ) {
			$params['status'] = $filters['status'];
		}
		if ( ! empty( $filters['projectId'] ) ) {
			$params['projectId'] = $filters['projectId'];
		}

		return $this->request( 'GET', '/v1/feeds/', $params );
	}

	/**
	 * Get specific RSS feed by ID
	 *
	 * @param string $feed_id Wisewand feed ID
	 * @return array|WP_Error Feed details
	 */
	public function get_feed( $feed_id ) {
		return $this->request( 'GET', "/v1/feeds/{$feed_id}" );
	}

	/**
	 * Get articles created by a specific RSS feed
	 *
	 * @param string $feed_id Wisewand feed ID (used as maker parameter)
	 * @param int    $skip Pagination offset
	 * @param int    $take Items per page (max 50)
	 * @param array  $filters Optional filters (status, published)
	 * @return array|WP_Error Articles list with items and count
	 */
	public function get_feed_articles( $feed_id, $skip = 0, $take = 50, $filters = array() ) {
		$params = array(
			'maker' => $feed_id, // Query parameter is 'maker' (response field is 'maker_id')
			'skip'  => $skip,
			'take'  => min( 50, $take ),
		);

		if ( ! empty( $filters['status'] ) ) {
			$params['status'] = $filters['status'];
		}
		if ( isset( $filters['published'] ) ) {
			$params['published'] = $filters['published'] ? 'true' : 'false';
		}

		return $this->request( 'GET', '/v1/articles/', $params );
	}

	/**
	 * Get discoverarticles from a specific feed
	 *
	 * @param string $feed_id Wisewand feed ID
	 * @param int    $skip Number of articles to skip
	 * @param int    $take Number of articles to retrieve (max 50)
	 * @param array  $filters Optional filters (status, published)
	 * @return array|WP_Error API response or error
	 */
	public function get_feed_discoverarticles( $feed_id, $skip = 0, $take = 50, $filters = array() ) {
		$params = array(
			'maker' => $feed_id,
			'skip'  => $skip,
			'take'  => min( 50, $take ),
		);

		if ( ! empty( $filters['status'] ) ) {
			$params['status'] = $filters['status'];
		}
		if ( isset( $filters['published'] ) ) {
			$params['published'] = $filters['published'] ? 'true' : 'false';
		}

		return $this->request( 'GET', '/v1/discoverarticles/', $params );
	}

	/**
	 * Create category page
	 */
	public function create_categorypage( $data ) {
		return $this->request( 'POST', '/v1/categorypages/', array(), $data );
	}

	/**
	 * Get category page
	 */
	public function get_categorypage( $id ) {
		return $this->request( 'GET', "/v1/categorypages/{$id}" );
	}

	/**
	 * Run category page generation
	 */
	public function run_categorypage_generation( $id ) {
		return $this->request( 'POST', "/v1/categorypages/{$id}/run", array(), array() );
	}

	/**
	 * Create product page
	 */
	public function create_productpage( $data ) {
		return $this->request( 'POST', '/v1/productpages/', array(), $data );
	}

	/**
	 * Get product page
	 */
	public function get_productpage( $id ) {
		return $this->request( 'GET', "/v1/productpages/{$id}" );
	}

	/**
	 * Run product page generation
	 */
	public function run_productpage_generation( $id ) {
		return $this->request( 'POST', "/v1/productpages/{$id}/run", array(), array() );
	}

	/**
	 * Create discover article
	 */
	public function create_discoverarticle( $data ) {
		return $this->request( 'POST', '/v1/discoverarticles/', array(), $data );
	}

	/**
	 * Get discover article
	 */
	public function get_discoverarticle( $id ) {
		// Sanitize article_id - assuming it's alphanumeric with hyphens/underscores
		$id = sanitize_key( $id );

		if ( empty( $id ) ) {
			return new \WP_Error(
				'invalid_article_id',
				__( 'Invalid article ID provided', 'wisewand-ai-content-writer-seo-content-generator' ),
				array( 'article_id' => $id )
			);
		}

		return $this->request( 'GET', "/v1/discoverarticles/{$id}" );
	}

	/**
	 * Run discover article generation
	 */
	public function run_discoverarticle_generation( $id ) {
		// Sanitize article_id - assuming it's alphanumeric with hyphens/underscores
		$id = sanitize_key( $id );

		if ( empty( $id ) ) {
			return new \WP_Error(
				'invalid_article_id',
				__( 'Invalid article ID provided', 'wisewand-ai-content-writer-seo-content-generator' ),
				array( 'article_id' => $id )
			);
		}

		return $this->request( 'POST', "/v1/discoverarticles/{$id}/run", array(), array() );
	}

	/**
	 * Generic create content (routes to correct endpoint)
	 */
	public function create_content( $endpoint, $data ) {
		switch ( $endpoint ) {
			case 'categorypages':
				return $this->create_categorypage( $data );
			case 'productpages':
				return $this->create_productpage( $data );
			case 'discoverarticles':
				return $this->create_discoverarticle( $data );
			case 'articles':
			default:
				return $this->create_article( $data );
		}
	}

	/**
	 * Generic run generation (routes to correct endpoint)
	 */
	public function run_content_generation( $endpoint, $id ) {
		switch ( $endpoint ) {
			case 'categorypages':
				return $this->run_categorypage_generation( $id );
			case 'productpages':
				return $this->run_productpage_generation( $id );
			case 'discoverarticles':
				return $this->run_discoverarticle_generation( $id );
			case 'articles':
			default:
				return $this->run_article_generation( $id );
		}
	}

	/**
	 * Generic get content (routes to correct endpoint)
	 */
	public function get_content( $endpoint, $id ) {
		switch ( $endpoint ) {
			case 'categorypages':
				return $this->get_categorypage( $id );
			case 'productpages':
				return $this->get_productpage( $id );
			case 'discoverarticles':
				return $this->get_discoverarticle( $id );
			case 'articles':
			default:
				return $this->get_article( $id );
		}
	}

	/**
	 * List projects
	 */
	public function list_projects( $params = array(), $force_refresh = false ) {
		$default_params = array(
			'skip'   => 0,
			'take'   => 20,
			'search' => '',
		);

		$params = array_merge( $default_params, $params );

		// Generate cache key based on parameters
		$cache_key = 'wisewand_projects_' . md5( serialize( $params ) );

		// Check cache first (unless force refresh)
		if ( ! $force_refresh ) {
			$cached = get_transient( $cache_key );
			if ( $cached !== false ) {
				if ( $this->logger ) {
					$this->logger->debug(
						'Using cached projects list',
						array(
							'params'    => $params,
							'cache_key' => $cache_key,
						)
					);
				}
				return $cached;
			}
		}

		// Fetch from API
		$result = $this->request( 'GET', '/v1/projects/', $params );

		// Cache successful results for 5 minutes (projects rarely change)
		if ( ! is_wp_error( $result ) ) {
			set_transient( $cache_key, $result, 5 * MINUTE_IN_SECONDS );

			if ( $this->logger ) {
				$this->logger->debug(
					'Cached projects list',
					array(
						'cache_key' => $cache_key,
						'ttl'       => '5 minutes',
					)
				);
			}
		}

		return $result;
	}

	/**
	 * Get specific project
	 */
	public function get_project( $project_id ) {
		return $this->request( 'GET', "/v1/projects/{$project_id}" );
	}

	/**
	 * Get project brief configuration
	 *
	 * @since 2.8.0
	 * @param string $project_id Project ID.
	 * @return array|WP_Error Brief data or error.
	 */
	public function get_project_brief( $project_id ) {
		return $this->request( 'GET', "/v1/projects/{$project_id}/brief" );
	}

	/**
	 * Create new project
	 */
	public function create_project( $project_data ) {
		return $this->request( 'POST', '/v1/projects/', array(), $project_data );
	}

	/**
	 * Update project
	 */
	public function update_project( $project_id, $updates ) {
		return $this->request( 'PATCH', "/v1/projects/{$project_id}", array(), $updates );
	}

	/**
	 * List personas with caching
	 */
	public function list_personas( $params = array(), $force_refresh = false ) {
		$default_params = array(
			'skip'   => 0,
			'take'   => 20,
			'search' => '',
		);

		$params = array_merge( $default_params, $params );

		// Generate cache key based on parameters
		$cache_key = 'wisewand_personas_' . md5( serialize( $params ) );

		// Check cache first (unless force refresh)
		if ( ! $force_refresh ) {
			$cached = get_transient( $cache_key );
			if ( $cached !== false ) {
				if ( $this->logger ) {
					$this->logger->debug(
						'Using cached personas list',
						array(
							'params'    => $params,
							'cache_key' => $cache_key,
						)
					);
				}
				return $cached;
			}
		}

		// Fetch from API
		$result = $this->request( 'GET', '/v1/personas/', $params );

		// Cache successful results for 5 minutes
		if ( ! is_wp_error( $result ) ) {
			set_transient( $cache_key, $result, 5 * MINUTE_IN_SECONDS );

			if ( $this->logger ) {
				$this->logger->debug(
					'Cached personas list',
					array(
						'cache_key' => $cache_key,
						'ttl'       => '5 minutes',
					)
				);
			}
		}

		return $result;
	}

	/**
	 * Get specific persona with caching
	 */
	public function get_persona( $persona_id, $force_refresh = false ) {
		// Generate cache key
		$cache_key = 'wisewand_persona_' . $persona_id;

		// Check cache first (unless force refresh)
		if ( ! $force_refresh ) {
			$cached = get_transient( $cache_key );
			if ( $cached !== false ) {
				if ( $this->logger ) {
					$this->logger->debug(
						'Using cached persona',
						array(
							'persona_id' => $persona_id,
						)
					);
				}
				return $cached;
			}
		}

		// Fetch from API
		$result = $this->request( 'GET', "/v1/personas/{$persona_id}" );

		// Cache successful results for 15 minutes (personas change rarely)
		if ( ! is_wp_error( $result ) ) {
			set_transient( $cache_key, $result, 15 * MINUTE_IN_SECONDS );

			if ( $this->logger ) {
				$this->logger->debug(
					'Cached persona',
					array(
						'persona_id' => $persona_id,
						'ttl'        => '15 minutes',
					)
				);
			}
		}

		return $result;
	}

	/**
	 * Create new persona
	 */
	public function create_persona( $persona_data ) {
		return $this->request( 'POST', '/v1/personas/', array(), $persona_data );
	}

	/**
	 * Update persona
	 */
	public function update_persona( $persona_id, $updates ) {
		return $this->request( 'PATCH', "/v1/personas/{$persona_id}", array(), $updates );
	}

	/**
	 * Delete persona
	 */
	public function delete_persona( $persona_id ) {
		return $this->request( 'DELETE', "/v1/personas/{$persona_id}" );
	}

	/**
	 * List connections
	 */
	public function list_connections( $params = array() ) {
		$default_params = array(
			'skip'   => 0,
			'take'   => 20,
			'search' => '',
		);

		$params = array_merge( $default_params, $params );

		return $this->request( 'GET', '/v1/connections/', $params );
	}

	/**
	 * Test API connection and authentication
	 */
	public function test_connection() {
		return $this->request( 'GET', '/v1/articles/', array( 'take' => 1 ) );
	}

	/**
	 * Debug method to see raw project data
	 */
	public function debug_projects() {
		$result = $this->request( 'GET', '/v1/projects/', array( 'take' => 5 ) );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		// Log raw project data for debugging
		if ( $this->logger ) {
			$this->logger->info(
				'Raw projects data from API',
				array(
					'total_projects'         => $result['count'] ?? 0,
					'first_project_raw'      => $result['items'][0] ?? 'none',
					'all_projects_structure' => array_map(
						function ( $p ) {
							return array_keys( $p );
						},
						$result['items'] ?? array()
					),
				)
			);
		}

		return $result;
	}

	/**
	 * Publish to WordPress (if endpoint available)
	 */
	public function publish_to_wordpress( $entity_id, $connection_id = null ) {
		$data = array();
		if ( $connection_id ) {
			$data['connection_id'] = $connection_id;
		}

		return $this->request( 'POST', "/v1/publish/wordpress/{$entity_id}", array(), $data );
	}

	/**
	 * Trigger webhook
	 */
	public function trigger_webhook( $entity_id, $webhook_id ) {
		return $this->request(
			'POST',
			"/v1/publish/webhook/{$entity_id}",
			array(),
			array(
				'webhook_id' => $webhook_id,
			)
		);
	}

	/**
	 * Make HTTP request to Wisewand API
	 */
	private function request( $method, $endpoint, $query_params = array(), $body = null ) {
		// Check rate limiter before making request
		$rate_check = $this->rate_limiter->check_rate_limit( $endpoint );
		if ( false !== $rate_check ) {
			if ( $this->logger ) {
				$this->logger->debug(
					'Request blocked by rate limiter',
					array(
						'endpoint'  => $endpoint,
						'wait_time' => $rate_check['wait_time'],
					)
				);
			}

			return new \WP_Error(
				'wisewand_rate_limited_client',
				$rate_check['message'],
				$rate_check
			);
		}

		// Record request timestamp
		$this->rate_limiter->record_request( $endpoint );

		$url = $this->base_url . $endpoint;

		// Add query parameters
		if ( ! empty( $query_params ) ) {
			$query_params = array_filter(
				$query_params,
				function ( $value ) {
					return $value !== '' && $value !== null;
				}
			);

			if ( ! empty( $query_params ) ) {
				$url .= '?' . http_build_query( $query_params );
			}
		}

		// Prepare request arguments
		$args = array(
			'method'  => $method,
			'timeout' => 30,
			'headers' => array(
				'Authorization' => 'Bearer ' . $this->api_key,
				'Accept'        => 'application/json',
				'User-Agent'    => 'Wisewand-plugin/' . WISEWAND_PLUGIN_VERSION,
			),
		);

		// Add body for POST/PATCH requests
		if ( $body !== null && in_array( $method, array( 'POST', 'PATCH', 'PUT' ) ) ) {
			$args['headers']['Content-Type'] = 'application/json';
			$args['body']                    = wp_json_encode( $body );
		}

		if ( $this->logger ) {
			$this->logger->debug(
				'Wisewand API request',
				array(
					'method'   => $method,
					'url'      => $url,
					'has_body' => $body !== null,
				)
			);
		}

		// Make the request
		$response = wp_remote_request( $url, $args );

		// Handle WordPress HTTP errors
		if ( is_wp_error( $response ) ) {
			if ( $this->logger ) {
				$this->logger->error(
					'Wisewand API request failed',
					array(
						'method'   => $method,
						'endpoint' => $endpoint,
						'error'    => $response->get_error_message(),
					)
				);
			}

			return new WP_Error(
				'wisewand_api_request_failed',
				sprintf( 'API request failed: %s', $response->get_error_message() )
			);
		}

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

		// Log the response
		if ( $this->logger ) {
			$this->logger->debug(
				'Wisewand API response',
				array(
					'method'        => $method,
					'endpoint'      => $endpoint,
					'status_code'   => $response_code,
					'response_size' => strlen( $response_body ),
				)
			);
		}

		// Handle HTTP errors
		if ( $response_code >= 400 ) {
			// RATE LIMIT DETECTION (429)
			if ( $response_code === 429 ) {
				// Extract Retry-After header if present
				$retry_after = wp_remote_retrieve_header( $response, 'Retry-After' );

				if ( $this->logger ) {
					$this->logger->warning(
						'API rate limit exceeded (429)',
						array(
							'endpoint'    => $endpoint,
							'retry_after' => $retry_after,
						)
					);
				}

				return new \WP_Error(
					'wisewand_rate_limit_exceeded',
					__( 'Rate limit exceeded. Please wait before retrying.', 'wisewand-ai-content-writer-seo-content-generator' ),
					array(
						'status_code' => 429,
						'retry_after' => $retry_after ? (int) $retry_after : 60,
						'endpoint'    => $endpoint,
						'retryable'   => true,
					)
				);
			}

			$error_data    = json_decode( $response_body, true );
			$error_message = 'API request failed';

			// ENHANCED ERROR LOGGING - Capture full raw response
			// Use separate error_log calls to avoid truncation
			if ( WP_DEBUG ) {
				error_log( '=== WISEWAND API ERROR RESPONSE (RAW) ===' );
				error_log( 'Endpoint: ' . $endpoint );
				error_log( 'Method: ' . $method );
				error_log( 'HTTP Status: ' . strval( $response_code ) );

				// Log response body in chunks if needed
				$body_preview = substr( $response_body, 0, 1000 ); // First 1000 chars
				error_log( 'Response Body (first 1000 chars): ' . $body_preview );
				error_log( 'Response Body Length: ' . strlen( $response_body ) );

				// Try to extract specific error fields
				if ( is_array( $error_data ) ) {
					if ( isset( $error_data['message'] ) ) {
						error_log( 'API Error Message: ' . $error_data['message'] );
					}
					if ( isset( $error_data['error'] ) ) {
						error_log( 'API Error: ' . $error_data['error'] );
					}
					if ( isset( $error_data['details'] ) ) {
						error_log( 'API Error Details: ' . print_r( $error_data['details'], true ) );
					}
					if ( isset( $error_data['validation'] ) ) {
						error_log( 'API Validation Errors: ' . print_r( $error_data['validation'], true ) );
					}
				} else {
					error_log( 'Response is not valid JSON' );
				}
				error_log( '=========================================' );
			}

			if ( $error_data && isset( $error_data['message'] ) ) {
				$error_message = $error_data['message'];
			} elseif ( $error_data && isset( $error_data['error'] ) ) {
				$error_message = $error_data['error'];
			}

			if ( $this->logger ) {
				$this->logger->error(
					'Wisewand API error response',
					array(
						'method'        => $method,
						'endpoint'      => $endpoint,
						'status_code'   => $response_code,
						'error_message' => $error_message,
						'raw_response'  => $response_body,
					)
				);
			}

			// Differentiate between 404 (not found - permanent) and other errors
			if ( $response_code === 404 ) {
				return new WP_Error(
					'wisewand_resource_not_found',  // Specific error code for 404
					$error_message,
					array(
						'status_code'   => $response_code,
						'response_data' => $error_data,
						'raw_response'  => $response_body,
						'permanent'     => true,  // Flag indicating this is likely permanent
					)
				);
			}

			return new WP_Error(
				'wisewand_api_error',
				$error_message,
				array(
					'status_code'   => $response_code,
					'response_data' => $error_data,
					'raw_response'  => $response_body,
				)
			);
		}

		// Parse JSON response
		$data = json_decode( $response_body, true );

		if ( json_last_error() !== JSON_ERROR_NONE ) {
			if ( $this->logger ) {
				$this->logger->error(
					'Wisewand API invalid JSON response',
					array(
						'method'     => $method,
						'endpoint'   => $endpoint,
						'json_error' => json_last_error_msg(),
					)
				);
			}

			return new WP_Error(
				'wisewand_api_invalid_json',
				'API returned invalid JSON response'
			);
		}

		return $data;
	}

	/**
	 * Test if API key is valid
	 */
	public function validate_api_key() {
		$result = $this->test_connection();

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return true;
	}

	/**
	 * Get API key info/usage
	 */
	public function get_api_info() {
		// This might not be available in all API versions
		$result = $this->request( 'GET', '/v1/user/me' );

		if ( is_wp_error( $result ) ) {
			// Fallback: just test connection
			$test_result = $this->test_connection();
			if ( is_wp_error( $test_result ) ) {
				return $test_result;
			}

			return array(
				'valid'      => true,
				'method'     => 'connection_test',
				'rate_limit' => '60 requests per minute',
			);
		}

		return $result;
	}


	/**
	 * Get formatted content list for WordPress admin (supports all content types)
	 */
	public function get_articles_for_admin( $page = 1, $per_page = 20, $filters = array() ) {
		$skip         = ( $page - 1 ) * $per_page;
		$content_type = $filters['content_type'] ?? 'articles';

		$params = array(
			'skip' => $skip,
			'take' => $per_page,
		);

		// Add filters
		if ( ! empty( $filters['search'] ) ) {
			$params['search'] = $filters['search'];
		}

		if ( ! empty( $filters['status'] ) ) {
			$params['status'] = $filters['status'];
		}

		if ( ! empty( $filters['project_id'] ) ) {
			$params['projectId'] = $filters['project_id'];
		}

		if ( isset( $filters['published'] ) ) {
			$params['published'] = $filters['published'] ? 'true' : 'false';
		}

		$result = $this->list_content( $content_type, $params );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		// Format for WordPress admin table
		$formatted_items = array();
		if ( isset( $result['items'] ) && is_array( $result['items'] ) ) {
			foreach ( $result['items'] as $item ) {
				$formatted_items[] = $this->format_content_for_admin( $item, $content_type );
			}
		}

		return array(
			'articles'     => $formatted_items, // Keep 'articles' key for compatibility
			'content_type' => $content_type,
			'total'        => $result['count'] ?? 0,
			'page'         => $page,
			'per_page'     => $per_page,
			'total_pages'  => ceil( ( $result['count'] ?? 0 ) / $per_page ),
		);
	}

	/**
	 * Format content data for admin display (supports all content types)
	 */
	private function format_content_for_admin( $item, $content_type = 'articles' ) {
		return $this->format_article_for_admin( $item, $content_type );
	}

	/**
	 * Format article data for admin display
	 */
	private function format_article_for_admin( $article, $content_type = 'articles' ) {
		$input = $article['data']['input'] ?? array();

		// Enhanced language detection from API response
		$detected_lang = $this->detect_language_from_content( $article );

		return array(
			'id'             => $article['id'] ?? '',
			'title'          => $article['title'] ?? $input['title'] ?? 'Untitled',
			'subject'        => $input['subject'] ?? '',
			'status'         => $article['status'] ?? 'unknown',
			'type'           => $input['type'] ?? 'blog',
			'content_type'   => $content_type, // Track what type of content this is
			'lang'           => $detected_lang['lang'],
			'country'        => $detected_lang['country'],
			'target_keyword' => $input['target_keyword'] ?? '',
			'created_at'     => $article['created_at'] ?? '',
			'updated_at'     => $article['updated_at'] ?? '',
			'is_published'   => $article['is_published'] ?? false,
			'cover_image'    => $article['cover_image'] ?? '',
			'project_id'     => $article['project_id'] ?? '',
			'last_output_id' => $article['last_output_id'] ?? '',
			'length'         => $input['length'] ?? 'auto',
			'features'       => array(
				'faq'            => $input['use_faq'] ?? false,
				'toc'            => $input['use_toc'] ?? false,
				'image'          => $input['use_image'] ?? false,
				'audio'          => $input['use_audio'] ?? false,
				'social'         => $input['use_social'] ?? false,
				'bold_keywords'  => $input['use_boldkeywords'] ?? false,
				'internal_links' => $input['use_internallinks'] ?? false,
			),
			'original_input' => $input, // Keep original data for reference
		);
	}

	private function detect_language_from_content( $article ) {
		$input = $article['data']['input'] ?? array();

		// Get the configured language and country
		$lang    = strtolower( $input['lang'] ?? 'en' );
		$country = strtolower( $input['country'] ?? 'us' );

		// If we have output content, analyze it to verify language
		$output = $article['data']['output'] ?? array();
		if ( ! empty( $output['content'] ) ) {
			$content_lang = $this->analyze_content_language( $output['content'] );
			if ( $content_lang && $content_lang !== $lang ) {
				// Content language differs from configured language - use content language
				$this->logger->info(
					'Language mismatch detected',
					array(
						'configured_lang'       => $lang,
						'detected_from_content' => $content_lang,
						'article_id'            => $article['id'] ?? 'unknown',
					)
				);
				$lang = $content_lang;
			}
		}

		return array(
			'lang'    => $lang,
			'country' => $country,
		);
	}

	private function analyze_content_language( $content ) {
		// Simple language detection based on common words/patterns
		$content_lower = strtolower( wp_strip_all_tags( $content ) );

		// French indicators
		$french_words = array( 'le ', 'la ', 'les ', 'un ', 'une ', 'des ', 'de ', 'du ', 'avec', 'pour', 'dans', 'sur', 'est ', 'sont', 'avoir', 'être' );
		$french_count = 0;
		foreach ( $french_words as $word ) {
			$french_count += substr_count( $content_lower, $word );
		}

		// English indicators
		$english_words = array( 'the ', 'and ', 'or ', 'but ', 'in ', 'on ', 'at ', 'to ', 'for', 'of ', 'with', 'by ', 'from', 'this', 'that', 'have', 'has' );
		$english_count = 0;
		foreach ( $english_words as $word ) {
			$english_count += substr_count( $content_lower, $word );
		}

		// Determine language based on word frequency
		if ( $english_count > $french_count && $english_count > 5 ) {
			return 'en';
		} elseif ( $french_count > $english_count && $french_count > 5 ) {
			return 'fr';
		}

		return null; // Could not determine
	}

	/**
	 * Get human-readable status
	 */
	public function get_status_label( $status ) {
		$labels = array(
			'queued'  => __( 'Queued', 'wisewand-ai-content-writer-seo-content-generator' ),
			'running' => __( 'Generating...', 'wisewand-ai-content-writer-seo-content-generator' ),
			'success' => __( 'Ready', 'wisewand-ai-content-writer-seo-content-generator' ),
			'error'   => __( 'Error', 'wisewand-ai-content-writer-seo-content-generator' ),
		);

		return $labels[ $status ] ?? $status;
	}

	/**
	 * Get status CSS class for admin display
	 */
	public function get_status_class( $status ) {
		$classes = array(
			'queued'  => 'status-queued',
			'running' => 'status-running',
			'success' => 'status-success',
			'error'   => 'status-error',
		);

		return $classes[ $status ] ?? 'status-unknown';
	}

	/**
	 * Check if article is ready for import
	 */
	public function is_article_ready( $article ) {
		return isset( $article['status'] ) && $article['status'] === 'success';
	}

	/**
	 * Get error message for failed articles
	 */
	public function get_error_message( $article ) {
		if ( isset( $article['status_detail'] ) ) {
			return $article['status_detail'];
		}

		if ( isset( $article['status'] ) && $article['status'] === 'error' ) {
			return __( 'Generation failed', 'wisewand-ai-content-writer-seo-content-generator' );
		}

		return '';
	}

	/**
	 * Validate API key format
	 */
	public static function validate_api_key_format( $api_key ) {
		// Basic validation - adjust based on Wisewand's key format
		if ( empty( $api_key ) ) {
			return false;
		}

		if ( strlen( $api_key ) < 10 ) {
			return false;
		}

		// Check for valid characters (adjust as needed)
		if ( ! preg_match( '/^[a-zA-Z0-9_.-]+$/', $api_key ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Secure storage of API key
	 */
	public static function store_api_key( $api_key ) {
		if ( ! self::validate_api_key_format( $api_key ) ) {
			return new WP_Error(
				'wisewand_invalid_api_key',
				__( 'Invalid API key format', 'wisewand-ai-content-writer-seo-content-generator' )
			);
		}

		// Store with WordPress options API (encrypted if possible)
		$success = update_option( 'wisewand_api_key', $api_key );

		if ( $success ) {
			// Log API key change (without exposing the key)
			$masked_key = substr( $api_key, 0, 8 ) . str_repeat( '*', max( 0, strlen( $api_key ) - 8 ) );

			if ( function_exists( 'get_current_user_id' ) ) {
				$user_id = get_current_user_id();
				update_option( 'wisewand_api_key_updated_by', $user_id );
				update_option( 'wisewand_api_key_updated_at', current_time( 'mysql' ) );
			}

			do_action( 'wisewand_api_key_updated', $masked_key );
		}

		return $success;
	}

	/**
	 * Retrieve stored API key
	 */
	public static function get_stored_api_key() {
		return get_option( 'wisewand_api_key', '' );
	}

	/**
	 * Check if API key is configured
	 */
	public static function is_api_key_configured() {
		$api_key = self::get_stored_api_key();
		return ! empty( $api_key ) && self::validate_api_key_format( $api_key );
	}

	/**
	 * Get masked API key for display
	 */
	public static function get_masked_api_key() {
		$api_key = self::get_stored_api_key();

		if ( empty( $api_key ) ) {
			return '';
		}

		return substr( $api_key, 0, 8 ) . str_repeat( '*', max( 0, strlen( $api_key ) - 8 ) );
	}

	/**
	 * Remove stored API key
	 */
	public static function remove_api_key() {
		delete_option( 'wisewand_api_key' );
		delete_option( 'wisewand_api_key_updated_by' );
		delete_option( 'wisewand_api_key_updated_at' );

		do_action( 'wisewand_api_key_removed' );

		return true;
	}

	/**
	 * Clear all cached API responses
	 * Call this after creating/updating/deleting projects or personas
	 */
	public function clear_cache() {
		global $wpdb;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk transient cleanup from WordPress options table, more efficient than individual delete_transient() calls
		// Clear all Wisewand API caches
		$wpdb->query(
			"DELETE FROM {$wpdb->options}
             WHERE option_name LIKE '_transient_wisewand_projects_%'
             OR option_name LIKE '_transient_timeout_wisewand_projects_%'
             OR option_name LIKE '_transient_wisewand_personas_%'
             OR option_name LIKE '_transient_timeout_wisewand_personas_%'
             OR option_name LIKE '_transient_wisewand_persona_%'
             OR option_name LIKE '_transient_timeout_wisewand_persona_%'"
		);

		if ( $this->logger ) {
			$this->logger->info( 'Cleared all Wisewand API caches' );
		}
	}

	/**
	 * Clear projects cache only
	 */
	public function clear_projects_cache() {
		global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk transient cleanup, more efficient than individual delete_transient() calls
		$wpdb->query(
			"DELETE FROM {$wpdb->options}
             WHERE option_name LIKE '_transient_wisewand_projects_%'
             OR option_name LIKE '_transient_timeout_wisewand_projects_%'"
		);
	}

	/**
	 * Clear personas cache only
	 */
	public function clear_personas_cache() {
		global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk transient cleanup, more efficient than individual delete_transient() calls
		$wpdb->query(
			"DELETE FROM {$wpdb->options}
             WHERE option_name LIKE '_transient_wisewand_personas_%'
             OR option_name LIKE '_transient_timeout_wisewand_personas_%'
             OR option_name LIKE '_transient_wisewand_persona_%'
             OR option_name LIKE '_transient_timeout_wisewand_persona_%'"
		);
	}
}
