<?php
/**
 * AI Requests
 *
 * This file contains all AI model provider requests.
 *
 * @package Simple_Ai_Auto_Post
 * @since 1.0.0
 */

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

// Make sure this file is being included by a parent file.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Make a generic AI request to any supported provider
 *
 * @param string $user_message The user's message
 * @param string $provider The AI provider (openai, anthropic, or gemini)
 * @param string $model The AI model to use
 * @param string $system_prompt Optional system prompt
 * @return string|WP_Error The AI response content or error
 */
function saiap_make_ai_request( $user_message, $provider = 'openai', $model = '', $system_prompt = '' ) {
	// Get API key
	$api_key = get_option( 'saiap_' . $provider . '_api_key' );
	if ( empty( $api_key ) ) {
		return new WP_Error( 'missing_api_key', 'API key not configured for ' . $provider );
	}

	// Prepare messages
	$messages = array();
	if ( ! empty( $system_prompt ) ) {
		$messages[] = array( 'role' => 'system', 'content' => $system_prompt );
	}
	$messages[] = array( 'role' => 'user', 'content' => $user_message );

    // Make API call based on provider
    if ( $provider === 'openai' ) {
        $schema = array(
            'type'       => 'object',
            'properties' => array(
                'chat_message'   => array(
                    'type'        => 'string',
                    'description' => 'Brief explanation of what you changed or a conversational response.',
                ),
                'has_edit'       => array(
                    'type'        => 'boolean',
                    'description' => 'Whether an edit was made to the content.',
                ),
                'edited_content' => array(
                    'type'        => 'string',
                    'description' => 'The complete edited content. If no edit is made, this should be an empty string.',
                ),
            ),
            'required'   => array( 'chat_message', 'has_edit', 'edited_content' ),
            'additionalProperties' => false,
        );

        // Convert messages to Responses API input format
        $input = array();
        foreach ( $messages as $m ) {
            $input[] = array(
                'role'    => $m['role'],
                'content' => array(
                    array( 'type' => 'input_text', 'text' => $m['content'] ),
                ),
            );
        }

        $response = wp_remote_post( 'https://api.openai.com/v1/responses', array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $api_key,
                'Content-Type' => 'application/json',
            ),
            'body' => wp_json_encode( array(
                'model' => $model ?: 'gpt-5.4',
                'tools' => array( array( 'type' => 'web_search' ) ),
                'input' => $input,
                'text' => array(
                    'format' => array(
                        'type' => 'json_schema',
                        'name' => 'json_responder',
                        'schema' => $schema,
                        'strict' => true,
                    )
				),
            ) ),
            'timeout' => 180,
        ) );

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

        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );

        // Responses API returns output_text or output tree
        if ( isset( $data['output_text'] ) && is_string( $data['output_text'] ) && $data['output_text'] !== '' ) {
            return $data['output_text'];
        }
        if ( isset( $data['output'][0]['content'][0]['text'] ) && is_string( $data['output'][0]['content'][0]['text'] ) ) {
            return $data['output'][0]['content'][0]['text'];
        }

        if ( isset( $data['error']['message'] ) ) {
            return new WP_Error( 'api_error', 'OpenAI API Error: ' . sanitize_text_field( $data['error']['message'] ) );
        }

        return new WP_Error( 'invalid_response', 'Invalid response from OpenAI Responses API' );
		
	} elseif ( $provider === 'anthropic' ) {
		$tool_schema = array(
			'type'          => 'custom',
			'name'          => 'json_responder',
			'description'   => 'Responds with a JSON object containing a chat message and edited content.',
			'input_schema'  => array(
				'type'       => 'object',
				'properties' => array(
					'chat_message'   => array(
						'type'        => 'string',
						'description' => 'Brief explanation of what you changed or a conversational response.',
					),
					'has_edit'       => array(
						'type'        => 'boolean',
						'description' => 'Whether an edit was made to the content.',
					),
					'edited_content' => array(
						'type'        => 'string',
						'description' => 'The complete edited content. If no edit is made, this should be an empty string.',
					),
				),
				'required'   => array( 'chat_message', 'has_edit', 'edited_content' ),
			),
		);

		// Extract system message for Anthropic API format
		$system_content = '';
		$anthropic_messages = array();
		
		foreach ( $messages as $message ) {
			if ( $message['role'] === 'system' ) {
				$system_content = $message['content'];
			} else {
				$anthropic_messages[] = $message;
			}
		}

		// Prepare request body for Anthropic (enable web search + JSON tool)
		$request_body = array(
			'model'       => $model ?: 'claude-opus-4-5',
			'messages'    => $anthropic_messages,
			'tool_choice' => array( 'type' => 'tool', 'name' => 'json_responder' ),
			'tools'       => array( array( 'type' => 'web_search_20250305', 'name' => 'web_search' ), $tool_schema ),
		);

		// Add system parameter if we have system content
		if ( ! empty( $system_content ) ) {
			$request_body['system'] = $system_content;
		}

		$response = wp_remote_post( 'https://api.anthropic.com/v1/messages', array(
			'headers' => array(
				'x-api-key'         => $api_key,
				'anthropic-version' => '2023-06-01',
				'Content-Type'      => 'application/json',
			),
			'body'    => wp_json_encode( $request_body ),
			'timeout' => 360, // 6 minutes
		) );

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

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			$error_message = 'Anthropic API error: ';
			$body          = wp_remote_retrieve_body( $response );
			$data          = json_decode( $body, true );

			if ( isset( $data['error']['message'] ) ) {
				$error_message .= sanitize_text_field( $data['error']['message'] );
			} else {
				$error_message .= 'HTTP status ' . $status_code;
			}

			return new WP_Error( 'api_error', $error_message );
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		if ( isset( $data['content'] ) && is_array( $data['content'] ) ) {
			foreach ( $data['content'] as $content_block ) {
				if (
					isset( $content_block['type'] ) &&
					'tool_use' === $content_block['type'] &&
					isset( $content_block['name'] ) &&
					'json_responder' === $content_block['name'] &&
					isset( $content_block['input'] )
				) {
					return wp_json_encode( $content_block['input'] );
				}
			}
		}

		if ( isset( $data['error']['message'] ) ) {
			return new WP_Error( 'api_error', 'Anthropic API Error: ' . sanitize_text_field( $data['error']['message'] ) );
		}

		return new WP_Error( 'invalid_response', 'Invalid response from Anthropic API. Expected a tool_use block.' );

	} elseif ( $provider === 'gemini' ) {
		// Convert messages to Gemini format
		$gemini_messages = array();
		foreach ( $messages as $message ) {
			if ( $message['role'] === 'system' ) {
				// Add system message as user message
				$gemini_messages[] = array(
					'role'  => 'user',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
				// Add a model response
				$gemini_messages[] = array(
					'role'  => 'model',
					'parts' => array(
						array( 'text' => "I understand. I'll follow these instructions." ),
					),
				);
			} elseif ( $message['role'] === 'user' ) {
				$gemini_messages[] = array(
					'role'  => 'user',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
			} elseif ( $message['role'] === 'assistant' ) {
				$gemini_messages[] = array(
					'role'  => 'model',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
			}
		}

		$schema = array(
			'type'       => 'OBJECT',
			'properties' => array(
				'chat_message'   => array(
					'type' => 'STRING',
					'description' => 'Brief explanation of what you changed or a conversational response.',
				),
				'has_edit'       => array(
					'type' => 'BOOLEAN',
					'description' => 'Whether an edit was made to the content.',
				),
				'edited_content' => array(
					'type' => 'STRING',
					'description' => 'The complete edited content. If no edit is made, this should be an empty string.',
				),
			),
			'required'   => array( 'chat_message', 'has_edit', 'edited_content' ),
		);

		// Prepare Gemini request body
		$gemini_request = array(
			'contents'         => $gemini_messages,
			'generationConfig' => array(
				'response_mime_type' => 'application/json',
				'response_schema'    => $schema,
				'maxOutputTokens'    => 100000,
				'temperature'        => 0.7,
				'topP'               => 0.95,
				'topK'               => 40,
			),
		);

		// Build URL with API key
		$model_id = $model ?: 'gemini-2.5-pro';
		$url      = "https://generativelanguage.googleapis.com/v1beta/models/{$model_id}:generateContent?key={$api_key}";

		// Make request to Gemini API
		$response = wp_remote_post(
			$url,
			array(
				'headers' => array(
					'Content-Type' => 'application/json',
				),
				'body'    => wp_json_encode( $gemini_request ),
				'timeout' => 360, // 6 minutes
			)
		);

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

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			$error_message = 'Gemini API error: ';
			$body          = wp_remote_retrieve_body( $response );
			$data          = json_decode( $body, true );

			if ( isset( $data['error']['message'] ) ) {
				$error_message .= sanitize_text_field( $data['error']['message'] );
			} else {
				$error_message .= 'HTTP status ' . $status_code;
			}

			return new WP_Error( 'api_error', $error_message );
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		// Check for error in response body, even with 200 status
		if ( isset( $data['error']['message'] ) ) {
			return new WP_Error( 'api_error', 'Gemini API Error: ' . sanitize_text_field( $data['error']['message'] ) );
		}

		// Check response structure
		if ( ! $data ||
			! isset( $data['candidates'] ) ||
			! isset( $data['candidates'][0] ) ||
			! isset( $data['candidates'][0]['content'] ) ||
			! isset( $data['candidates'][0]['content']['parts'] ) ||
			! isset( $data['candidates'][0]['content']['parts'][0] ) ||
			! isset( $data['candidates'][0]['content']['parts'][0]['text'] ) ) {
			return new WP_Error( 'invalid_response', 'Invalid response from Gemini API. Please check your API key and try again.' );
		}

		return $data['candidates'][0]['content']['parts'][0]['text'];
	}
	
	return new WP_Error( 'unsupported_provider', 'Unsupported provider: ' . $provider );
}

/**
 * Generate post content using AI APIs
 *
 * @param string $prompt The user's prompt
 * @param string $model The AI model to use
 * @param string $provider The AI provider (openai or anthropic)
 * @param string $type_key Optional post type map key to guide generation
 * @param string $content_brief Optional content brief with structure and image hints
 * @return array Generated content with title, content, link and link title; may include additional meta such as inline image tasks
 */
function saiap_generate_post_content( $prompt, $model = 'gpt-5.4', $provider = 'openai', $type_key = '', $content_brief = '' ) {
	// Prepare the request data
	$request_data = array(
		'model'      => $model,
		'messages'   => array(
			array(
				'role'    => 'system',
				'content' => saiap_get_system_prompt(),
			),
			array(
				'role'    => 'user',
				'content' => $prompt,
			),
		),
	);
	if ( ! empty( $type_key ) ) {
		$request_data['type_key'] = $type_key;
	}
	if ( ! empty( $content_brief ) ) {
		$request_data['content_brief'] = $content_brief;
	}

	// For users with premium license keys or active trials, try premium API first.
	// If it fails due to auth, fall back to local API.
	$license_key = get_option( 'saiap_license_key', '' );
	$has_premium_access = ! empty( $license_key ) || ( function_exists( 'saiap_has_active_trial' ) && saiap_has_active_trial() );
	if ( $has_premium_access ) {
		try {
			return saiap_generate_premium_content( $request_data, $provider );
		} catch ( Exception $e ) {
			// If premium service fails due to auth issues, fall back to local API
			// This allows graceful degradation for invalid keys
			if ( strpos( $e->getMessage(), 'license' ) !== false || strpos( $e->getMessage(), 'auth' ) !== false ) {
				// Continue to local API below
			} else {
				// Re-throw non-auth errors
				throw $e;
			}
		}
	}

	// Make direct request to the appropriate API (either no license key or auth failed)
	$api_key = '';

	if ( $provider === 'anthropic' ) {
		// Request to Anthropic API using structured outputs (tool_use)
		$api_key = get_option( 'saiap_anthropic_api_key' );

		if ( empty( $api_key ) ) {
			throw new Exception( 'Anthropic API key is required. Please enter your API key in the settings.' );
		}

		// Define the post generation tool schema
		$post_tool_schema = array(
			'type'          => 'custom',
			'name'          => 'generate_post',
			'description'   => 'Generate a WordPress blog post with title, Gutenberg content, and optional reference link.',
			'input_schema'  => array(
				'type'       => 'object',
				'properties' => array(
					'title'     => array(
						'type'        => 'string',
						'description' => 'The post title. Should be engaging and SEO-friendly.',
					),
					'content'   => array(
						'type'        => 'string',
						'description' => 'The full post content as valid Gutenberg blocks. Use wp:paragraph, wp:heading, wp:table, etc. Do NOT use markdown.',
					),
					'link'      => array(
						'type'        => 'string',
						'description' => 'A relevant external resource URL for further reading. Leave empty string if not applicable.',
					),
					'linkTitle' => array(
						'type'        => 'string',
						'description' => 'The anchor text for the external link. Leave empty string if link is empty.',
					),
				),
				'required'   => array( 'title', 'content', 'link', 'linkTitle' ),
			),
		);

		// Extract system message for Anthropic API format
		$system_content = '';
		$anthropic_messages = array();

		foreach ( $request_data['messages'] as $message ) {
			if ( $message['role'] === 'system' ) {
				$system_content = $message['content'];
			} else {
				$anthropic_messages[] = $message;
			}
		}

		// Prepare request body for Anthropic with tool_use
		$anthropic_request_data = array(
			'model'       => $request_data['model'],
			'messages'    => $anthropic_messages,
			'tools'       => array(
				array( 'type' => 'web_search_20250305', 'name' => 'web_search' ),
				$post_tool_schema,
			),
			'tool_choice' => array( 'type' => 'tool', 'name' => 'generate_post' ),
			'max_tokens'  => 8192,
		);

		// Add system parameter if we have system content
		if ( ! empty( $system_content ) ) {
			$anthropic_request_data['system'] = $system_content;
		}

		$response = wp_remote_post(
			'https://api.anthropic.com/v1/messages',
			array(
				'headers' => array(
					'x-api-key'         => $api_key,
					'anthropic-version' => '2023-06-01',
					'Content-Type'      => 'application/json',
				),
				'body'    => wp_json_encode( $anthropic_request_data ),
				'timeout' => 360, // 6 minutes
			)
		);

		if ( is_wp_error( $response ) ) {
			throw new Exception( esc_html( $response->get_error_message() ) );
		}

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			$error_message = 'Anthropic API error: ';
			$body          = wp_remote_retrieve_body( $response );
			$data          = json_decode( $body, true );

			if ( isset( $data['error']['message'] ) ) {
				$error_message .= sanitize_text_field( $data['error']['message'] );
			} else {
				$error_message .= 'HTTP status ' . $status_code;
			}

			throw new Exception( esc_html( $error_message ) );
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		// Extract structured output from tool_use block
		$structured_output = null;
		if ( isset( $data['content'] ) && is_array( $data['content'] ) ) {
			foreach ( $data['content'] as $content_block ) {
				if (
					isset( $content_block['type'] ) &&
					'tool_use' === $content_block['type'] &&
					isset( $content_block['name'] ) &&
					'generate_post' === $content_block['name'] &&
					isset( $content_block['input'] )
				) {
					$structured_output = $content_block['input'];
					break;
				}
			}
		}

		if ( $structured_output && isset( $structured_output['title'] ) && isset( $structured_output['content'] ) ) {
			// Successfully got structured output
			return array(
				'title'     => sanitize_text_field( $structured_output['title'] ),
				'content'   => $structured_output['content'],
				'link'      => isset( $structured_output['link'] ) ? esc_url_raw( $structured_output['link'] ) : '',
				'linkTitle' => isset( $structured_output['linkTitle'] ) ? sanitize_text_field( $structured_output['linkTitle'] ) : '',
			);
		}

		// Fallback: try to get text content for regex parsing
		if ( isset( $data['content'][0]['text'] ) ) {
			$content = $data['content'][0]['text'];
		} else {
			throw new Exception( 'Invalid response from Anthropic API. Please check your API key and try again.' );
		}

	} elseif ( $provider === 'gemini' ) {
		// Request to Gemini API using structured outputs (responseSchema)
		$api_key = get_option( 'saiap_gemini_api_key' );

		if ( empty( $api_key ) ) {
			throw new Exception( 'Gemini API key is required. Please enter your API key in the settings.' );
		}

		// Define the post generation schema (Gemini uses UPPERCASE types)
		$post_schema = array(
			'type'       => 'OBJECT',
			'properties' => array(
				'title'     => array(
					'type'        => 'STRING',
					'description' => 'The post title. Should be engaging and SEO-friendly.',
				),
				'content'   => array(
					'type'        => 'STRING',
					'description' => 'The full post content as valid Gutenberg blocks. Use wp:paragraph, wp:heading, wp:table, etc. Do NOT use markdown.',
				),
				'link'      => array(
					'type'        => 'STRING',
					'description' => 'A relevant external resource URL for further reading. Leave empty string if not applicable.',
				),
				'linkTitle' => array(
					'type'        => 'STRING',
					'description' => 'The anchor text for the external link. Leave empty string if link is empty.',
				),
			),
			'required'   => array( 'title', 'content', 'link', 'linkTitle' ),
		);

		// Convert messages to Gemini format
		$gemini_messages = array();
		foreach ( $request_data['messages'] as $message ) {
			if ( $message['role'] === 'system' ) {
				// Add system message as user message
				$gemini_messages[] = array(
					'role'  => 'user',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
				// Add a model response
				$gemini_messages[] = array(
					'role'  => 'model',
					'parts' => array(
						array( 'text' => "I understand. I'll follow these instructions." ),
					),
				);
			} elseif ( $message['role'] === 'user' ) {
				$gemini_messages[] = array(
					'role'  => 'user',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
			} elseif ( $message['role'] === 'assistant' ) {
				$gemini_messages[] = array(
					'role'  => 'model',
					'parts' => array(
						array( 'text' => $message['content'] ),
					),
				);
			}
		}

		// Prepare Gemini request body with structured output
		$gemini_request = array(
			'contents'         => $gemini_messages,
			'generationConfig' => array(
				'responseMimeType' => 'application/json',
				'responseSchema'   => $post_schema,
				'temperature'      => 0.7,
				'topP'             => 0.95,
				'topK'             => 40,
			),
		);

		// Build URL with API key
		$model_id = $model;
		$url      = "https://generativelanguage.googleapis.com/v1beta/models/{$model_id}:generateContent?key={$api_key}";

		// Make request to Gemini API
		$response = wp_remote_post(
			$url,
			array(
				'headers' => array(
					'Content-Type' => 'application/json',
				),
				'body'    => wp_json_encode( $gemini_request ),
				'timeout' => 360, // 6 minutes
			)
		);

		if ( is_wp_error( $response ) ) {
			throw new Exception( esc_html( $response->get_error_message() ) );
		}

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			$error_message = 'Gemini API error: ';
			$body          = wp_remote_retrieve_body( $response );
			$data          = json_decode( $body, true );

			if ( isset( $data['error']['message'] ) ) {
				$error_message .= sanitize_text_field( $data['error']['message'] );
			} else {
				$error_message .= 'HTTP status ' . $status_code;
			}

			throw new Exception( esc_html( $error_message ) );
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		// Check response structure
		if ( ! $data ||
			! isset( $data['candidates'] ) ||
			! isset( $data['candidates'][0] ) ||
			! isset( $data['candidates'][0]['content'] ) ||
			! isset( $data['candidates'][0]['content']['parts'] ) ||
			! isset( $data['candidates'][0]['content']['parts'][0] ) ||
			! isset( $data['candidates'][0]['content']['parts'][0]['text'] ) ) {
			throw new Exception( 'Invalid response from Gemini API. Please check your API key and try again.' );
		}

		$json_text = $data['candidates'][0]['content']['parts'][0]['text'];

		// Parse the JSON response
		$structured_output = json_decode( $json_text, true );
		if ( $structured_output && isset( $structured_output['title'] ) && isset( $structured_output['content'] ) ) {
			// Successfully got structured output
			return array(
				'title'     => sanitize_text_field( $structured_output['title'] ),
				'content'   => $structured_output['content'],
				'link'      => isset( $structured_output['link'] ) ? esc_url_raw( $structured_output['link'] ) : '',
				'linkTitle' => isset( $structured_output['linkTitle'] ) ? sanitize_text_field( $structured_output['linkTitle'] ) : '',
			);
		}

		// Fallback to regex parsing if JSON parsing fails
		$content = $json_text;

	} elseif ( $provider === 'openai' ) {
		// Request to OpenAI Responses API using structured outputs (json_schema)
		$api_key = get_option( 'saiap_openai_api_key' );

		if ( empty( $api_key ) ) {
			throw new Exception( 'OpenAI API key is required. Please enter your API key in the settings.' );
		}

		// Define the post generation schema
		$post_schema = array(
			'type'       => 'object',
			'properties' => array(
				'title'     => array(
					'type'        => 'string',
					'description' => 'The post title. Should be engaging and SEO-friendly.',
				),
				'content'   => array(
					'type'        => 'string',
					'description' => 'The full post content as valid Gutenberg blocks. Use wp:paragraph, wp:heading, wp:table, etc. Do NOT use markdown.',
				),
				'link'      => array(
					'type'        => 'string',
					'description' => 'A relevant external resource URL for further reading. Leave empty string if not applicable.',
				),
				'linkTitle' => array(
					'type'        => 'string',
					'description' => 'The anchor text for the external link. Leave empty string if link is empty.',
				),
			),
			'required'             => array( 'title', 'content', 'link', 'linkTitle' ),
			'additionalProperties' => false,
		);

		// Convert messages to Responses API input format
		$input = array();
		foreach ( $request_data['messages'] as $m ) {
			$input[] = array(
				'role'    => $m['role'],
				'content' => array(
					array( 'type' => 'input_text', 'text' => $m['content'] ),
				),
			);
		}

		$response = wp_remote_post(
			'https://api.openai.com/v1/responses',
			array(
				'headers' => array(
					'Authorization' => 'Bearer ' . $api_key,
					'Content-Type'  => 'application/json',
				),
				'body'    => wp_json_encode(
					array(
						'model' => $request_data['model'],
						'tools' => array( array( 'type' => 'web_search' ) ),
						'input' => $input,
						'text'  => array(
							'format' => array(
								'type'   => 'json_schema',
								'name'   => 'generate_post',
								'schema' => $post_schema,
								'strict' => true,
							),
						),
					)
				),
				'timeout' => 180,
			)
		);

		if ( is_wp_error( $response ) ) {
			throw new Exception( esc_html( $response->get_error_message() ) );
		}

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			$error_message = 'OpenAI API error: ';
			$body          = wp_remote_retrieve_body( $response );
			$data          = json_decode( $body, true );

			if ( isset( $data['error']['message'] ) ) {
				$error_message .= sanitize_text_field( $data['error']['message'] );
			} else {
				$error_message .= 'HTTP status ' . $status_code;
			}

			throw new Exception( esc_html( $error_message ) );
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		// Responses API returns output_text or output tree
		$json_text = '';
		if ( isset( $data['output_text'] ) && is_string( $data['output_text'] ) && $data['output_text'] !== '' ) {
			$json_text = $data['output_text'];
		} elseif ( isset( $data['output'][0]['content'][0]['text'] ) && is_string( $data['output'][0]['content'][0]['text'] ) ) {
			$json_text = $data['output'][0]['content'][0]['text'];
		}

		if ( ! empty( $json_text ) ) {
			// Parse the JSON response
			$structured_output = json_decode( $json_text, true );
			if ( $structured_output && isset( $structured_output['title'] ) && isset( $structured_output['content'] ) ) {
				// Successfully got structured output
				return array(
					'title'     => sanitize_text_field( $structured_output['title'] ),
					'content'   => $structured_output['content'],
					'link'      => isset( $structured_output['link'] ) ? esc_url_raw( $structured_output['link'] ) : '',
					'linkTitle' => isset( $structured_output['linkTitle'] ) ? sanitize_text_field( $structured_output['linkTitle'] ) : '',
				);
			}
			// Fallback to regex parsing
			$content = $json_text;
		} else {
			throw new Exception( 'Invalid response from OpenAI Responses API. Please check your API key and try again.' );
		}
	} else {
		// Unknown provider
		throw new Exception( 'Unknown AI provider: ' . esc_html( $provider ) . '. Please select OpenAI, Anthropic, or Gemini.' );
	}

	// Parse the response
	$regex   = '/Title: (.+)\n\nContent: (.+)\n\nLink: (.+)\nLink Title: (.+)/s';
	$matches = preg_match( $regex, $content, $parts );

	if ( ! $matches ) {
		return array(
			'title'     => 'AI Generated Post',
			'content'   => $content,
			'link'      => '',
			'linkTitle' => '',
		);
	}

	return array(
		'title'     => trim( $parts[1] ),
		'content'   => trim( $parts[2] ),
		'link'      => trim( $parts[3] ),
		'linkTitle' => trim( $parts[4] ),
	);
}


/**
 * Get available AI models for all providers
 *
 * @return array Array of models grouped by provider
 */
function saiap_get_ai_models() {
	// Fallback bundled list used when API is unavailable
	$fallback = array(
		'openai'    => array(
			'gpt-5.4'      => 'GPT-5.4',
			'gpt-5.4-mini' => 'GPT-5.4 Mini',
			'gpt-5.2'      => 'GPT-5.2',
			'gpt-5.1'      => 'GPT-5.1',
			'gpt-4.1'      => 'GPT-4.1',
			'gpt-4.1-mini' => 'GPT-4.1 Mini',
			'gpt-4o'       => 'GPT-4o',
			'o4-mini'      => 'o4 Mini',
			'o3'           => 'o3',
		),
		'anthropic' => array(
			'claude-opus-4-7'   => 'Claude Opus 4.7',
			'claude-opus-4-6'   => 'Claude Opus 4.6',
			'claude-sonnet-4-5' => 'Claude Sonnet 4.5',
			'claude-haiku-4-5'  => 'Claude Haiku 4.5',
		),
		'gemini'    => array(
			'gemini-3.1-pro-preview' => 'Gemini 3.1 Pro',
			'gemini-3-pro-preview'   => 'Gemini 3 Pro',
			'gemini-3-flash-preview' => 'Gemini 3 Flash',
			'gemini-2.5-pro'         => 'Gemini 2.5 Pro',
			'gemini-2.5-flash'       => 'Gemini 2.5 Flash',
			'gemini-2.5-flash-lite'  => 'Gemini 2.5 Flash Lite',
		),
	);

	// Fetch from models endpoint (no caching for now)
	$response = wp_remote_get(
		'https://saiap.gopurposego.com/api/models',
		array(
			'timeout' => 15,
			'headers' => array(
				'Accept' => 'application/json',
			),
		)
	);

	if ( is_wp_error( $response ) ) {
		return $fallback;
	}

	$code = wp_remote_retrieve_response_code( $response );
	if ( $code !== 200 ) {
		return $fallback;
	}

	$body = wp_remote_retrieve_body( $response );
	$data = json_decode( $body, true );
	if ( ! is_array( $data ) || empty( $data['providers'] ) ) {
		return $fallback;
	}

	$mapped = array();
	foreach ( $data['providers'] as $provider => $provider_data ) {
		if ( empty( $provider_data['models'] ) || ! is_array( $provider_data['models'] ) ) {
			continue;
		}
		foreach ( $provider_data['models'] as $model ) {
			$mapped[ $provider ][ $model['id'] ] = isset( $model['name'] ) ? $model['name'] : $model['id'];
		}
	}

	return ! empty( $mapped ) ? $mapped : $fallback;
}

/**
 * AJAX: Fetch models list
 */
function saiap_ajax_models_list() {
	check_ajax_referer( 'saiap_update_context', 'nonce' );
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_send_json_error( 'Insufficient permissions' );
	}

	$response = wp_remote_get(
		'https://saiap.gopurposego.com/api/models',
		array(
			'timeout' => 30,
			'headers' => array( 'Accept' => 'application/json' ),
		)
	);

	if ( is_wp_error( $response ) ) {
		wp_send_json_error( 'Error: ' . $response->get_error_message() );
	}

	$code = wp_remote_retrieve_response_code( $response );
	$body = json_decode( wp_remote_retrieve_body( $response ), true );

	if ( 200 !== $code ) {
		wp_send_json_error( $body && isset( $body['error'] ) ? $body['error'] : 'HTTP ' . $code );
	}

	wp_send_json_success( $body );
}
add_action( 'wp_ajax_saiap_models_list', 'saiap_ajax_models_list' );

/**
 * Cron callback to refresh the models registry transient in the background.
 */
function saiap_cron_refresh_models_registry() {
	$response = wp_remote_get(
		'https://saiap.gopurposego.com/api/models',
		array(
			'timeout' => 15,
			'headers' => array( 'Accept' => 'application/json' ),
		)
	);

	if ( is_wp_error( $response ) ) {
		// Backoff retry in 3 hours
		wp_schedule_single_event( time() + 3 * HOUR_IN_SECONDS, 'saiap_refresh_models_registry_event' );
		return;
	}

	$code = wp_remote_retrieve_response_code( $response );
	if ( $code !== 200 ) {
		wp_schedule_single_event( time() + 6 * HOUR_IN_SECONDS, 'saiap_refresh_models_registry_event' );
		return;
	}

	$body = wp_remote_retrieve_body( $response );
	$data = json_decode( $body, true );
	if ( ! is_array( $data ) || empty( $data['providers'] ) ) {
		return;
	}

	$ttl = 6 * HOUR_IN_SECONDS;
	if ( isset( $data['ttlSeconds'] ) && is_numeric( $data['ttlSeconds'] ) ) {
		$ttl = max( MINUTE_IN_SECONDS, min( DAY_IN_SECONDS, intval( $data['ttlSeconds'] ) ) );
	}
	set_transient( 'saiap_models_registry_v1', $data, $ttl );
}
add_action( 'saiap_refresh_models_registry_event', 'saiap_cron_refresh_models_registry' );