<?php
/**
 * This file is reponsible for the admin dashboard.
 *
 * @package Webdigit
 */

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

/**
 * This is required to generate custom tooltips.
 */
require_once WD_CHATBOT_PATH . 'includes/summaries/class-wdgpt-custom-tooltip.php';


use Orhanerday\OpenAi\OpenAi;

/**
 * Checks if the OpenAI API key is valid.
 *
 * @param string $openai_key The OpenAI API key to validate. Optional.
 *
 * @return array An array with the message, the color of the message, and optionally available models IDs.
 */
function wdpgt_is_valid_api_key( $openai_key = '' ) {
	if ( empty( $openai_key ) ) {
		$openai_key = get_option( 'wd_openai_api_key', '' );
	}

	if ( ! $openai_key ) {
		return array(
			'message'            => __( 'Please enter your API key!', 'webdigit-chatbot' ),
			'color'              => 'orange',
			'is_valid'           => false,
			'availableModelsIds' => array(),
		);
	}

	// Modèles Chat Completions supportés - voir https://platform.openai.com/docs/models
	$models_to_check      = array(
		'gpt-3.5-turbo',
		'gpt-4o',
		'gpt-4o-mini',
		'gpt-4.1',
		'gpt-4.1-mini',
		'gpt-4.1-nano',
		'gpt-5-mini',
		'gpt-5-nano',
		'gpt-5.4',
		'gpt-5',
		'o4-mini',
		'o3-mini',
		'o3',
	);
	$available_models_ids = array();

	try {
		// Utilisation de wp_remote_get au lieu du SDK pour la validation directe
		$api_url = 'https://api.openai.com/v1/models';
		$headers = array(
			'Authorization' => 'Bearer ' . $openai_key,
			'Content-Type'  => 'application/json',
		);

		$response = wp_remote_get(
			$api_url,
			array(
				'headers' => $headers,
				'timeout' => 10, // Timeout en secondes
			)
		);

		if ( is_wp_error( $response ) ) {
			return array(
				'message'            => __( 'Error connecting to OpenAI API: ', 'webdigit-chatbot' ) . $response->get_error_message(),
				'color'              => 'red',
				'is_valid'           => false,
				'availableModelsIds' => array(),
			);
		}

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

		if ( 200 !== $http_code ) {
			$error_message = isset( $data['error']['message'] ) ? $data['error']['message'] : __( 'Unknown error.', 'webdigit-chatbot' );
			return array(
				'message'            => __( 'Your API key is invalid! If you think this is a mistake, please check your account on the OpenAI platform.', 'webdigit-chatbot' ) . ' ' . $error_message,
				'color'              => 'red',
				'is_valid'           => false,
				'availableModelsIds' => array(),
			);
		}

		// Si la requête réussit (code 200), extraire les IDs des modèles disponibles.
		// L'API peut retourner des IDs versionnés (ex: gpt-4o-2024-05-13) - on matche par préfixe.
		if ( isset( $data['data'] ) && is_array( $data['data'] ) ) {
			$available_models_ids = array();
			foreach ( $data['data'] as $model ) {
				if ( ! isset( $model['id'] ) ) {
					continue;
				}
				$api_model_id = $model['id'];
				foreach ( $models_to_check as $base_model ) {
					if ( $api_model_id === $base_model || strpos( $api_model_id, $base_model . '-' ) === 0 ) {
						$available_models_ids[] = $base_model;
						break;
					}
				}
			}
			$available_models_ids = array_unique( $available_models_ids );
		}

		if ( empty( $available_models_ids ) ) {
			return array(
				'message'            => __( 'Your API key is valid, but no supported models were found. Please check your OpenAI plan.', 'webdigit-chatbot' ),
				'color'              => 'orange',
				'is_valid'           => false,
				'availableModelsIds' => array(),
			);
		}

		return array(
			'message'            => __( 'Your API key is valid!', 'webdigit-chatbot' ),
			'color'              => 'green',
			'is_valid'           => true,
			'availableModelsIds' => $available_models_ids,
		);

	} catch ( Exception $e ) {
		return array(
			'message'            => __( 'An error occurred while contacting OpenAI: ' . $e->getMessage(), 'webdigit-chatbot' ),
			'color'              => 'red',
			'is_valid'           => false,
			'availableModelsIds' => array(),
		);
	}
}

/**
 * Return the max_tokens value sent to the API for a given model.
 * Single source of truth for internal token limits per model.
 * Reasoning models need ~25K to allow reasoning tokens + visible output (OpenAI recommendation).
 *
 * @param string $model The model ID (e.g. gpt-5, gpt-4o, o3).
 * @return int The max_tokens value to use for API calls.
 */
function wdgpt_get_max_tokens_for_model( $model ) {
	if ( wdgpt_is_reasoning_model( $model ) ) {
		return 25000;
	}
	$large_context_models = array(
		'gpt-4o', 'gpt-4o-mini', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
	);
	if ( in_array( $model, $large_context_models, true ) ) {
		return 3000;
	}
	return 1000;
}

/**
 * Check if the model is a reasoning model (gpt-5, o3, o4-mini, etc.).
 *
 * @param string $model The model ID.
 * @return bool True if reasoning model.
 */
function wdgpt_is_reasoning_model( $model ) {
	$reasoning_models = array(
		'gpt-5', 'gpt-5.4', 'gpt-5-mini', 'gpt-5-nano',
		'o3', 'o3-mini', 'o4-mini',
	);
	return in_array( $model, $reasoning_models, true );
}

/**
 * Format a token count for display (e.g. 25000 -> "25K").
 *
 * @param int $tokens The token count.
 * @return string Human-readable format.
 */
function wdgpt_format_tokens_for_display( $tokens ) {
	if ( $tokens >= 1000 ) {
		return ( $tokens / 1000 ) . 'K';
	}
	return (string) $tokens;
}

/**
 * Return the characteristics of each supported ChatGPT model for display in the settings.
 * Data source: https://platform.openai.com/docs/models
 * Recommendation/Warning: OpenAI docs, community best practices for chatbot vs reasoning use cases.
 *
 * @return array<string, array{context: string, max_output: string, max_tokens_used: string, type: string, description: string, recommendation: string, warning: string, cost_level: string, ideal_for_chatbot: bool}>
 */
function wdgpt_get_model_characteristics() {
	$models = array(
		'gpt-3.5-turbo'   => array(
			'context'            => '16K',
			'max_output'         => '4K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Legacy model, economical for simple tasks', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: very low cost, simple Q&A. Best for high-volume basic queries.', 'webdigit-chatbot' ),
			'warning'            => __( 'Lower quality than newer models. Consider gpt-4o-mini for better results at similar cost.', 'webdigit-chatbot' ),
			'cost_level'         => 'low',
			'ideal_for_chatbot'  => true,
		),
		'gpt-4o-mini'     => array(
			'context'            => '128K',
			'max_output'         => '16K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Fast, affordable for focused tasks', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: fast responses, low cost, good balance of quality and speed.', 'webdigit-chatbot' ),
			'warning'            => '',
			'cost_level'         => 'low',
			'ideal_for_chatbot'  => true,
		),
		'gpt-4.1-nano'    => array(
			'context'            => '128K',
			'max_output'         => '16K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Fastest, most cost-efficient GPT-4.1', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: fastest responses, very low cost, large context.', 'webdigit-chatbot' ),
			'warning'            => '',
			'cost_level'         => 'low',
			'ideal_for_chatbot'  => true,
		),
		'gpt-4.1-mini'    => array(
			'context'            => '128K',
			'max_output'         => '16K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Smaller, faster version of GPT-4.1', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: fast, smart, cost-effective.', 'webdigit-chatbot' ),
			'warning'            => '',
			'cost_level'         => 'low',
			'ideal_for_chatbot'  => true,
		),
		'gpt-4o'          => array(
			'context'            => '128K',
			'max_output'         => '16K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Fast, intelligent, flexible', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: lowest latency, best conversational quality. Recommended for real-time assistants.', 'webdigit-chatbot' ),
			'warning'            => '',
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => true,
		),
		'gpt-4.1'         => array(
			'context'            => '128K',
			'max_output'         => '16K',
			'type'               => __( 'Chat', 'webdigit-chatbot' ),
			'description'        => __( 'Smartest non-reasoning model', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Ideal for chatbot: best non-reasoning intelligence, 1M context. Suited for complex document Q&A.', 'webdigit-chatbot' ),
			'warning'            => __( 'Higher cost and slower than gpt-4o for simple conversational tasks.', 'webdigit-chatbot' ),
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => true,
		),
		'gpt-5-nano'      => array(
			'context'            => '400K',
			'max_output'         => '128K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Fastest, most cost-efficient GPT-5', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for reasoning tasks: math, coding, multi-step logic. Fastest among reasoning models.', 'webdigit-chatbot' ),
			'warning'            => __( 'Less suitable for simple chatbot: longer latency, higher cost. Prefer gpt-4o for conversational Q&A.', 'webdigit-chatbot' ),
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => false,
		),
		'gpt-5-mini'      => array(
			'context'            => '400K',
			'max_output'         => '128K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Near-frontier, cost-sensitive workloads', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for complex reasoning: coding, analytics, difficult tasks. Cost-efficient for reasoning workloads.', 'webdigit-chatbot' ),
			'warning'            => __( 'Less suitable for simple chatbot: longer reasoning time, higher cost than chat models.', 'webdigit-chatbot' ),
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => false,
		),
		'o4-mini'         => array(
			'context'            => '400K',
			'max_output'         => '128K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Fast, cost-efficient reasoning', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for reasoning: math, STEM, data science. Fastest o-series model.', 'webdigit-chatbot' ),
			'warning'            => __( 'Less suitable for simple chatbot: reasoning latency (30–60s), can be verbose or off-topic on simple questions.', 'webdigit-chatbot' ),
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => false,
		),
		'o3-mini'         => array(
			'context'            => '200K',
			'max_output'         => '100K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Small reasoning model', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for complex reasoning: math, coding, multi-step logic.', 'webdigit-chatbot' ),
			'warning'            => __( 'Less suitable for simple chatbot: longer latency, higher cost, may over-explain simple answers.', 'webdigit-chatbot' ),
			'cost_level'         => 'medium',
			'ideal_for_chatbot'  => false,
		),
		'gpt-5'           => array(
			'context'            => '400K',
			'max_output'         => '128K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Intelligent reasoning, coding, agentic tasks', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for agentic tasks: coding, tools, complex workflows. Best for difficult reasoning.', 'webdigit-chatbot' ),
			'warning'            => __( 'Not ideal for chatbot: long reasoning (30–120s), high cost, risk of verbose or off-topic answers on simple questions.', 'webdigit-chatbot' ),
			'cost_level'         => 'high',
			'ideal_for_chatbot'  => false,
		),
		'o3'               => array(
			'context'            => '200K',
			'max_output'         => '100K',
			'type'               => __( 'Reasoning', 'webdigit-chatbot' ),
			'description'        => __( 'Reasoning for complex tasks', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for complex reasoning: math, science, coding, visual reasoning. Frontier reasoning model.', 'webdigit-chatbot' ),
			'warning'            => __( 'Not ideal for chatbot: long reasoning (30–120s), high cost. May produce overly detailed or tangential responses.', 'webdigit-chatbot' ),
			'cost_level'         => 'high',
			'ideal_for_chatbot'  => false,
		),
		'gpt-5.4'         => array(
			'context'            => '1M',
			'max_output'         => '128K',
			'type'               => __( 'Frontier', 'webdigit-chatbot' ),
			'description'        => __( 'Best intelligence for agentic, coding, professional work', 'webdigit-chatbot' ),
			'recommendation'     => __( 'Suited for agentic workflows: coding, research, professional tools. Highest intelligence available.', 'webdigit-chatbot' ),
			'warning'            => __( 'Not ideal for chatbot: highest cost, long latency. Overkill for simple Q&A; prefer gpt-4o or gpt-4.1.', 'webdigit-chatbot' ),
			'cost_level'         => 'high',
			'ideal_for_chatbot'  => false,
		),
	);

	// Ajouter max_tokens_used (limite utilisée par le plugin) pour chaque modèle.
	foreach ( array_keys( $models ) as $model_id ) {
		$models[ $model_id ]['max_tokens_used'] = wdgpt_format_tokens_for_display( wdgpt_get_max_tokens_for_model( $model_id ) );
		// Libellé du coût pour l'affichage.
		$models[ $model_id ]['cost_label'] = wdgpt_get_cost_level_label( $models[ $model_id ]['cost_level'] );
	}

	return $models;
}

/**
 * Return the translatable label for a cost level.
 *
 * @param string $level 'low', 'medium', or 'high'.
 * @return string Translated label.
 */
function wdgpt_get_cost_level_label( $level ) {
	$labels = array(
		'low'    => __( 'Low', 'webdigit-chatbot' ),
		'medium' => __( 'Medium', 'webdigit-chatbot' ),
		'high'   => __( 'High', 'webdigit-chatbot' ),
	);
	return isset( $labels[ $level ] ) ? $labels[ $level ] : $level;
}

/**
 * Return model IDs ordered with "ideal for chatbot" models first.
 *
 * @return array Ordered model IDs.
 */
function wdgpt_get_models_ordered_for_chatbot() {
	$chars  = wdgpt_get_model_characteristics();
	$ideal  = array();
	$other  = array();
	foreach ( array_keys( $chars ) as $model_id ) {
		if ( ! empty( $chars[ $model_id ]['ideal_for_chatbot'] ) ) {
			$ideal[] = $model_id;
		} else {
			$other[] = $model_id;
		}
	}
	return array_merge( $ideal, $other );
}

/**
 * Return the Chat Completions API parameters specific to each model.
 * Based on: https://platform.openai.com/docs/guides/reasoning
 *           https://platform.openai.com/docs/guides/latest-model
 *
 * @param string $model The model ID (e.g. gpt-5, gpt-4o, o3).
 * @return array<string, mixed> Extra parameters to merge into the chat request.
 */
function wdgpt_get_chat_params_for_model( $model ) {
	$params = array();

	// max_tokens centralisé (une seule source de vérité).
	$params['max_tokens'] = wdgpt_get_max_tokens_for_model( $model );

	// Modèles reasoning : nécessitent reasoning_effort.
	// GPT-5.4+ : supporte "none" (latence minimale). GPT-5, o3 : minimal/low/medium/high.
	// Doc: https://platform.openai.com/docs/guides/reasoning
	$reasoning_models = array(
		'gpt-5'      => 'minimal', // gpt-5 : minimal, low, medium, high.
		'gpt-5.4'    => 'none',    // gpt-5.4+ : none, low, medium, high, xhigh.
		'gpt-5-mini' => 'none',
		'gpt-5-nano' => 'none',
		'o3'         => 'low',    // o3 : low, medium, high.
		'o3-mini'    => 'low',
		'o4-mini'    => 'low',
	);

	if ( isset( $reasoning_models[ $model ] ) ) {
		$params['reasoning_effort'] = $reasoning_models[ $model ];
	}

	// Modèles GPT-5.4+ : verbosity pour des réponses plus concises (adapté au chatbot).
	// Doc: https://platform.openai.com/docs/guides/latest-model
	$verbosity_models = array( 'gpt-5.4', 'gpt-5-mini', 'gpt-5-nano' );
	if ( in_array( $model, $verbosity_models, true ) ) {
		$params['verbosity'] = 'low';
	}

	// o3 et o4-mini ne supportent pas le paramètre stop - on ne l'ajoute jamais.
	// Les modèles standard peuvent utiliser stop mais nous ne l'utilisons pas actuellement.

	return $params;
}

/**
 * Get the models that are available with the current api key.
 *
 * @param array $available_models The models that are available.
 */
function wdpgt_get_models( $available_models ) {
	$openai_api_key = get_option( 'wd_openai_api_key', '' );
	if ( ! $openai_api_key ) {
		return array();
	}
	try {
		$openai_client = new OpenAI( $openai_api_key );
		$response      = $openai_client->listModels();
		if ( $response === false ) {
			return array();
		}
		$models = json_decode( $response, true );
		if ( isset( $models['error'] ) || ! isset( $models['data'] ) ) {
			return array();
		}
	} catch ( \Exception $e ) {
		// Log error but don't crash the admin page
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			error_log( 'SmartSearchWP: Error getting models - ' . $e->getMessage() );
		}
		return array();
	}
	// Filtrer les modèles API qui correspondent à notre liste (exact ou préfixe pour les versions).
	// Normaliser vers les IDs de base pour la cohérence avec le select.
	$normalized = array();
	foreach ( $models['data'] as $model ) {
		if ( ! isset( $model['id'] ) ) {
			continue;
		}
		$api_id = $model['id'];
		foreach ( $available_models as $base_id ) {
			if ( $api_id === $base_id || strpos( $api_id, $base_id . '-' ) === 0 ) {
				$normalized[ $base_id ] = array_merge( $model, array( 'id' => $base_id ) );
				break;
			}
		}
	}
	return array_values( $normalized );
}

/**
 * Show an admin notice to rate the plugin.
 */
function wdgpt_show_admin_notice_rate_us() {
	?>
		<div id="wdgpt-rate-us-notice" class="notice notice-info">
			<p>
				<?php

				esc_html_e(
					'If you like this plugin, please leave us a review to help us grow. Thank you!',
					'webdigit-chatbot'
				);
				?>
			</p>
			<p>
				<a href="https://wordpress.org/support/plugin/smartsearchwp/reviews/#new-post" target="_blank">
					<?php
					esc_html_e(
						'Leave a review',
						'webdigit-chatbot'
					);
					?>
				</a>&nbsp;
				<a href="#" id="wdgpt_rate_us_no_thanks">
				<?php
					esc_html_e(
						'No, thanks',
						'webdigit-chatbot'
					);
				?>
				</a>&nbsp;
				<a href="#" id="wdgpt_rate_us_done">
				<?php
					esc_html_e(
						'Already rated',
						'webdigit-chatbot'
					);
				?>
				</a>&nbsp;
				<a href="#" id="wdgpt_remind_me_later">
				<?php
					esc_html_e(
						'Remind me later',
						'webdigit-chatbot'
					);
				?>
				</a>
			</p>
		</div>
		<?php
}



/**
 * Generate the admin dashboard.
 */
function wdgpt_config_form() {
	// $active_tab = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_STRING );
	$active_tab = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_SPECIAL_CHARS );
	$active_tab = $active_tab ? $active_tab : 'wdgpt_settings';
	?>
	<div class="wrap">
		<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
		<?php
		wdgpt_show_admin_notice_rate_us();
		?>

		<h2 class="nav-tab-wrapper">
			<a href="?page=wdgpt&tab=wdgpt_settings" class="nav-tab <?php echo 'wdgpt_settings' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'General Settings', 'webdigit-chatbot' ); ?></a>
			<a href="?page=wdgpt&tab=wdgpt_reporting" class="nav-tab <?php echo 'wdgpt_reporting' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'Reporting', 'webdigit-chatbot' ); ?></a>
			<?php
				$current_version  = wdgpt_chatbot()->get_version();
				$database_updater = new WDGPT_Database_Updater( $current_version );
				$pending_updates  = $database_updater->check_for_updates();
			if ( ! empty( $pending_updates ) ) {
				?>
						<a href="?page=wdgpt&tab=wdgpt_db_update" class="nav-tab <?php echo 'wdgpt_db_update' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'Database Update', 'webdigit-chatbot' ); ?></a>
					<?php
			}
			?>
		</h2>

		<form method="post" enctype="multipart/form-data">
		<?php
		switch ( $active_tab ) {
			case 'wdgpt_settings':
				settings_fields( 'wdgpt_settings' );
				do_settings_sections( 'wdgpt_settings' );
				break;
			case 'wdgpt_reporting':
				settings_fields( 'wdgpt_reporting' );
				do_settings_sections( 'wdgpt_reporting' );
				break;
			case 'wdgpt_db_update':
				settings_fields( 'wdgpt_database_update' );
				do_settings_sections( 'wdgpt_database_update' );
				break;
			default:
				settings_fields( 'wdgpt_settings' );
				do_settings_sections( 'wdgpt_settings' );
				break;
		}
		?>
		</form>
	</div>
	<script>
		function updateImage(event) {
			const file = event.target.files[0];
			const reader = new FileReader();
			reader.onload = function(event) {
			const img = document.getElementById('pluginimg');
			img.src = event.target.result;
			const filenameInput = document.getElementById('wdgpt_image_name');
			filenameInput.value = file.name;
			}
			reader.readAsDataURL(file);
		}
	</script>
	<?php
}

/**
 * Add enctype to form
 */
function wdgpt_post_edit_form_tag() {
	echo ' enctype="multipart/form-data"';
}
add_action( 'post_edit_form_tag', 'wdgpt_post_edit_form_tag' );

?>
