<?php
/**
 * Generator Class for WPStack AI ALT Genius
 * Handles API calls and data processing.
 */

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

class Aialtg_Generator {

	private $option_name = 'aialtg_settings';

	/**
	 * Process a single image.
	 *
	 * @param int         $post_id          Attachment ID.
	 * @param string      $source           Source of generation ('manual' or 'cron').
	 * @param string      $override_api_key Optional explicit API key.
	 * @param int|null    $key_index        Optional NVIDIA pool index for cron.
	 * @return array|WP_Error Result data.
	 */
	public function process_image( $post_id, $source = 'manual', $override_api_key = '', $key_index = null ) {
		$options  = get_option( $this->option_name );
		$options  = is_array( $options ) ? $options : array();
		$provider = isset( $options['provider'] ) ? $options['provider'] : 'openrouter';
		$api_key  = Aialtg_Helpers::resolve_api_key( $options, $override_api_key, $key_index );
		$model    = isset( $options['model'] ) && ! empty( $options['model'] ) ? $options['model'] : '';

		$enable_alt         = Aialtg_Helpers::is_enabled( $options, 'enable_alt', true );
		$enable_title       = Aialtg_Helpers::is_enabled( $options, 'enable_title', true );
		$enable_caption     = Aialtg_Helpers::is_enabled( $options, 'enable_caption', true );
		$enable_description = Aialtg_Helpers::is_enabled( $options, 'enable_description', true );

		if ( empty( $api_key ) ) {
			return new WP_Error( 'missing_key', __( 'API Key missing', AIALTG_TEXT_DOMAIN ) );
		}

		// Get Image URL.
		$image_url = wp_get_attachment_url( $post_id );

		// Fallback: Try getting it via image_src if direct url fails.
		if ( ! $image_url ) {
			$src = wp_get_attachment_image_src( $post_id, 'full' );
			if ( $src && isset( $src[0] ) ) {
				$image_url = $src[0];
			}
		}

		if ( ! $image_url ) {
			return new WP_Error( 'missing_url', __( 'Image URL not found', AIALTG_TEXT_DOMAIN ) );
		}

		// FIX: Ensure URL is properly encoded (e.g., spaces to %20) for the API.
		// OpenRouter/OpenAI will reject URLs with spaces.
		$image_url = str_replace( ' ', '%20', $image_url );

		// FIX: Ensure protocol is present (handle protocol-relative URLs like //example.com/img.jpg).
		if ( strpos( $image_url, '//' ) === 0 ) {
			$image_url = 'https:' . $image_url;
		}

		// Check Supported MIME Type.
		// We use the helper in Settings class if available, else standard image check.
		if ( class_exists( 'Aialtg_Settings' ) && method_exists( 'Aialtg_Settings', 'get_allowed_mimes' ) ) {
			$allowed_mimes = Aialtg_Settings::get_allowed_mimes();
			$current_mime  = get_post_mime_type( $post_id );

			// If allowed_mimes is just 'image', it allows all. If it's an array, we check.
			if ( is_array( $allowed_mimes ) && ! in_array( $current_mime, $allowed_mimes, true ) ) {
				/* translators: %s: MIME type (e.g. image/jpeg) */
				return new WP_Error( 'unsupported_format', sprintf( __( 'Format %s not supported in settings', AIALTG_TEXT_DOMAIN ), $current_mime ) );
			}
		}

		// Prepare Prompts.
		$default_alt_prompt = 'Generate a concise, descriptive alt text for this image. Do not use phrases like "Image of".';
		$alt_prompt         = isset( $options['prompt'] ) && ! empty( $options['prompt'] ) ? $options['prompt'] : $default_alt_prompt;

		$default_title_prompt = 'Generate a short, descriptive title for this image.';
		$title_prompt         = isset( $options['title_prompt'] ) && ! empty( $options['title_prompt'] ) ? $options['title_prompt'] : $default_title_prompt;

		$default_caption_prompt = 'Generate a 1-2 sentence caption providing supplementary context about this image beyond what alt text covers.';
		$caption_prompt         = isset( $options['caption_prompt'] ) && ! empty( $options['caption_prompt'] ) ? $options['caption_prompt'] : $default_caption_prompt;

		$default_description_prompt = 'Generate a detailed 2-4 sentence description of this image including background, setting, and relevant details for SEO.';
		$description_prompt         = isset( $options['description_prompt'] ) && ! empty( $options['description_prompt'] ) ? $options['description_prompt'] : $default_description_prompt;

		// Get Global Context.
		$global_context = isset( $options['global_context'] ) && ! empty( $options['global_context'] ) ? $options['global_context'] : '';

		// Context Replacement.
		$parent_title   = 'N/A';
		$parent_content = 'N/A';
		$attachment     = get_post( $post_id );

		if ( $attachment && $attachment->post_parent ) {
			$parent_post = get_post( $attachment->post_parent );
			if ( $parent_post ) {
				if ( ! empty( $parent_post->post_title ) ) {
					$parent_title = $parent_post->post_title;
				}
				if ( ! empty( $parent_post->post_content ) ) {
					// Use wp_strip_all_tags to clean content for the AI prompt.
					$parent_content = wp_strip_all_tags( $parent_post->post_content );
				}
			}
		}

		$replacements = array( $parent_title, $parent_content );
		$search_tags  = array( '{post_title}', '{post_content}' );

		// Apply replacements to all prompt fields.
		$global_context     = str_replace( $search_tags, $replacements, $global_context );
		$alt_prompt         = str_replace( $search_tags, $replacements, $alt_prompt );
		$title_prompt       = str_replace( $search_tags, $replacements, $title_prompt );
		$caption_prompt     = str_replace( $search_tags, $replacements, $caption_prompt );
		$description_prompt = str_replace( $search_tags, $replacements, $description_prompt );

		// Build System Instruction.
		$system_instructions = "Analyze the image and generate text based on the following instructions.\n";

		// Append Global Context if it exists.
		if ( ! empty( $global_context ) ) {
			$system_instructions .= "CONTEXT:\n" . $global_context . "\n\n";
		}

		$expected_keys = array();
		if ( $enable_alt ) {
			$system_instructions .= '1. Alt Text Prompt: ' . $alt_prompt . "\n";
			$expected_keys[]      = "'alt_text'";
		}
		if ( $enable_title ) {
			$system_instructions .= '2. Title Prompt: ' . $title_prompt . "\n";
			$expected_keys[]      = "'title'";
		}
		if ( $enable_caption ) {
			$system_instructions .= '3. Caption Prompt: ' . $caption_prompt . "\n";
			$expected_keys[]      = "'caption'";
		}
		if ( $enable_description ) {
			$system_instructions .= '4. Description Prompt: ' . $description_prompt . "\n";
			$expected_keys[]      = "'description'";
		}
		$system_instructions .= 'Return ONLY valid JSON with keys ' . implode( ' and ', $expected_keys ) . '.';

		// API Call — provider-aware.
		$providers  = Aialtg_Settings::get_providers();
		$default_model = isset( $providers[ $provider ]['default_model'] ) ? $providers[ $provider ]['default_model'] : 'google/gemini-2.5-flash-lite';
		if ( empty( $model ) ) {
			$model = $default_model;
		}
		if ( ! Aialtg_Helpers::model_supports_vision( $model, $provider ) ) {
			return new WP_Error(
				'not_vision_model',
				sprintf(
					/* translators: %s: model ID */
					__( 'The selected model "%s" does not support image analysis. Please select a vision-capable model (look for the 📷 icon in the model dropdown).', AIALTG_TEXT_DOMAIN ),
					esc_html( $model )
				)
			);
		}

		$base_url  = isset( $providers[ $provider ]['base_url'] ) ? $providers[ $provider ]['base_url'] : $providers['openrouter']['base_url'];

		$headers = array(
			'Authorization' => 'Bearer ' . $api_key,
			'Content-Type'  => 'application/json',
		);

		// OpenRouter-specific headers for analytics.
		if ( 'openrouter' === $provider ) {
			$headers['HTTP-Referer'] = add_query_arg( 'page', AIALTG_SLUG, get_site_url() );
			$headers['X-Title']      = get_bloginfo( 'name' );
		}

		// NVIDIA NIM uses nvcf-{key} format but standard Bearer auth.
		// All three providers use the same request body format.

		// Build request body.
		$request_body = array(
			'model'    => $model,
			'messages' => array(
				array(
					'role'    => 'user',
					'content' => array(
						array(
							'type' => 'text',
							'text' => $system_instructions,
						),
						array(
							'type'      => 'image_url',
							'image_url' => array( 'url' => $image_url ),
						),
					),
				),
			),
		);

		// response_format is supported by OpenRouter and OpenAI but not all NVIDIA models.
		if ( 'nvidia' !== $provider ) {
			$request_body['response_format'] = array( 'type' => 'json_object' );
		}

		$response = wp_remote_post(
			$base_url,
			array(
				'headers' => $headers,
				'body'    => wp_json_encode( $request_body ),
				'timeout' => 45,
			)
		);

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

		$response_code = wp_remote_retrieve_response_code( $response );
		if ( 200 !== $response_code ) {
			$body = wp_remote_retrieve_body( $response );
			$data = json_decode( $body, true );
			$err_msg = '';
			if ( is_array( $data ) && isset( $data['error']['message'] ) ) {
				$err_msg = $data['error']['message'];
			} else {
				$err_msg = wp_remote_retrieve_response_message( $response );
			}
			return new WP_Error( 'api_http_error', sprintf( __( 'API returned HTTP %d: %s', AIALTG_TEXT_DOMAIN ), $response_code, $err_msg ) );
		}

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

		if ( ! is_array( $data ) ) {
			return new WP_Error( 'invalid_json', __( 'Invalid response format from API', AIALTG_TEXT_DOMAIN ) );
		}

		if ( isset( $data['error'] ) ) {
			return new WP_Error( 'api_error', isset( $data['error']['message'] ) ? $data['error']['message'] : __( 'Unknown error', AIALTG_TEXT_DOMAIN ) );
		}

		if ( empty( $data['choices'][0]['message']['content'] ) ) {
			return new WP_Error( 'empty_response', __( 'Empty response from API', AIALTG_TEXT_DOMAIN ) );
		}

		// Parse Content.
		$content_str = trim( $data['choices'][0]['message']['content'] );
		$content_str = str_replace( array( '```json', '```' ), '', $content_str );
		$result_json = json_decode( $content_str, true );

		$alt_text    = '';
		$title       = '';
		$caption     = '';
		$description = '';

		if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $result_json ) ) {
			// Fallback.
			if ( $enable_alt ) {
				$alt_text = wp_strip_all_tags( $content_str );
			} elseif ( $enable_title ) {
				$title = wp_strip_all_tags( $content_str );
			} elseif ( $enable_caption ) {
				$caption = wp_strip_all_tags( $content_str );
			} elseif ( $enable_description ) {
				$description = wp_strip_all_tags( $content_str );
			}
		} else {
			if ( $enable_alt ) {
				$alt_text = isset( $result_json['alt_text'] ) ? wp_strip_all_tags( $result_json['alt_text'] ) : '';
			}
			if ( $enable_title ) {
				$title = isset( $result_json['title'] ) ? wp_strip_all_tags( $result_json['title'] ) : '';
			}
			if ( $enable_caption ) {
				$caption = isset( $result_json['caption'] ) ? wp_strip_all_tags( $result_json['caption'] ) : '';
			}
			if ( $enable_description ) {
				$description = isset( $result_json['description'] ) ? wp_strip_all_tags( $result_json['description'] ) : '';
			}
		}

		// Save Data.
		if ( $enable_alt && ! empty( $alt_text ) ) {
			update_post_meta( $post_id, '_wp_attachment_image_alt', $alt_text );
		}

		// Build post update array for title, caption, and description.
		$post_update = array( 'ID' => $post_id );
		if ( $enable_title && ! empty( $title ) ) {
			$post_update['post_title'] = $title;
		}
		if ( $enable_caption && ! empty( $caption ) ) {
			$post_update['post_excerpt'] = $caption;
		}
		if ( $enable_description && ! empty( $description ) ) {
			$post_update['post_content'] = $description;
		}
		if ( count( $post_update ) > 1 ) {
			wp_update_post( $post_update );
		}

		// Mark as processed by the plugin.
		update_post_meta( $post_id, '_aialtg_processed', '1' );

		// Save Generation Meta if enabled.
		if ( ! empty( $options['save_gen_meta'] ) ) {
			// Use gmdate() instead of date() to avoid timezone issues.
			update_post_meta( $post_id, '_aialtg_gen_date', gmdate( 'Y-m-d H:i:s' ) );
			update_post_meta( $post_id, '_aialtg_gen_source', sanitize_text_field( $source ) );
		}

		// Cleanup any previous error log since it succeeded this time.
		delete_post_meta( $post_id, '_aialtg_error_log' );

		return array(
			'alt_text'    => $alt_text,
			'title'       => $title,
			'caption'     => $caption,
			'description' => $description,
		);
	}
}