<?php
/**
 * OpenAI Provider Class
 *
 * Integration with OpenAI API
 *
 * @package SmartyPress_AI_Engine
 * @since 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * OpenAI Provider class
 */
class SmartyPress_AI_OpenAI_Provider extends SmartyPress_AI_AI_Provider {

	/**
	 * Constructor
	 *
	 * @param string $api_key API key.
	 * @param string $model Model name.
	 */
	public function __construct( $api_key, $model = 'gpt-4o' ) {
		parent::__construct( $api_key, $model );
		$this->api_endpoint = 'https://api.openai.com/v1/chat/completions';
	}

	/**
	 * Get token parameter name based on model
	 *
	 * @param string $model Model name.
	 * @return string Token parameter name.
	 */
	private function get_token_param_name( $model ) {
		// New models use max_completion_tokens
		$new_models = array( 'gpt-5.5', 'gpt-5.3', 'gpt-5.2', 'gpt-5.1', 'gpt-5', 'gpt-4.1', 'o3', 'o3-mini', 'o1', 'o1-mini', 'o1-preview' );

		foreach ( $new_models as $new_model ) {
			if ( stripos( $model, $new_model ) !== false ) {
				return 'max_completion_tokens';
			}
		}

		return 'max_tokens';
	}

	/**
	 * Generate content using OpenAI
	 *
	 * @param string $prompt The prompt to send to AI.
	 * @param array  $params Additional parameters.
	 * @return array Response with content or error.
	 */
	public function generate_content( $prompt, $params = array() ) {
		$system_prompt = $params['system_prompt'] ?? __( 'You are a helpful assistant for content generation.', 'smartypress-ai-engine' );
		$messages      = $this->build_messages( $system_prompt, $prompt );

		$model = ! empty( $params['model'] ) ? $params['model'] : $this->model;
		$token_param = $this->get_token_param_name( $model );

		$api_params = array(
			'model'       => $model,
			'messages'    => $messages,
			'temperature' => $params['temperature'] ?? 0.7,
			$token_param  => $params['max_tokens'] ?? 2000,
		);

		if ( ! empty( $params['response_format'] ) && is_array( $params['response_format'] ) ) {
			$api_params['response_format'] = $params['response_format'];
		}

		if ( ! empty( $params['request_timeout'] ) ) {
			$api_params['request_timeout'] = absint( $params['request_timeout'] );
		}

		return $this->make_request( $messages, $api_params );
	}

	/**
	 * Validate API key
	 *
	 * @return bool True if valid, false otherwise.
	 */
	public function validate_api_key() {
		$messages = $this->build_messages(
			__( 'You are a helpful assistant.', 'smartypress-ai-engine' ),
			__( 'Say "Hello"', 'smartypress-ai-engine' )
		);

		$token_param = $this->get_token_param_name( $this->model );
		$result = $this->make_request( $messages, array( $token_param => 10 ) );

		return $result['success'] ?? false;
	}

	/**
	 * Generate image using OpenAI Images API
	 *
	 * Supports gpt-image-1, dall-e-3, and dall-e-3-hd models.
	 *
	 * @param string $prompt Image generation prompt.
	 * @param array  $params Additional parameters (model, resolution).
	 * @return array Response with image URL/b64 or error.
	 */
	public function generate_image( $prompt, $params = array() ) {
		$model      = $params['model'] ?? 'gpt-image-1';
		$resolution = $params['resolution'] ?? '1024x1024';
		$endpoint   = 'https://api.openai.com/v1/images/generations';

		$body = array(
			'prompt' => $prompt,
			'n'      => 1,
			'size'   => $resolution,
		);

		if ( strpos( $model, 'gpt-image' ) === 0 ) {
			// GPT Image models (token-based pricing).
			$body['model']      = $model;
			$body['quality']    = 'high';
			$body['moderation'] = 'low';
		} else {
			// DALL-E models (per-image pricing).
			$body['response_format'] = 'b64_json';

			if ( 'dall-e-3-hd' === $model ) {
				$body['model']   = 'dall-e-3';
				$body['quality'] = 'hd';
			} elseif ( 'dall-e-3' === $model ) {
				$body['model'] = 'dall-e-3';
			}
		}

		$result = $this->make_api_request( $endpoint, $body, 120 );

		if ( ! $result['success'] ) {
			return $result;
		}

		$data       = $result['data'];
		$image_data = $data['data'][0] ?? null;

		if ( ! $image_data ) {
			return array(
				'success' => false,
				'error'   => __( 'No image data in API response.', 'smartypress-ai-engine' ),
			);
		}

		// Extract image URL or b64 data.
		$image_url = $image_data['url'] ?? '';
		$image_b64 = $image_data['b64_json'] ?? '';

		if ( empty( $image_url ) && empty( $image_b64 ) ) {
			return array(
				'success' => false,
				'error'   => __( 'No image URL or data in API response.', 'smartypress-ai-engine' ),
			);
		}

		return array(
			'success'   => true,
			'url'       => $image_url,
			'b64_json'  => $image_b64,
			'model'     => $model,
			'usage'     => $data['usage'] ?? array(),
		);
	}

	/**
	 * Edit image using OpenAI Images Edits API
	 *
	 * Supports gpt-image-1 and gpt-image-1.5 models. Uses multipart/form-data.
	 *
	 * @param string $image_path Path to the image file.
	 * @param string $prompt     Edit instruction prompt.
	 * @param array  $params     Additional parameters (model, size).
	 * @return array Response with b64_json or error.
	 */
	public function edit_image( $image_path, $prompt, $params = array() ) {
		if ( ! file_exists( $image_path ) || ! is_readable( $image_path ) ) {
			return array(
				'success' => false,
				'error'   => __( 'Image file not found or not readable.', 'smartypress-ai-engine' ),
			);
		}

		$model      = $params['model'] ?? 'gpt-image-1';
		$resolution = $params['size'] ?? $params['resolution'] ?? '1024x1024';
		$endpoint   = 'https://api.openai.com/v1/images/edits';

		// Only gpt-image models support the edits endpoint.
		if ( strpos( $model, 'gpt-image' ) !== 0 ) {
			return array(
				'success' => false,
				'error'   => __( 'Image edit is only supported for GPT Image models.', 'smartypress-ai-engine' ),
			);
		}

		$boundary = wp_generate_password( 24, false );
		$mime     = $this->detect_image_mime_type( $image_path );
		$filename = basename( $image_path );
		$content  = file_get_contents( $image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents

		if ( false === $content ) {
			return array(
				'success' => false,
				'error'   => __( 'Failed to read image file.', 'smartypress-ai-engine' ),
			);
		}

		$body = '--' . $boundary . "\r\n";
		$body .= 'Content-Disposition: form-data; name="image"; filename="' . $filename . '"' . "\r\n";
		$body .= 'Content-Type: ' . $mime . "\r\n\r\n";
		$body .= $content . "\r\n";
		$body .= '--' . $boundary . "\r\n";
		$body .= 'Content-Disposition: form-data; name="prompt"' . "\r\n\r\n";
		$body .= $prompt . "\r\n";
		$body .= '--' . $boundary . "\r\n";
		$body .= 'Content-Disposition: form-data; name="model"' . "\r\n\r\n";
		$body .= $model . "\r\n";
		$body .= '--' . $boundary . "\r\n";
		$body .= 'Content-Disposition: form-data; name="size"' . "\r\n\r\n";
		$body .= $resolution . "\r\n";
		$body .= '--' . $boundary . '--';

		$request_args = array(
			'headers' => array(
				'Content-Type'   => 'multipart/form-data; boundary=' . $boundary,
				'Authorization'  => 'Bearer ' . $this->api_key,
				'Content-Length'  => strlen( $body ),
			),
			'body'    => $body,
			'timeout' => 120,
		);

		$response = wp_remote_post( $endpoint, $request_args );

		if ( is_wp_error( $response ) ) {
			return array(
				'success' => false,
				'error'   => $response->get_error_message(),
			);
		}

		$response_code = wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );
		$data          = json_decode( $response_body, true );

		if ( 200 !== $response_code ) {
			$error_message = $data['error']['message'] ?? __( 'Unknown API error', 'smartypress-ai-engine' );
			return array(
				'success' => false,
				'error'   => $error_message,
			);
		}

		$image_data = $data['data'][0] ?? null;
		$image_b64  = $image_data['b64_json'] ?? '';

		if ( empty( $image_b64 ) ) {
			return array(
				'success' => false,
				'error'   => __( 'No image data in API response.', 'smartypress-ai-engine' ),
			);
		}

		$usage = $data['usage'] ?? array();

		// Record token usage for image edit calls.
		if ( class_exists( 'SmartyPress_AI_Token_Tracker' ) && ! empty( $usage ) ) {
			SmartyPress_AI_Token_Tracker::record( array(
				'provider' => $this->get_provider_name(),
				'model'    => $model,
				'usage'    => $usage,
			) );
		}

		return array(
			'success'  => true,
			'b64_json' => $image_b64,
			'model'    => $model,
			'usage'    => $usage,
		);
	}

	/**
	 * Describe image using vision model (GPT-4o)
	 *
	 * Used for DALL-E regenerate: describe the image so it can be re-generated.
	 *
	 * @param string $image_path Path to the image file.
	 * @return array Response with content (description) or error.
	 */
	public function describe_image( $image_path ) {
		if ( ! file_exists( $image_path ) || ! is_readable( $image_path ) ) {
			return array(
				'success' => false,
				'error'   => __( 'Image file not found or not readable.', 'smartypress-ai-engine' ),
			);
		}

		$image_data = file_get_contents( $image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		if ( false === $image_data ) {
			return array(
				'success' => false,
				'error'   => __( 'Failed to read image file.', 'smartypress-ai-engine' ),
			);
		}

		$base64 = base64_encode( $image_data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
		$mime   = $this->detect_image_mime_type( $image_path );

		$messages = array(
			array(
				'role'    => 'system',
				'content' => __( 'Describe this image in detail for another AI to recreate it. Include composition, colors, style, subjects, and any text visible. Be thorough but concise. Respond in the same language as the user prompt.', 'smartypress-ai-engine' ),
			),
			array(
				'role'    => 'user',
				'content' => array(
					array(
						'type'      => 'text',
						'text'      => __( 'Describe this image in detail so it can be recreated.', 'smartypress-ai-engine' ),
					),
					array(
						'type'      => 'image_url',
						'image_url' => array(
							'url' => 'data:' . $mime . ';base64,' . $base64,
						),
					),
				),
			),
		);

		$api_params = array(
			'model'       => 'gpt-4o',
			'messages'    => $messages,
			'max_tokens'  => 500,
		);

		return $this->make_request( $messages, $api_params );
	}

	/**
	 * Describe image with a custom vision prompt.
	 *
	 * Used by Image ALT generation to create JSON metadata from the actual image.
	 *
	 * @param string $image_path Path to the image file.
	 * @param string $prompt     Prompt for the vision model.
	 * @param array  $params     Additional params.
	 * @return array Response with content or error.
	 */
	public function describe_image_with_prompt( $image_path, $prompt, $params = array() ) {
		if ( ! file_exists( $image_path ) || ! is_readable( $image_path ) ) {
			return array(
				'success' => false,
				'error'   => __( 'Image file not found or not readable.', 'smartypress-ai-engine' ),
			);
		}

		$image_data = file_get_contents( $image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		if ( false === $image_data ) {
			return array(
				'success' => false,
				'error'   => __( 'Failed to read image file.', 'smartypress-ai-engine' ),
			);
		}

		$base64 = base64_encode( $image_data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
		$mime   = $this->detect_image_mime_type( $image_path );
		$model  = ! empty( $params['model'] ) ? $params['model'] : 'gpt-4o';

		$messages = array(
			array(
				'role'    => 'system',
				'content' => __( 'You generate accurate WordPress image metadata from visual content and SEO context.', 'smartypress-ai-engine' ),
			),
			array(
				'role'    => 'user',
				'content' => array(
					array(
						'type' => 'text',
						'text' => $prompt,
					),
					array(
						'type'      => 'image_url',
						'image_url' => array(
							'url' => 'data:' . $mime . ';base64,' . $base64,
						),
					),
				),
			),
		);

		$token_param = $this->get_token_param_name( $model );
		$api_params  = array(
			'model'       => $model,
			'messages'    => $messages,
			'temperature' => $params['temperature'] ?? 0.2,
			$token_param  => $params['max_tokens'] ?? 500,
		);

		return $this->make_request( $messages, $api_params );
	}

	/**
	 * Get available image generation models
	 *
	 * @return array List of image models with supported resolutions.
	 */
	public function get_available_image_models() {
		return SmartyPress_AI_Model_Map::get_image_models( 'openai' );
	}

	/**
	 * Get available image edit models
	 *
	 * @return array List of image edit models with supported resolutions.
	 */
	public function get_available_image_edit_models() {
		return SmartyPress_AI_Model_Map::get_image_edit_models( 'openai' );
	}

	/**
	 * Get available models
	 *
	 * @return array List of available models with metadata.
	 */
	public function get_available_models() {
		return SmartyPress_AI_Model_Map::get_text_models( 'openai' );
	}
}

